Assembly x86程序集:为什么需要堆栈帧?
在我看到的大多数x86程序集(尤其是NASM)代码示例(甚至是GCC生成的代码示例)上,我看到了所谓的“堆栈框架设置”。像这样:Assembly x86程序集:为什么需要堆栈帧?,assembly,x86,nasm,Assembly,X86,Nasm,在我看到的大多数x86程序集(尤其是NASM)代码示例(甚至是GCC生成的代码示例)上,我看到了所谓的“堆栈框架设置”。像这样: main: /*setting the stack frame*/ push ebp mov ebp,esp ... code goes here ... /*removing the stack frame*/
main:
/*setting the stack frame*/
push ebp
mov ebp,esp
...
code goes here
...
/*removing the stack frame*/
mov esp, ebp
pop ebp
关于这种做法,我有3个问题:
谢谢你基本上是对的
不过,堆栈帧确实有某些好处,即使您不需要固定的堆栈引用来访问参数和局部变量。特别是在那里使用它们可以精确地遍历堆栈,以便生成用于调试目的的堆栈跟踪。这是按照约定完成的。C语言函数使用堆栈帧访问发送给函数的参数,并设置动态局部变量。这就是为什么他们会在您正在查看的示例代码中这样做。当然,如果您想按自己的方式执行,您可以,但您将无法从C等调用代码
编辑:我也非常确定有一些编译器实现了不同的调用约定来优化它,并且可能根本不创建框架。所以基本上,你是对的。堆栈帧不是必需的。事实上,您不需要堆栈帧 当您在堆栈中保存寄存器和存储局部变量时,堆栈帧非常方便—以简化编写和调试:您只需将
ebp
设置为堆栈中的一个固定点,并使用ebp
对所有堆栈数据进行寻址。而且更容易在最后恢复esp
此外,调试器通常期望堆栈帧存在,否则您可能会得到不准确的堆栈调用(例如)
因此,1的答案是肯定的,2和3的答案在上面。如果要调试程序并查看堆栈跟踪,堆栈帧也是必需的。堆栈帧实际上不需要。如你所见。在X86-64中,我们没有堆栈帧和ebp寄存器。所以您是对的,堆栈帧只是为了方便使用。
-fomit frame pointer
在Linuxgcc-m32
中启用优化时默认为打开。2013年可能不是这样,或者如果您使用的是更旧的编译器,但多年来(2018年)都是这样<代码>-默认情况下,x86-64模式下,fomit帧指针始终处于打开状态。参数实际上与当前堆栈帧的底部成负偏移。它使用堆栈将参数传递给函数,但如果我没有记错,它不会指定使用堆栈帧。实际上,函数调用约定根本不依赖于堆栈帧。@akonsu在我看来,您的措辞暗示了这一点,但我错了。C中函数内部的代码使用堆栈帧基(我不确定正确的术语是什么)来访问参数和设置局部变量。参数位于帧基准(负偏移)之外,局部区域位于帧内部。这就是我20年前的记忆@谢谢你。我改变了措辞。组装是非常有趣的使用。很长时间过去了。我不再使用它了。。。