c - 为什么 GCC 不优化掉函数序言和结尾 (push ebp; mov ebp, esp; ...; pop ebp)

标签 c gcc assembly compiler-optimization calling-convention

当编译一个甚至不改变 ebp 寄存器的简单函数时,GCC 仍然会保存函数开头的值,然后在函数末尾恢复相同的值:

#add.c
int add( int a, int b )
{
  return ( a + b );
}

gcc -c -S -m32 -O3 add.c -o add.S

#add.S
    .file   "add.c"
    .text
    .p2align 4,,15
.globl add
    .type   add, @function
add:
    pushl   %ebp
    movl    %esp, %ebp
    movl    12(%ebp), %eax
    addl    8(%ebp), %eax
    popl    %ebp
    ret
    .size   add, .-add
    .ident  "GCC: (GNU) 4.4.6"
    .section        .note.GNU-stack,"",@progbits

保持 ebp 不变,计算相对于 esp 的偏移量并保存 3 条指令,这似乎是一个简单的优化。

为什么 GCC 不这样做?

谢谢

安德鲁

最佳答案

诸如调试器和堆栈遍历器之类的工具过去常常期望代码具有构造帧指针的序言,并且无法理解没有它的代码。随着时间的推移,该限制已被删除。

编译器本身可以毫无困难地生成没有帧指针的代码,您可以使用 -fomit-frame-pointer 要求将其删除。我相信最新版本的 gcc (~4.8) 和 x86-64 上的 gcc 默认省略帧指针。

关于c - 为什么 GCC 不优化掉函数序言和结尾 (push ebp; mov ebp, esp; ...; pop ebp),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21620215/

相关文章:

gcc - 为什么 ARM 的交叉编译在 ./configure 中失败?

linux - 如何指定 scons 中使用的 linux 程序集的命令行 args 和 liker?

c - 警告 : format ‘%s’ expects argument of type ‘char *’ , 但参数 2 的类型为 ‘int’ 使用 argv

c++ - 与动态库链接导致的可执行运行时崩溃

c++ -/usr/bin/ld 找不到 header : File format not recognized

c - 链接程序

assembly - 如何用汇编语言打印余数

c - udp客户端服务器程序c

c - 如何使 C 编译器将所有嵌套循环转换为单个循环

c - getc 函数产生段错误