汇编中的堆栈/基址指针

mal*_*ngi 6 x86 assembly callstack backtrace stack-frame

我知道这个话题已经覆盖生厌这里,并在互联网上其他地方-但希望这个问题很简单,因为我试图让我的头周围装配...

因此,如果我理解正确,ebp(基指针)将指向堆栈的顶部,并且esp(堆栈指针)将指向底部 - 因为堆栈向下增长.因此,esp指向"当前位置".因此,在函数调用中,一旦将ebp保存在堆栈上,就会为函数插入一个新的堆栈帧.因此,对于下图,如果您从N-3开始,您将通过函数调用转到N-2.但是当你在N-2时 - 你的ebp == 25和esp == 24(至少最初,在任何数据被放入堆栈之前)?

这是正确的还是我在这里切线?

谢谢!

http://upload.wikimedia.org/wikipedia/en/a/a7/ProgramCallStack2.png http://upload.wikimedia.org/wikipedia/en/a/a7/ProgramCallStack2.png

Cra*_*rks 4

这实际上不仅取决于硬件架构和编译器,还取决于调用约定,这只是函数与堆栈相互调用的一种商定的方式。换句话说,函数可以采用不同的顺序将内容推入堆栈,具体取决于您的编译器设置(以及特殊#pragma选项等)。

看起来你正在谈论cdeclx86 架构上的调用约定。在这种情况下,调用者的地址ebp通常在返回地址之后立即被压入堆栈。因此,在您的示例的 N-2 中,位置 25 将包含一个返回调用函数 N-3 的指针(即,它将包含紧随call进入 N-2 的指令之后的指令的地址),而位置 24 将包含旧的ebp,并且您的 esp 将在调用后立即 = 23,然后将任何本地变量推入堆栈。(除了某些编译器会在调用后立即在堆栈上腾出空间,因此 ESP 将为 20,而不是在函数 N-2 内上下移动。)

请注意,在 x86 上,编译器有时可以进行一种特殊的优化,称为帧指针省略,它可以避免在某些条件下将旧数据ebp完全推入堆栈。