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

performance assembly x86

48366 观看

5回复

我是汇编语言的初学者,并注意到编译器发出的x86代码通常会在释放/优化模式下保持帧指针,因为它可以将EBP寄存器用于其他东西。

我理解为什么帧指针可能使代码更容易调试,并且如果alloca()在函数内调用则可能是必要的。但是,x86只有很少的寄存器,并使用其中两个寄存器来保存堆栈帧的位置,当一个就足够了,对我来说没有意义。为什么即使在优化/发布版本中省略框架指针也是一个坏主意?

作者: dsimcha 的来源 发布者: 2019 年 7 月 30 日

回应 (5)


91

决定

帧指针是一个引用指针,允许调试器通过单个常量偏移量知道局部变量或参数的位置。虽然ESP的值在执行过程中会发生变化,但EBP保持不变,因此可以在相同的偏移量下达到相同的变量(例如,第一个参数将始终保持在EBP + 8,而ESP偏移可能会因为您的推动而显着变化/弹出的东西)

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

正如Greg所提到的,它还有助于堆栈展开调试器,因为EBP提供了堆栈帧的反向链接列表,因此让调试器能够计算出函数的堆栈帧(局部变量+参数)的大小。

大多数编译器提供了省略帧指针的选项,尽管它使调试变得非常困难。永远不要在全局使用该选项,即使在发布代码中也是如此。您不知道何时需要调试用户的崩溃。

作者: Sedat Kapanoglu 发布者: 23.02.2009 08:55

28

把我的两分钱加到已经很好的答案上。

它是具有一系列堆栈帧的良好语言架构的一部分。BP指向当前帧,其中存储子例程局部变量。(当地人处于负偏移,参数处于正偏移量。)

它阻止了一个非常好的寄存器被用于优化的想法提出了一个问题:优化的时间和地点实际上值得吗?

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

其他代码可以被扭曲和挤压以摆脱循环,并且它无关紧要,因为程序计数器几乎从不存在。

我知道你没有问过这个问题,但根据我的经验,99%的性能问题与编译器优化没什么关系。它们与过度设计有关。

作者: Mike Dunlavey 发布者: 24.02.2009 09:43

8

当然,这取决于编译器。我见过x86编译器发出的优化代码,它们可以自由地使用EBP寄存器作为通用寄存器。(我不记得我注意到哪个编译器。)

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

作者: Greg Hewgill 发布者: 23.02.2009 08:49

4

但是,x86的寄存器很少

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

作者: MSN 发布者: 23.02.2009 09:00

1

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

你节省了多少钱?这值得么?

作者: dwc 发布者: 23.02.2009 08:51
32x32