【发布时间】:2015-02-25 09:33:34
【问题描述】:
我知道这是一个非常基本的问题,但在这里:
我开始学习汇编程序,并试图了解堆栈的工作原理。
首先,当我将值传递给汇编函数时,我会像这样访问它:
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 再做一次有什么好处?
有没有人有关于如何学习堆栈如何工作以便学习这些堆栈指针、返回地址等的好的学习工具(针对傻瓜型)的提示?我还没有找到任何关于它如何工作的好的视觉演示。 谢谢!
【问题讨论】:
-
假设你在你的函数中将一些东西压入堆栈。如果您将当前堆栈指针复制到函数开头的
ebp,则在访问参数时不必跟踪对esp所做的更改。 -
谢谢,@Michael。我想我只是对他们每个人(
%ebp和%esp)所做的事情以及我应该如何跟踪堆栈和地址感到困惑。 -
顺便说一句,第二个并不好,除非有别的东西强迫你建立一个标准的堆栈框架。这显然是更多的指令,而且您通常不会在设置本地后更改 esp,因此 esp 与 ebp 一样稳定。
-
你应该在互联网上找到很多关于堆栈如何工作的好草图。也许谷歌书籍也可以帮助你。当您想了解 EBP 的用途时,您需要在 Google 上搜索“堆栈框架”。堆栈框架是在堆栈“内部”创建的自制结构。这是高级编程语言编译器在调用函数时生成的东西。每次调用函数时,编译器都会为被调用函数创建一个栈帧。但是当您自己编写汇编代码时,您可以根据需要手动创建堆栈帧。但你不必这样做。
-
使用 EBP 而不是 ESI 的原因是因为 EBP 默认访问堆栈段,而 ESI 访问数据段。这些可以被覆盖,但目的是让寄存器以这种方式使用。