GCC内联汇编

来源:互联网 发布:java软件编程 编辑:程序博客网 时间:2024/05/12 23:51

一.基本内联汇编的格式是:
__asm__ __volatile__("Instruction List");

1. __asm__
__asm__是GCC 关键字asm 的宏定义:
#define __asm__ asm
__asm__或asm 用来声明一个内联汇编表达式,所以任何一个内联汇编表达式都是以它开头的,是必不可少的。

2. Instruction List
Instruction List 是汇编指令序列。它可以是空的,比如:__asm__ __volatile__(""); 或
__asm__ ("");都是完全合法的内联汇编表达式,只不过这两条语句没有什么意义。但并非所有Instruction List 为空的内联汇编表达式都是没有意义的,比如:__asm__ ("":::"memory");
就非常有意义,它向GCC 声明:“内存作了改动”,GCC 在编译的时候,会将此因素考虑进去。
当在"Instruction List"中有多条指令的时候,可以在一对引号中列出全部指令,也可以将一条
或几条指令放在一对引号中,所有指令放在多对引号中。如果是前者,可以将每一条指令放在一行,如果要将多条指令放在一行,则必须用分号(;)或换行符(/n)将它们分开.
综上述:(1)每条指令都必须被双引号括起来 (2)两条指令必须用换行或分号分开。
例如:
__asm__("movl %eax, %ebx; sti/n/t"
"popl %edi; subl %ecx, %ebx");

3. __volatile__
__volatile__是GCC 关键字volatile 的宏定义
#define __volatile__ volatile
__volatile__或volatile 是可选的。如果用了它,则是向GCC 声明不允许对该内联汇编优化,否则当
使用了优化选项(-O)进行编译时,GCC 将会根据自己的判断决定是否将这个内联汇编表达式中的指令优化掉。

在基本内联汇编里可以使用全局变量

二.扩展的内联汇编格式为
__asm__ __volatile__("Instruction List"
: Output
: Input
: Clobber/Modify);

这4 个部分都不是必须的,任何一个部分都可以为空,其规则为:
(1)如果Clobber/Modify 为空,则其前面的冒号(:)必须省略。比如
__asm__("mov %%eax, %%ebx" : "=b"(foo) : "a"(inp) : )就是非法的写法;
而__asm__("mov %%eax, %%ebx" : "=b"(foo) : "a"(inp) )则是正确的。
(2)如果Instruction List 为空,则Input,Output,Clobber/Modify 可以不为空,也可以为空。
比如__asm__ ( " " : : : "memory" );和__asm__(" " : : );都是合法的写法。
(3)如果Output,Input,Clobber/Modify 都为空,Output,Input 之前的冒号(:)既可以省略,
也可以不省略。如果都省略,则此汇编退化为一个基本内联汇编,否则,仍然是一个扩展的内联汇编,
此时"Instruction List"中的寄存器写法要遵守相关规定,比如寄存器前必须使用两个百分号(%%),而不是像基本汇编格式一样在寄存器前只使用一个百分号(%) 。
比如__asm__( " mov %%eax,%%ebx" : : );
__asm__( " mov %%eax, %%ebx" : )和__asm__( " mov %eax, %ebx" )都是正确的写法,
而__asm__( " mov %eax, %ebx" : : );__asm__( " mov %eax,%ebx" : );
__asm__( " mov %%eax, %%ebx" )都是错误的写法。
(4) 如果Input,Clobber/Modify 为空,但Output 不为空,Input 前的冒号(:)既可以
省略,也可以不省略。比如__asm__( " mov %%eax, %%ebx" : "=b"(foo) : );
__asm__( " mov %%eax, %%ebx" : "=b"(foo) )都是正确的。
(5)如果后面的部分不为空,而前面的部分为空,则前面的冒号(:)都必须保留,否则无
法说明不为空的部分究竟是第几部分。比如, Clobber/Modify,Output 为空,
而Input 不为空,则Clobber/Modify 前的冒号必须省略(前面的规则),而Output
前的冒号必须为保留。如果Clobber/Modify 不为空,而Input 和Output 都为空,
则Input 和Output 前的冒号都必须保留。比如__asm__( " mov %%eax, %%ebx" : :
"a"(foo) )和__asm__( " mov %%eax, %%ebx" : : : "ebx" )。
总之不能有歧义.

1. Output
Output 用来指定当前内联汇编语句的输出
2. Input
Input 域的内容用来指定当前内联汇编语句的输入
Output和Input中,格式为形如“constraint”(variable)的列表(逗号分隔)
3. Clobber/Modify
Clobber/Modify 声明当前内联汇编在Instruction List中对某些寄存器或内存进行修改。不能有Input或Output中限制的寄存器

===================================================================================
Constraint Description
a Use the %eax, %ax, or %al registers.
b Use the %ebx, %bx, or %bl registers.
c Use the %ecx, %cx, or %cl registers.
d Use the %edx, %dx, or $dl registers.
S Use the %esi or %si registers.
D Use the %edi or %di registers.
r Use any available general-purpose register.
q Use either the %eax, %ebx, %ecx, or %edx register.
A Use the %eax and the %edx registers for a 64-bit value.
f Use a floating-point register.
t Use the first (top) floating-point register.
u Use the second floating-point register.
m Use the variable’s memory location.
o Use an offset memory location.
V Use only a direct memory location.
i Use an immediate integer value.
n Use an immediate integer value with a known value.
g Use any register or memory location available.
原创粉丝点击