EBP帧指针寄存器的用途是什么?

我是汇编语言的初学者,并且注意到编译器发出的x86代码通常会保持帧指针,即使在发布/优化模式下,也可以使用EBP寄存器来实现其他function。 我明白为什么帧指针可能会使代码更易于debugging,并且如果在函数中调用alloca(),则可能是必需的。 然而,x86有很less的寄存器,并且使用其中的两个来保存堆栈帧的位置就足够了,这对我来说是没有意义的。 为什么即使在优化/发布版本中,忽略帧指针也是一个糟糕的主意?

帧指针是一个引用指针,允许debugging器知道局部variables或参数在哪里与一个单一的常量偏移。 尽pipeESP的值在执行过程中发生了变化,但EBP保持不变,可以在相同的偏移量上达到相同的variables(例如,第一个参数始终在EBP + 8,而ESP偏移量可能会发生显着变化,因为您将要/popup的东西)

为什么不编译器丢弃帧指针? 由于使用帧指针,debugging器可以确定局部variables和参数使用符号表的位置,因为它们保证与EBP的偏移量保持不变。 否则,没有一种简单的方法可以确定局部variables在代码中的任何位置。

正如Greg所说的那样,它也有助于堆栈展开,因为EBP提供了一个反向链接的栈帧列表,因此debugging器可以计算出函数的栈帧大小(局部variables+参数)。

大多数编译器提供了一个选项来省略帧指针,尽pipe它使debugging非常困难。 即使在发布代码中,该选项也不应该在全局范围内使用。 你不知道什么时候需要debugging用户的崩溃。

只要加上我的两分钱已经很好的答案。

这是一个良好的语言架构的一部分,有一个堆栈框架链。 BP指向存储子例程局部variables的当前帧。 (当地人的消极抵消,争论是正面抵消。)

从优化中防止一个完美的寄存器的想法提出了一个问题:何时何地优化实际上是值得的?

优化只有在1)不调用函数,2)程序计数器花费相当一部分时间的紧密循环中是有价值的,3)代码中编译器实际上会看到(即非库函数)。 这通常是整个代码的一小部分,特别是在大型系统中。

其他代码可以扭曲和挤压摆脱循环,这根本就没有关系,因为程序计数器实际上从来没有在那里。

我知道你没有问这个问题,但根据我的经验,99%的性能问题与编译器优化毫无关系。 他们有一切与过度devise。

当然,这取决于编译器。 我已经看到了x86编译器发布的优化代码,可以自由地将EBP寄存器用作通用寄存器。 (我不记得我注意到哪个编译器,但是。)

编译器也可以select维护EBP寄存器来协助exception处理期间的堆栈展开,但这又取决于精确的编译器实现。

但是,x86有很less的寄存器

只有在操作码只能寻址8个寄存器的意义上,情况才是正确的。 处理器本身实际上会有更多的寄存器,并使用寄存器重命名,stream水线,推测执行和其他处理器stream行语来绕过这个限制。 维基百科有一个很好的介绍性的段落,说明x86处理器可以做些什么来克服注册限制: http : //en.wikipedia.org/wiki/X86#Current_implementations 。

即使在远程现代化的情况下,使用堆栈帧在任何硬件上都变得非常便宜。 如果你有便宜的堆栈帧,那么保存一些寄存器并不重要。 我确信快速堆栈帧与更多的寄存器是一个工程权衡,快速堆栈帧赢了。

你要存多less钱去登记? 这值得么?