首页 > 解决方案 > 在使用堆栈方面,为什么我们需要一个基指针和一个堆栈指针

问题描述

无论如何,就 x86 汇编代码而言。我一直在阅读有关函数调用的内容,但仍然无法完全掌握对基/帧指针 (EBP) 以及堆栈指针 (ESP) 的需求。

当我们调用一个函数时,EBP 的当前值将被放入堆栈,然后 EBP 获取当前的 ESP 值。

函数的返回值、函数参数和局部变量的占位符然后将被放置在堆栈上,堆栈指针 ESP 值将减少(或增加)以指向最后一个放置在堆栈上的占位符之后。

现在我们让 EBP 指向当前堆栈帧的开头,而 ESP 指向堆栈帧的结尾。

由于与 EBP 的恒定偏移,EBP 将用于访问函数的参数和局部变量。那也行。我不明白的是,为什么 ESP 也不能通过使用它的偏移量来访问这些变量。EBP 指向栈帧的开头,ESP 指向栈帧的结尾。有什么不同?

一旦所有局部变量等都有占位符,ESP就不应该改变,还是应该改变?

标签: cassemblyx86stackabi

解决方案


从技术上讲,可以(但有时很难)跟踪堆栈中存储了多少局部变量和临时变量,这样就可以在没有 EBP 的情况下访问函数输入和局部变量。

考虑以下“C”代码;

int func(int arg) {
   int result ;
   double x[arg+5] ;
   // Do something with x, calculate result
   return result ;
} ;

存储在堆栈中的项目数现在是变量(arg+5 个双精度项目)。从堆栈中计算“arg”的位置需要运行时计算,这会对性能产生重大的负面影响。

使用额外寄存器 (EBP),arg 的位置始终位于固定位置 (EBP-2)。执行“返回”总是很简单——将 BP 移动到 SP,然后返回,等等。

归根结底,将 EBP 寄存器提交给单个函数(而不是将其用作通用寄存器)的决定是性能、简单性、代码大小和其他因素之间的权衡。实践经验表明,收益大于成本。


推荐阅读