8

我正在编译这个 C 程序并比较生成的汇编代码:

int main(){ return 0; }

GCC给出了这个主要功能(cc hello.c -S):

_main:
LFB2:
    pushq   %rbp
LCFI0:
    movq    %rsp, %rbp
LCFI1:
    movl    $0, %eax
    leave
    ret

LLVM提供了这个主要功能 ( clang hello.c -S):

_main:
Leh_func_begin0:
    pushq   %rbp
Ltmp0:
    movq    %rsp, %rbp
Ltmp1:
    movl    $0, %eax
    movl    $0, -4(%rbp)
    popq    %rbp
    ret
Leh_func_end0:

什么是movl $0, -4(%rbp)popq %rbp需要什么?在堆栈上移动一些东西然后直接弹出它对我来说似乎没用。

4

3 回答 3

9

实际上,它们是可比的。Leave 是一个高级指令:

来自英特尔手册:

16-bit: C9 LEAVE A Valid Valid Set SP to BP, then pop BP.
32-bit: C9 LEAVE A N.E. Valid Set ESP to EBP, then pop EBP.
64-bit: C9 LEAVE A Valid N.E. Set RSP to RBP, then pop RBP.

基本上,请假相当于

movq %rbp, %rsp
popq %rbp
于 2011-02-04T23:52:13.763 回答
9

movl $0, -4(%rbp)指令已失效,因为这是未优化的代码。尝试传递-O给两个编译器以查看发生了什么变化。

于 2011-02-05T15:09:14.923 回答
2

看起来 LLVM 正在使用传统的函数 prolog/epilog,而 GCC 正在利用入口点不需要清理的事实

于 2011-02-04T23:31:35.723 回答