当我将%esp移动到%ebp时会发生什么?

时间:2015-02-25 09:33:34

标签: assembly stack

我知道这是一个非常基本的问题,但在这里:

我开始学习汇编程序,我正在努力了解堆栈的工作原理。

首先,当我将值传递给汇编程序函数时,我会像这样访问它:

movl 4(%esp),%eax  # first parameter
movl 8(%esp),%ebx  # second parameter

但我被告知最好这样做:

push %ebp
movl %esp,%ebp
# and then I'd access the values on %ebp:
movl 8(%ebp),%eax
movl 12(%ebp),%eax
pop %ebp

好的,这有什么区别?当我直接从%esp访问值时,它们是否已经在堆栈中?使用push再次执行此操作有什么好处?

有没有人有一个关于如何学习堆栈如何工作的好学习工具(对于dummies-type)的提示,这样可以学习这些堆栈指针,返回地址等等?我没有找到任何关于它如何工作的良好视觉演示。 谢谢!

2 个答案:

答案 0 :(得分:2)

在大多数情况下使用%ebp有历史原因:在16位程序中,如" movw 2(%sp),%ax" x86 CPU不支持,因为x86 CPU仅支持%bx,%si,%di和%bp寄存器用于内存寻址。所以在16位程序中你不能使用%sp,所以你改用%bp。

使用优化良好的现代编译器时,您将看不到" push"和" mov%esp,%ebp" 32位代码中的指令,但代码看起来就像你的第一个例子(" 4(%esp)"而不是" 8(%ebp)")。

此类编译器有时会将%ebp寄存器用于不同目的。

有一个用例仍然需要%ebp:alloca()函数:此函数通过执行" sub%eax,%esp"来保留堆栈中的内存。 (或类似的)指令。在这条指令之后,你不再知道你的论点在哪里。

但是在32位代码中使用" flat"内存布局(%ds =%ss)您也可以使用任何其他寄存器而不是%ebp。

答案 1 :(得分:1)

差异和原因都与堆栈帧有关。以下链接有一个相当不错的摘要(如果我自己这么说)。

What is stack frame in assembly?