当我将 %esp 移动到 %ebp 时会发生什么?
What happens when I move %esp to %ebp?
我知道这是一个非常基本的问题,但问题是:
我开始学习汇编程序,我正在尝试了解堆栈的工作原理。
起初,当我将值传递给汇编程序函数时,我会像这样访问它:
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做有什么好处?
有没有人提供关于如何学习堆栈如何工作的好学习工具(针对傻瓜类型)的提示,以便可以学习这些堆栈指针、return 地址等等?我还没有找到任何关于它如何工作的良好视觉演示。
谢谢!
区别和原因都与堆栈帧有关。下面的link总结得还不错(如果我自己这么说的话)。
What is stack frame in assembly?
在大多数情况下使用 %ebp 有历史原因:在 16 位程序中,x86 CPU 不支持像 "movw 2(%sp), %ax" 这样的指令,因为 x86 CPU 只支持 %bx、%si、%di 和 %bp 寄存器用于内存寻址。所以在 16 位程序中你不能使用 %sp 所以你使用 %bp 代替。
使用优化良好的现代编译器时,您将不会再在 32 位代码中看到 "push" 和 "mov %esp, %ebp" 指令,但代码看起来像您的第一个示例 ("4( %esp)" 而不是 "8(%ebp)")。
此类编译器有时会出于不同目的使用 %ebp 寄存器。
有一个用例仍然需要 %ebp:alloca() 函数:此函数通过执行 "sub %eax, %esp"(或类似)指令在堆栈上保留内存。在这条指令之后,你不再知道你的参数在哪里。
然而,在具有 "flat" 内存布局 (%ds=%ss) 的 32 位代码中,您也可以使用任何其他寄存器代替 %ebp。
我知道这是一个非常基本的问题,但问题是:
我开始学习汇编程序,我正在尝试了解堆栈的工作原理。
起初,当我将值传递给汇编程序函数时,我会像这样访问它:
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做有什么好处?
有没有人提供关于如何学习堆栈如何工作的好学习工具(针对傻瓜类型)的提示,以便可以学习这些堆栈指针、return 地址等等?我还没有找到任何关于它如何工作的良好视觉演示。 谢谢!
区别和原因都与堆栈帧有关。下面的link总结得还不错(如果我自己这么说的话)。
What is stack frame in assembly?
在大多数情况下使用 %ebp 有历史原因:在 16 位程序中,x86 CPU 不支持像 "movw 2(%sp), %ax" 这样的指令,因为 x86 CPU 只支持 %bx、%si、%di 和 %bp 寄存器用于内存寻址。所以在 16 位程序中你不能使用 %sp 所以你使用 %bp 代替。
使用优化良好的现代编译器时,您将不会再在 32 位代码中看到 "push" 和 "mov %esp, %ebp" 指令,但代码看起来像您的第一个示例 ("4( %esp)" 而不是 "8(%ebp)")。
此类编译器有时会出于不同目的使用 %ebp 寄存器。
有一个用例仍然需要 %ebp:alloca() 函数:此函数通过执行 "sub %eax, %esp"(或类似)指令在堆栈上保留内存。在这条指令之后,你不再知道你的参数在哪里。
然而,在具有 "flat" 内存布局 (%ds=%ss) 的 32 位代码中,您也可以使用任何其他寄存器代替 %ebp。