我试图了解函数prolog如何在汇编中工作。我的书显示以下代码:
push %ebp
movl %ebp, %esp
在push的定义中,它表示它将ESP的值减少4(字节?),然后将操作数放入ESP指定的内存中。但是这不会覆盖一些数据,如图所示?
此外我假设每个段都是4(字节?)但是我很确定函数可以有超过4个字节的已分配堆栈空间?
接下来,第二条指令将ESP中的内容移动到EBP中,但是有什么需要呢?那已经存在了吗?当调用pop
时,它如何知道从堆栈中带走多少? (我解释的所有内容都假设指令mov
和push
从指向它们的位置开始,并在执行任何操作时上升到存储器中。
答案 0 :(得分:3)
x86机器上的堆栈从较高地址到较低地址逐渐减少
这由push
指令的语义反映出来:
push ebp
在语义上等同于
sub esp, 04h
mov DWORD [esp], ebp
从技术上讲,我们说堆栈是完全下降,完整因为esp
总是指向推送的最后一个值而降序原因很明显。
事实上,堆栈指针上方的所有内容都被某些代码推送,因此它被初始化并隐式分配内存。
相反,堆栈下面的所有内容是可用内存。
因此push ebp
不会覆盖任何有用的内容,通常 push 不会这样做。
mov ebp, esp
不接受 EBP 的内容(本来是mov ebp, DWORD [esp]
,而是复制 ESP的内容将自己注册到 EBP
使用 EBP 有两个原因:
最后,pop
指令与push
指令类似,其操作数决定了操作的大小:push ax/eax/rax
分别在堆栈上推送2,4和8个字节。
程序员仍然有责任保持堆栈平衡,如果需要甚至对齐,但这通常没什么可问的。
注意:x86内存是字节可寻址的,所以当进行间接寄存器寻址时,即当我们访问像mov eax, DWORD [ebx]
这样的寄存器中指定的地址时,该数字表示地址就字节而言。
通过 N 递减该数字意味着将 N 字节读取更低,因此从 ESP 中减去4会在中的新旧地址之间留下4个字节ESP 。
答案 1 :(得分:0)
布拉
寄存器推送消耗了多少字节取决于寄存器大小,而寄存器大小又取决于芯片架构。在您的示例中,您使用32位寄存器,因此每次寄存器推送将消耗4个字节。
对于x86说明,此description可能非常有用。