0

我正在阅读Richard Blum的专业汇编语言,当您输入呼叫时,您应该将寄存器的值复制到,他还提供了以下模板:ESPEBP

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

我不明白为什么这是必要的。当你在函数中 push 一些东西时,你显然打算把它弹回来,从而恢复ESP到它的原始值。

那么为什么要有这个模板呢?
无论如何,寄存器有什么用EBP

我显然错过了一些东西,但它是什么?

4

1 回答 1

2

当你在函数中 push 一些东西时,你显然打算把它弹回来

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

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

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

于 2013-04-07T14:57:07.277 回答