GCC使用-fomit-frame-pointer选项

时间:2010-08-08 09:30:46

标签: gcc assembly

我正在使用带有-fomit-frame-pointer-O2选项的GCC。当我查看它生成的汇编代码时,

push %ebp
movl %esp, %ebp

在开始时,结尾的pop %ebp被删除。但是esp的一些冗余subl / addl指令保留在开头的subl $12, %esp和结尾的addl $12, %esp

我将如何删除它们,因为在jmp被激活之前,某些内联汇编会addl到另一个函数。

3 个答案:

答案 0 :(得分:3)

您可能不想删除那些 - 通常是分配和释放本地变量的代码。如果删除它们,您的代码将遍历返回地址等等。

摆脱它们的唯一安全方法是不使用任何局部变量。即使在宏中。并且要非常小心内联函数,因为它们通常都有自己的本地文件,这些函数会与您的本地文件一起使用。如果可以,您可能需要考虑明确禁用该部分代码的函数内联。

如果你完全确定不需要add和subs(我的意思是真的,非常肯定),在我的机器上GCC会执行一些堆栈操作以保持堆栈在16字节边界处对齐。您可能会说“-mpreferred-stack-boundary = 2”,它将与4字节边界对齐 - 无论如何x86处理器都喜欢这样做,因此不会生成任何代码来重新对齐它。使用我的GCC在我的盒子上工作; int main() { return 0; }变成了

main: 
    xorl %eax, %eax
    ret

但对齐代码看起来与...开头不同,所以这可能不是你的问题。

正好让你受到警告:优化会导致许多奇怪的事情发生。小心手动编码汇编语言并优化< insert-almost-any-language-here>代码,特别是当你做一些非结构化的东西时,从一个函数的中间跳转到另一个函数。

答案 1 :(得分:1)

我通过提供函数原型解决了这个问题,然后手动定义它:

void my_function();

asm (
    ".globl _my_function\n"
"_my_function:\n\t"
/* Assembler instructions go here */
);

后来我也希望导出该函数,所以我在源文件的末尾添加了这个:

asm (
    ".section  .drectve\n\t"
    ".ascii \" -export:my_function\"\n"
);

答案 2 :(得分:0)

  

我将如何删除它们,因为在执行addl之前,某些内联汇编将jmp到另一个函数。

这会破坏你的堆栈,调用者期望堆栈指针 在功能返回时纠正。其他功能是否返回 通过 ret 指令?你究竟想要达到什么目的?也许有另一种解决方案可能吗?

请向我们展示函数调用(在调用者中)和您的 有问题的函数的进入/退出部分。