为什么要在电话中将ESP保留在EBP中?

时间:2013-04-07 13:11:04

标签: function assembly x86 callstack cpu-registers

我正在Professional Assembly Language Richard Blum阅读,当您输入电话时,您应该将ESP注册的值复制到EBP,他还提供了以下模板:

function_label:
    pushl %ebp
    movl %esp, %ebp
    < normal function code goes here>
    movl %ebp, %esp
    popl %ebp
    ret

我不明白为什么这是必要的。当您在函数内部推送某些内容时,您显然打算将其弹回,从而将ESP恢复为原始值。

为什么要有这个模板呢? 那么EBP寄存器的用途是什么?

我显然错过了什么,但它是什么?

1 个答案:

答案 0 :(得分:2)

  

当你在函数内部推送某些内容时,你显然打算将其弹回

这只是使用堆栈的部分原因。更常见的用法是你的代码片段中缺少的一个,存储局部变量。在设置EBP之后看到的下一个常见代码是ESP上的减法,相当于本地变量存储所需的空间量。这当然也很容易平衡,只需在功能结尾添加相同的数量。当代码也使用诸如C99可变长度数组或非标准但通常可用的_alloca()函数之类的东西时,它变得更加困难。能够从EBP恢复ESP使这很简单。

或许更重要的是,像这样设置堆栈帧是而不是。大多数x86编译器都支持称为“帧指针省略”的优化选项。在MSVC上使用GCC的-fomit-frame-pointer / Oy打开。这使得EBP寄存器可用于一般用途,这对x86非常有用,因为它缺乏cpu寄存器。

但优化有一个非常严重的缺点。如果EBP寄存器指向堆栈帧的开头,则执行堆栈遍历变得非常困难。当您需要调试代码时,这很重要。堆栈跟踪对于了解代码如何最终崩溃非常重要。当您从客户那里获得崩溃的“核心转储”时,这是非常宝贵的。如此有价值的微软同意{2}在Windows二进制文件上为客户提供了诊断崩溃的机会。