2 次函数调用期间 EBP 和 ESP 在堆栈中的行为
Behaviour of EBP and ESP in stack during 2 function calls
我正在研究函数调用在 x86 平台上的工作方式。据我了解如下
调用函数时发生的步骤:
函数的参数和return地址被压入堆栈。
然后将当前EBP的值压入堆栈。
现在 ESP 已更改(由于步骤 2),EBP 已替换为 ESP,现在它们是
指向(堆栈?)的相同地址。
然后局部变量被推送,函数执行它的工作。
最后弹出这个函数的局部变量和寄存器。在这个
进程ESP也在动吧?
最后,EBP 被替换为当前 ESP
的值
现在 ESP 和 EBP 指向相同的堆栈地址。
所以我的问题如果以上几点都正确,否则请指正,如何
该系统在 2 个函数调用的情况下工作。让我解释一下
对于第一个函数调用,ebp 被压入堆栈并且 esp 和 ebp 相同。
现在 esp 递增以创建第一个函数调用的本地堆栈,例如 foo()。
现在假设有来自 foo() 的第二个函数调用,比如 goo()。
现在将再次发生相同的过程....当前 ebp 将被推入堆栈
esp 和 ebp 将相同并且 esp 将递增(从技术上讲,
递减 ) 对于 goo() 函数的局部变量。
现在让我们关注函数何时 return。
return 从 goo() 中调用,esp 递增,因为本地寄存器从堆栈中弹出并在
last esp 将被分配位置 ebp 持有的值而不是 current 的值
ebp,对吧?
然后弹出保存ebp的位置
所以我的问题是,如果是这种情况,现在我们已经丢失了
function foo() 因为ebp和esp指向foo()的ebp,一旦出现就会弹出
foo() returns...
由于实际情况并非如此,我一定遗漏了一些东西。请帮助我...
谢谢。
我假设你在谈论 cdecl (https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl) 调用约定(c 中经常使用的那个)。
%ebp 是基址指针寄存器,它是被调用者保存的,这意味着调用者可以假设被调用者不会修改它的值,因此调用者可以假设 %ebp 将始终引用其堆栈的基址.
%esp是Stack Pointer寄存器,也是callee保存的,但是,由于caller将callee的参数压入stack,%esp是递减的,所以当callee return.我认为这就是您的问题所在,%esp 的值仅增加到足以释放分配的参数,而不是 return 到堆栈的底部。
而 %ebp 和 %esp 实际上指的是堆栈的基址和 'top'。没问题
我正在研究函数调用在 x86 平台上的工作方式。据我了解如下 调用函数时发生的步骤:
函数的参数和return地址被压入堆栈。
然后将当前EBP的值压入堆栈。
现在 ESP 已更改(由于步骤 2),EBP 已替换为 ESP,现在它们是 指向(堆栈?)的相同地址。
然后局部变量被推送,函数执行它的工作。
最后弹出这个函数的局部变量和寄存器。在这个 进程ESP也在动吧?
最后,EBP 被替换为当前 ESP
的值
现在 ESP 和 EBP 指向相同的堆栈地址。
所以我的问题如果以上几点都正确,否则请指正,如何 该系统在 2 个函数调用的情况下工作。让我解释一下
对于第一个函数调用,ebp 被压入堆栈并且 esp 和 ebp 相同。
现在 esp 递增以创建第一个函数调用的本地堆栈,例如 foo()。
现在假设有来自 foo() 的第二个函数调用,比如 goo()。
现在将再次发生相同的过程....当前 ebp 将被推入堆栈
esp 和 ebp 将相同并且 esp 将递增(从技术上讲, 递减 ) 对于 goo() 函数的局部变量。
现在让我们关注函数何时 return。
return 从 goo() 中调用,esp 递增,因为本地寄存器从堆栈中弹出并在 last esp 将被分配位置 ebp 持有的值而不是 current 的值 ebp,对吧?
然后弹出保存ebp的位置
所以我的问题是,如果是这种情况,现在我们已经丢失了 function foo() 因为ebp和esp指向foo()的ebp,一旦出现就会弹出 foo() returns...
由于实际情况并非如此,我一定遗漏了一些东西。请帮助我...
谢谢。
我假设你在谈论 cdecl (https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl) 调用约定(c 中经常使用的那个)。
%ebp 是基址指针寄存器,它是被调用者保存的,这意味着调用者可以假设被调用者不会修改它的值,因此调用者可以假设 %ebp 将始终引用其堆栈的基址.
%esp是Stack Pointer寄存器,也是callee保存的,但是,由于caller将callee的参数压入stack,%esp是递减的,所以当callee return.我认为这就是您的问题所在,%esp 的值仅增加到足以释放分配的参数,而不是 return 到堆栈的底部。
而 %ebp 和 %esp 实际上指的是堆栈的基址和 'top'。没问题