【发布时间】:2014-12-10 22:42:27
【问题描述】:
在第 3.4.2 节中,IA32 popl 指令被描述为从 堆栈的顶部到目标寄存器,然后递增堆栈 指针。所以,如果我们有一个 popl REG 形式的指令,它就是等价的 到代码序列:
movl (%esp),REG //Read REG from stack
addl $4,%esp //Increment stack pointer
A.根据问题 4.7 中所做的分析,此代码序列是否正确 描述指令 popl %esp 的行为?解释一下。
B.您如何重写代码序列以便正确描述两者 REG 是 %esp 以及任何其他寄存器的情况?
问题 4.7:
下面的汇编代码函数让我们确定指令的行为 IA32 的 popl %esp:
1 .text
2 .globl poptest
3 poptest:
4 pushl %ebp
5 movl %esp, %ebp
6 pushl $0xabcd Push test value
7 popl %esp Pop to stack pointer
8 movl %esp, %eax Set popped value as return value
9 leave Restore stack and frame pointers
10 ret
我们发现这个函数总是返回 0xabcd。这对 popl %esp 的行为意味着什么?还有哪些 Y86 指令会有完全相同的行为?
对于第一个问题中的代码序列是否正确描述了指令 popl %esp 的行为,我感到很痛苦。起初我认为是的,因为它从堆栈中获取 REG 就像 popl 会返回值(我可能错了),然后它将 esp 增加 4 以从堆栈中删除该实例。
但后来我遇到了语句“popl %esp 指令在将旧堆栈顶部的数据写入目标之前递增堆栈指针。”
如果是这种情况,那么在将值放入目标寄存器之前应该发生 4 到 esp 的增量,使得
movl (%esp),REG //Read REG from stack
addl $4,%esp //Increment stack pointer
popl %esp 的错误表示。
谁能澄清它是否真的没有正确描述行为或popl %esp?
【问题讨论】:
标签: assembly stack cpu-registers x86