GCC内联汇编(2)GCC生成汇编代码简单实例

来源:互联网 发布:java在线考试系统代码 编辑:程序博客网 时间:2024/05/29 03:14

GCC内联汇编(2)GCC生成汇编代码简单实例

  • 作者:柳大·Poechant(钟超)
  • 邮箱:zhongchao.ustc#gmail.com(# -> @)
  • 博客:Blog.CSDN.net/Poechant
  • 日期:July 8th, 2012

1 准备示例

先看一个空的 main 函数会生成怎样的汇编代码。要注意的是我这里是在 Mac OS X 上进行的测试,编译器是 Apple’s version of GCC,实际上用的是 llvm-gcc。

[代码段-1]

int main() {    return 0;}

[命令行-1]

gcc -S main.c

生成的汇编如下(这里只截取主要部分,下同):

[代码段-2]

Leh_func_begin1:    pushq   %rbpLtmp0:    movq    %rsp, %rbpLtmp1:    movl    $0, -8(%rbp)    movl    -8(%rbp), %eax    movl    %eax, -4(%rbp)    movl    -4(%rbp), %eax    pop     %rbp    retLeh_func_end1:

如果开启优化编译选项呢?一定会有一些变化吧。

[命令行-2]

gcc -S main.c -O3

[代码段-3]

Leh_func_begin1:    pushq   %rbpLtmp0:    movq    %rsp, %rbpLtmp1:    xorl    %eax, %eax    popq    %rbp    pop     %rbp    retLeh_func_end1:

是的,一些“废话”被优化掉了。

[代码段-4]

int main() {    int a = 19, b = 100;    return 0;}

看下面的简单实例,声明两个整形变量,并赋以初值。

[命令行-3]

gcc -S main.c

生成的汇编代码如下。可以看到 a 代表的局部变量值 19 被压入栈中,位置是栈基址减去 12,b 代表的局部变量压入栈中,位置是栈基址减去 16,而返回值所使用的立即数 0 被放入栈基址减去 8。

[代码段-5]

Leh_func_begin1:    pushq   %rbpLtmp0:    movq    %rsp, %rbpLtmp1:    movl    $19, -12(%rbp)    movl    $100, -16(%rbp)    movl    $0, -8(%rbp)    movl    -8(%rbp), %eax    movl    %eax, -4(%rbp)    movl    -4(%rbp), %eax    pop     %rbp    retLeh_func_end1:

如果打开优化编译选项编译,则会把int a = 19, b = 100这句优化掉,从而与[代码段-3]一样。

2 内联汇编实例

int main(){    int a = 19, b = 100;    __asm__ (        "addl %2, %1";        : "=a"(a)        : "a"(a), "b"(b)        : "%eax", "%ebx"    )    return 0;}

生成的汇编如下:

_main:Leh_func_begin1:    pushq   %rbpLtmp0:    movq    %rsp, %rbpLtmp1:    pushq   %rbx    subq    $24, %rspLtmp2:    movl    $19, -20(%rbp) # 局部变量 a 的位置是栈基址减去 20    movl    $100, -24(%rbp) # 局部变量 b 的位置是栈基址减去 24        # 处理内敛汇编的入口    movl    -20(%rbp), %eax    movl    -24(%rbp), %ecx    movl    %ecx, %ebx        ## InlineAsm Start    addl    %ebx, %eax;    ## InlineAsm End    movl    %eax, -20(%rbp) # 返回值放在指定的局部变量 a 中        # 剩下的部分与前面的简单实例一样,就是处理返回值    movl    $0, -16(%rbp)    movl    -16(%rbp), %eax    movl    %eax, -12(%rbp)    movl    -12(%rbp), %eax    popq    %rbx    popq    %rbp    ret Leh_func_end1:
#include                                                                                                                                                                                         int main() {    int a = 19, b = 100;    __asm__ (        "addl %1, %0;"        : //no output        : "a"(a), "b"(b)        : "%eax", "%ebx"    );      return 0;}
_main:Leh_func_begin1:    pushq   %rbpLtmp0:    movq    %rsp, %rbpLtmp1:    pushq   %rbxLtmp2:    # Immediate numbers    movl    $19, -20(%rbp)    movl    $100, -24(%rbp)        # Input    movl    -20(%rbp), %eax    movl    -24(%rbp), %ecx    movl    %ecx, %ebx        ## InlineAsm Start    addl %ebx, %eax;    ## InlineAsm End        # Note: no output        # Similar to above examples    movl    $0, -16(%rbp)    movl    -16(%rbp), %eax    movl    %eax, -12(%rbp)    movl    -12(%rbp), %eax    popq    %rbx    popq    %rbp    ret Leh_func_end1:

也间接证实了%0%1%2⋯⋯ 是从输出开始排序的,如果没有输出,就从输入开始排序。

另外使用m则可以表示memory,即变量是在内存中,而非寄存器中。如下示例:

#include                                                                                                                                                                                         int main() {    int a = 17, b = 100;    __asm__ (        "addl %2, %1;"        : "=m"(a)        : "m"(a), "b"(b)        : "memory", "%ebx"    );      printf("%d\n", a);     return 0;}

生成的汇编代码的主要部分如下:

movl    $17, -20(%rbp)movl    $100, -24(%rbp)movl    -24(%rbp), %eaxmovl    %eax, %ebx## InlineAsm Startaddl    %ebx, -20(%rbp)## InlineAsm End## 下面的部分同此前的所有代码段,略去

可以看到是直接加到操作上的,而非寄存器。

-

转载请注明来自柳大的CSDN博客:Blog.CSDN.net/Poechant

-

原创粉丝点击