2013-04-07 55 views
0

我读Professional Assembly Language通过Richard Blum,当你输入一个电话你应该ESP寄存器的值复制到EBP,他还提供了下面的模板:为什么要在呼叫中保持EBP中的ESP?

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

我不明白为什么这个是必要的。当你在功能内部推动某个东西时,你显然打算将其弹回来,从而将ESP恢复为原始值。

那么,为什么这个模板?
无论如何,EBP注册的用途是什么?

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

+0

这被称为堆栈框架,它可以用于创建从函数完成后被破坏的局部变量。 – 2013-04-07 13:22:07

+0

@Sp。为什么我不弹出这些局部变量? /为什么弹出不会摧毁它们?对不起,有点慢。 – MasterMastic 2013-04-07 13:23:30

+0

也许你需要看看这个答案,更好地解释,http://stackoverflow.com/questions/3699283/what-is-stack-frame-in-assembly#answer-3700219 – 2013-04-07 13:27:32

回答

2

当你按下功能里面的东西,你显然打算弹出回来

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

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

虽然这种优化有一个非常严重的缺点。如果没有EBP寄存器指向堆栈帧的开始,则执行堆栈遍历将非常困难。当你需要调试你的代码。堆栈跟踪对于了解代码如何最终崩溃非常重要。当您从客户那里得到崩溃的“核心转储”时,这是非常宝贵的。微软同意在Windows二进制文件上同意turn off the optimization,以便为其客户提供诊断崩溃的机会。