在linux平台gcc编译器支持两种形式的内联asm代码:
基本 asm 格式:不支持操作数;
扩展 asm 格式:支持操作数;
基本asm
语法结构
asm [volatile] ("汇编指令")
格式说明
(1)所有指令,必须用双引号包裹起来;
(2)超过一条指令,必须用\n分隔符进行分割,为了排版,一般会加上\t;
(3)多条汇编指令,可以写在一行,也可以写在多行;
(4)关键字 asm 可以使用 asm 来替换;
(5)volatile 是可选的,编译器有可能对汇编代码进行优化,使用 volatile 关键字之后,告诉编译器不要优化手写的内联汇编代码。
3、使用示例
(1)内联汇编
asm volatile ("movl a, %eax\n\t"
"addl b, %eax\n\t"
"movl %eax, c");
(2)功能说明
movl a, %eax // 把变量a的值复制到 %eax 寄存器中;
addl b, %eax // 把变量 b 的值 与 %eax 寄存器中的值(a)相加,结果放在 %eax 寄存器中;
movl %eax, c // 把 %eax 寄存器中的值复制到变量 c 中;
扩展asm
语法结构
asm [volatile] ("汇编指令" : "输出操作数列表" : "输入操作数列表" : "改动的寄存器")
格式说明
(1)汇编指令:与基本asm格式相同;
(2)输出操作数列表:汇编代码如何把处理结果传递到 C 代码中;
(3)输入操作数列表:C 代码如何把数据传递给内联汇编代码;
(4)改动的寄存器:告诉编译器,在内联汇编代码中,我们使用了哪些寄存器;
(5)“改动的寄存器”可以省略,此时最后一个冒号可以不要,但是前面的冒号必须保留,(6)即使输出/输入操作数列表为空。
3、使用示例
(1)扩展内联汇编
asm("movl %%ebx, %%eax\n\t"
"addl %%ecx, %%eax"
: "=a"(data3)
: "b"(data1),"c"(data2));
(2)功能说明
"b"(data1),"c"(data2) ==> 把变量 data1 复制到寄存器 %ebx,变量 data2 复制到寄存器 %ecx。这样,内联汇编代码中,就可以通过这两个寄存器来操作这两个数了;
"=a"(data3) ==> 把处理结果放在寄存器 %eax 中,然后复制给变量data3。前面的修饰符等号意思是:会写入往 %eax 中写入数据,不会从中读取数据。