功能序言和结语由GCC优化删除

时间:2013-03-22 05:36:37

标签: c optimization gcc assembly x86

采取空程序

//demo.c

int main(void)
{

}

在默认优化时编译程序。

gcc -S  demo.c -o dasm.asm 

我得到汇编输出为

//Removed labels and directive which are not relevant

main:

pushl   %ebp                  // prologue of main
movl    %esp, %ebp            // prologue of main
popl    %ebp                  // epilogue of main
ret

现在在-O2优化时编译程序。

gcc -O2 -S  demo.c -o dasm.asm 

我得到了优化的程序集

main:

rep
ret

在我最初的搜索中,我发现优化标志 -fomit-frame-pointer 负责删除序言和结尾。

我在gcc compiler manual中找到了有关该旗帜的更多信息。但是在手册中给出的删除序言和结语的情况下,我无法理解以下这个原因。

  

不要将帧指针保留在寄存器中以查找不能执行的功能   需要一个。

出于上述原因,还有其他方法吗?

"rep"指令出现在-02优化的原因是什么?

为什么main函数不需要堆栈帧初始化?

如果没有在主函数内设置帧指针,那么谁来做这个工作?

是由操作系统完成的还是硬件的功能?

1 个答案:

答案 0 :(得分:5)

编译器越来越聪明,它知道你不需要存储在寄存器中的堆栈帧指针,因为你放入main()函数的任何东西都没有使用堆栈。

至于rep ret:

  

这是原则。处理器尝试获取接下来的几个   要执行的指令,以便它可以启动进程   解码并执行它们。它甚至可以通过跳跃和返回来实现   说明,猜测程序下一步的位置。

     

AMD在这里说的是,如果一个ret指令紧随其后   条件跳转指令,他们的预测器无法弄清楚在哪里   ret指令正在进行中。预取必须停止,直到   ret实际执行,只有这样它才能开始寻找   再次前进。

     

“rep ret”技巧显然可以解决这个问题,并且可以解决问题   预测者做好自己的工作。 “rep”对指令没有影响。

来源:一些论坛,谷歌一句话找到它。

有一点需要注意的是,仅仅因为没有序言它并不意味着没有堆栈,你仍然可以轻松推送和弹出它只是复杂的堆栈操作将是困难的。

没有序言/结语的功能通常被称为裸体。黑客喜欢使用它们,因为当你对它们进行jmp时它们不会污染堆栈,我必须承认我知道在优化之外没有其他用途。在Visual Studio中,它通过以下方式完成:

__declspec(naked)