6

在我看到的大多数 x86 程序集(特别是 NASM)代码示例中(甚至在 GCC 生成的代码示例中),我看到了所谓的“堆栈框架设置”。像这样:

main: 
        /*setting the stack frame*/
        push    ebp     
        mov     ebp,esp

        ...
        code goes here
        ...

        /*removing the stack frame*/
        mov     esp, ebp
        pop     ebp

我对这种做法有 3 个问题:

  1. 如果我的代码没有触及堆栈,那么如上所述设置/删除堆栈框架是完全没用的,对吧?

  2. 即使我的代码使用堆栈,只要弹出我推送的所有内容(本质上保持堆栈不变)然后再次设置堆栈框架是完全没用的,对吧?

  3. 在我看来,这样做的唯一目的是保存 ESP 的值,这样我就可以在我的代码中使用它,而不必担心把事情搞砸,一旦我完成了,我只需恢复它的原始值。这是堆栈框架设置的目的还是我遗漏了什么?

谢谢

4

3 回答 3

7

好吧,事实上,您不需要堆栈帧。

当您保存寄存器并将局部变量存储在堆栈中时,堆栈帧很方便 - 使编写和调试更容易:您只需设置ebp堆栈中的固定点并使用ebp. 最后更容易恢复esp

此外,调试器通常希望存在堆栈帧,否则您可能会得到不准确的堆栈调用。

所以,1的答案是肯定的,2和3的答案在上面。

于 2013-06-21T16:16:59.613 回答
4

你基本上是正确的。

不过,堆栈帧确实有一定的好处,即使您不需要固定的堆栈引用来访问参数和局部变量。特别是让它们在那里允许准确的堆栈遍历,以生成用于调试目的的堆栈跟踪。

于 2013-06-21T16:15:55.477 回答
2

这是按惯例完成的。C 语言函数使用堆栈帧来访问发送给函数的参数,并设置动态局部变量。这就是他们在您正在查看的示例代码中执行此操作的原因。当然,如果您想按照自己的方式进行操作,可以,但是您将无法从 C 等调用您的代码。

编辑:我也很确定有些编译器实现了不同的调用约定来优化它,并且可能根本不创建框架。所以基本上,你是对的。堆栈帧不是必需的。

于 2013-06-21T16:15:57.633 回答