基本语法格式
使用特殊的语法格式,允许C代码里面直接嵌入自己设计的汇编指令。格式如下:
asm("assembly code" : output locations : input operands : changed registers);
其中,asm可以使用关键字"__asm__"。
1.assembly code:内联汇编代码
2.output locations:包含汇编代码运行之后输出值的寄存器列表或者内存位置
3.input operands:包含输入值的寄存器列表或者内存位置,这些输入值给汇编代码使用
4.changed registers:内联汇编代码会修改的任何其他寄存器
以上2/3/4部分如果没有,可以为空,但是4如果没有,可以直接去掉不写,2/3需要保留前面的冒号。
指定输入输出值
output locations和input operands分别表示输出值和输入值,他们遵循统一的格式,都可以指定寄存器或者内存位置,格式如下:
: "constraint" (variable)
1.constraint:表示一种约束,说明输入变量存放在哪里并且输出值放到哪里去
2.variable:表示C中的变量名,可以是局部或者全局变量
以上的constraint,使用单个字符的编码,用以区分不同的约束,如下:
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. |
除了以上约束,输出值还包含一个修饰符,用以指出输出值如何被编译器处理。输出修饰符如下:
+ | The operand can be both read from and written to |
= | The operand can only be written to |
% | The operand can be switched with the next operand if necessary |
& | The operand can be deleted and reused before the inline functions complete |
举个例子,以下汇编语句:
asm (“assembly code” : “=a”(result) : “d”(data1), “c”(data2));
表示将C变量data1放到EDX寄存器,变量data2放到ECX寄存器。内联汇编的结果将被放到EAX寄存器,然后会被移到result变量。
使用占位符
占位符是一个'%'后面跟上一个数字,比如"%1"。每个列在内联汇编代码里的输入输出值将基于位置分配一个数字,这个数字从0开始。然后内联汇编代码里面,就可以使用这个占位符用以代表这个值。举个例子,以上列举的汇编语句中:
%0表示寄存器,这个寄存器中包含result变量的值
%1表示寄存器,这个寄存器中包含data1变量的值
%2表示寄存器,这个寄存器中包含data2变量的值
如果输入输出值共享某个C变量,可以通过使用占位符来约束一个值。比如:
asm (“imull %1, %0”: “=r”(data2): “r”(data1), “0”(data2));
'0'标记让编译器使用那个包含输出值的寄存器作为输入,存放data2,那个寄存器的值最终也会输出到data2变量。
如果有很多的输入输出值,那么简单的数字占位符将存在一些困惑,此时,可以使用另一种占位符,这种占位符允许你指定一个名称。格式如下:
%[name]”constraint”(variable)
比如,如下内联汇编语句:
asm (“imull %[value1], %[value2]”
: [value2] “=r”(data2)
: [value1] “r”(data1), “0”(data2));
用法基本一致,取而代之的不是数字,而是变成了一个name。如上的value2、value1。
以上信息来源于《汇编语言程序设计》。