Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly popl%esp的替代方案_Assembly_Stack_Cpu Registers_X86 - Fatal编程技术网

Assembly popl%esp的替代方案

Assembly popl%esp的替代方案,assembly,stack,cpu-registers,x86,Assembly,Stack,Cpu Registers,X86,在第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以及任何其他寄存器的

在第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指令在旧堆栈顶部的数据写入目标之前递增堆栈指针。”

如果是这种情况,那么esp的增量4应该在将值放入目标寄存器之前发生,使

movl (%esp),REG //Read REG from stack
addl $4,%esp //Increment stack pointer
popl%esp的表示不正确


有人能澄清一下它是否真的没有正确地描述行为或popl%esp吗?

事实上,这对于
pop
来说是一个错误的等价物。有趣的是,这也是英特尔在官方指令集参考中使用的。但至少他们在课文中说得很清楚。更好的等效代码是:

leal 4(%esp), %esp ; use lea to preserve flags (thanks to @Sparky)
movl -4(%esp), REG
然而,这只是一个逻辑等价物,因为实际上有人(如中断或信号处理程序)可以破坏两条指令之间堆栈上的值。原始代码没有遇到这个问题


请注意,这也适用于内存操作数,手册中说:“如果将ESP寄存器用作基址寄存器来寻址内存中的目标操作数,POP指令将在递增ESP寄存器后计算操作数的有效地址。”。我们也涵盖了该案例。

除了已经被列为潜在问题的问题外,“addl$4,%esp”还影响eflags登记册。为了补偿这一点,“leal4(%esp),%esp”可以用在它的位置。@Jester对于
push%esp
?@bluejamesbond:那将是
movl%esp,-4(%esp);leal-4(%esp),%esp
,但有相同的警告。