理解gcc -S输出

21

我在x86_64上对下面这个非常复杂的程序执行了gcc -S:

int main() {
    int x = 3;
    x = 5;
    return 0;
}

我得到的是:

       .file   "main.c"
        .text
.globl main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $3, -4(%rbp)
        movl    $5, -4(%rbp)
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
        .section        .note.GNU-stack,"",@progbits
我想知道是否有人可以帮我理解输出或者给我一些解释的链接。具体来说,cfi, LFB0, LFE0, leave 是什么意思?我只能找到关于这些的这篇文章,但是我无法完全理解它的用途。此外,在这种情况下,ret 是做什么的?我猜它会返回到__libc_start_main(),然后调用do_exit(),这正确吗?
2个回答

27

.cfisomething指令会导致编译器生成额外的数据。这些数据有助于在指令引发异常时遍历调用栈,以便找到并正确执行异常处理程序(如果有的话)。调用栈信息对于调试非常有用。这些数据很可能会进入可执行文件的一个单独部分,不会插入到您代码的指令之间。

.LFsomething:只是常规标签,可能被额外的与异常相关的数据所引用。

leaveret是CPU指令。

leave相当于:

movq    %rbp, %rsp
popq    %rbp

它会撤销这两个指令的效果。

pushq   %rbp
movq    %rsp, %rbp

通过从rsp减去某个值来在栈上为变量分配空间的指令。

ret用于函数返回。它从栈中弹出返回地址并跳转到该地址。如果是__libc_start_main()调用了main(),那么它会返回到那里。


7
在这种体系结构中,GCC的所有本地标签都以“.L”开头并以数字结尾。只有以“.L”和数字为标签的是跳转目标。在其他字母之间具有某些目的的标签则不同。在这种情况下,“FB”代表“函数开始”,“FE”代表“函数结束”,它们可能已经不再使用了。如果我没记错的话,它们曾经在GCC自己计算异常处理数据而不是由汇编器完成时是必需的,并且它们仍然存在是因为x86后端非常复杂,很难确定它们是否不必要。 - zwol

16
  1. .LFB0, .LFE0 只是本地标签。

  2. .cfi_startproc 用于每个函数的开头,函数结束时使用 .cfi_endproc

    • 这些汇编指令帮助汇编器将调试和堆栈展开信息放入可执行文件中。
  3. leave 指令是 x86 汇编指令,其作用是恢复调用函数的堆栈帧。

最后,在 ret 指令之后,会发生以下事情:

  • %rip 包含返回地址
  • %rsp 指向调用者推送的参数,这些参数没有适配 amd64 上用于传递参数的六个寄存器 (%rdi,%rsi,%rdx,%rcx,%r8,%r9)
  • 被调用函数可能会破坏参数
  • %rax 包含返回值(或垃圾值,如果函数为 void)(或者如果返回值大小大于 8 字节但小于或等于 16 字节,则 %rax%rdx 包含返回值1
  • %r10%r11 可能会损坏
  • %rbp%rbx%r12%r13%r14%r15 必须包含调用时的内容

更多信息可以在这里找到:(SO 问题)(标准 PDF)

或者,在 32 位系统上:

  • %eip 包含返回地址
  • %esp 指向由调用者推送的参数
  • 被调用的函数可能已经破坏了参数
  • %eax 包含返回值(如果函数是void,则为垃圾)
  • %ecx%edx 可能已被破坏
  • %ebp%ebx%esi%edi 必须包含调用时的内容

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接