c - 在使用堆栈方面,为什么我们需要一个基指针和一个堆栈指针
问题描述
无论如何,就 x86 汇编代码而言。我一直在阅读有关函数调用的内容,但仍然无法完全掌握对基/帧指针 (EBP) 以及堆栈指针 (ESP) 的需求。
当我们调用一个函数时,EBP 的当前值将被放入堆栈,然后 EBP 获取当前的 ESP 值。
函数的返回值、函数参数和局部变量的占位符然后将被放置在堆栈上,堆栈指针 ESP 值将减少(或增加)以指向最后一个放置在堆栈上的占位符之后。
现在我们让 EBP 指向当前堆栈帧的开头,而 ESP 指向堆栈帧的结尾。
由于与 EBP 的恒定偏移,EBP 将用于访问函数的参数和局部变量。那也行。我不明白的是,为什么 ESP 也不能通过使用它的偏移量来访问这些变量。EBP 指向栈帧的开头,ESP 指向栈帧的结尾。有什么不同?
一旦所有局部变量等都有占位符,ESP就不应该改变,还是应该改变?
解决方案
从技术上讲,可以(但有时很难)跟踪堆栈中存储了多少局部变量和临时变量,这样就可以在没有 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 寄存器提交给单个函数(而不是将其用作通用寄存器)的决定是性能、简单性、代码大小和其他因素之间的权衡。实践经验表明,收益大于成本。