当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《EBP帧指针寄存器的用途是什么?》经验,为你挑选了3个好方法。

我是汇编语言的初学者,并注意到编译器发出的x86代码通常在释放/优化模式下保持帧指针,当它可以使用EBP寄存器时.

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



1> Sedat Kapano..:

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

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

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

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


编译器可能知道它对ESP的作用.其他点有效,但是+1
即使在使用`-fomit-frame-pointer`编译的代码中,现代调试器也可以进行堆栈回溯.该设置是最近gcc中的默认设置.
@SedatKapanoglu:`.eh_frame_hdr`部分也用于运行时异常.你可以在Linux系统的大多数二进制文件中找到它(带有`objdump -h`),`/ bin/bash`约为16k,GNU`/bin/true`约为572B,`ffmpeg`为108k.有一个gcc选项可以禁用生成它,但它是一个"普通"数据部分,而不是默认情况下`strip`删除的调试部分.否则,您无法通过没有调试符号的库函数进行回溯.该部分可能比它替换的`push/mov/pop`指令更大,但它的运行时成本几乎为零(例如uop缓存).
关于"诸如第一个参数总是在EBP-4":不是EBP + 8上的第一个参数(在x86上)?
@SedatKapanoglu:数据部分记录了必要的信息:http://yosefk.com/blog/getting-the-call-stack-without-a-frame-pointer.html

2> Mike Dunlave..:

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

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

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

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

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

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


@augurar语言演变:"提出问题"现在只是意味着"提出问题".作为过时使用的规定主义者,不会增加任何东西.
取消帧指针也可以为每个函数调用节省一些指令,这本身就是一个小优化.顺便说一句,你对"问题"的使用是不正确的; 你的意思是"提出问题".

3> Greg Hewgill..:

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

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

推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有