堆栈指针和基指针

时间:2021-07-06 13:44:54

标签: c++ memory memory-management

您好,我想问一下 EBP 和 ESP 寄存器在程序执行过程中是如何初始化和更新的。

我下面有一张图,作者解释说,当进入一个新函数时,首先将参数压入黄色区域所示的堆栈,然后更新基指针EBP并存储前一个函数的基指针,其次是堆栈为局部变量和返回地址分配更多资源。

我想知道在进入新函数时简单地更新基指针,然后为前一个函数的基指针寄存器地址分配内存,然后是参数,局部变量和返回值是不是更容易?而不是将 EBP 放在函数的堆栈帧中间。

我的另一个问题是,返回地址值在前一个函数中究竟指向哪里,是在前一个函数的末尾,还是在前一个函数的开头?

我的另一个问题是,如果您已经存储了前一个函数的返回地址,那么存储前一个函数基指针寄存器有什么意义?

我从指针中得到的想法是,您本质上只想将它们用作访问函数本地资源的引用,您可以使用返回地址

谢谢

stack illustration

1 个答案:

答案 0 :(得分:0)

要从函数返回,您需要(至少)恢复两件事。

一个是指令指针所在的位置,即您运行它的下一条指令所在的位置。

另一个是栈指针所在的位置,你正在操作的数据所在的位置。

(根据调用约定,寄存器可能也需要重置,但我不知道这里的细节)。

返回地址——指令指针——指向从调用返回时代码应该继续执行的位置。这通常不是调用函数的开始或结束,而是调用后的“下一条指令”。 (但不是真的;它指向处理函数返回的代码,这在某些调用约定中确实有效)。

代码调用一个函数必须更新堆栈指针,以便被调用的函数知道它的堆栈参数在哪里,并为被调用的函数返回提供足够的信息。

调用的函数不需要在内部进行。它(好吧,编写它的编译器知道)它在堆栈中放置了哪些变量,以及它们有多大。在函数体中,堆栈上的变量集可能会随时间变化。因此更新堆栈指针毫无意义,甚至会使偏移量计算变得更加复杂(因为它们会不断变化,而不是对于给定的“变量”保持不变)并且让汇编编写者感到困惑。

访问堆栈的代码无论如何都会使用偏移量。不改变堆栈指针比改变堆栈指针所做的工作更少,而且做更少的工作通常比做更多的工作更快。

所以除非你需要改变它,否则你不用管堆栈指针。

返回地址对于访问可变数据没有用。返回地址通常指向只读机器代码,而不是堆栈上的可变状态。

现在,有大量的调用约定。他们中的许多人做的事情略有不同。哪些参数进入堆栈,哪些存储在寄存器中,什么样的参数去哪里,以及谁重置堆栈指针(调用者或被调用者)等都可能有所不同。

相关问题