在使用堆栈方面,为什么我们需要基本指针和堆栈指针

时间:2019-10-03 20:10:28

标签: c assembly x86 stack abi

无论如何,对于x86汇编代码。我一直在阅读有关函数调用的信息,但仍然不能完全理解对基/帧指针(EBP)和堆栈指针(ESP)的需求。

调用函数时,EBP的当前值将被放置在堆栈上,然后EBP获取当前的ESP值。

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

现在,我们使EBP指向当前堆栈帧的开始,而ESP指向堆栈帧的结束。

由于与EBP的偏移量恒定,因此EBP将用于访问函数的参数和局部变量。那也行。我不明白的是,为什么不能只通过使用ESP的偏移量来使用ESP来访问这些变量。 EBP指向堆栈框架的开始,而ESP指向堆栈框架的结束。有什么区别?

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

2 个答案:

答案 0 :(得分:2)

从技术上讲,可以(但有时很难)跟踪堆栈上存储了多少个局部和临时变量,以便无需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寄存器提交给单个功能(而不是将其用作通用寄存器)是在性能,简单性,代码大小和其他因素之间的权衡。实践经验表明,收益大于成本。

答案 1 :(得分:2)

有关调试器/运行时工具的注释:

使用EBP使调试器(和其他运行时工具)更容易“遍历堆栈”。工具可以在运行时检查堆栈,而无需了解有关当前程序堆栈的任何信息(例如,有多少项目已被推入eac框架),它们可以将堆栈一直移动到“主程序”。

在没有EBP指向“下一个”框架的情况下,运行时工具(包括调试器)将面临非常艰巨的任务(不可能吗?),即如何从ESP移至特定的局部变量。

相关问题