pushl%esp是否在存储之前或之后更新ESP?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pushl%esp是否在存储之前或之后更新ESP?相关的知识,希望对你有一定的参考价值。
pushl
Y86指令将堆栈指针递减4并将寄存器值写入存储器。因此,当执行指令pushl %esp
时,处理器应该做什么并不清楚,因为被推送的寄存器正被相同的指令改变。可能发生两种可能的事件:
(1)推动%esp
的原始值,或(2)推动%esp
的递减值。
鉴于此,我们如何修改这个代码相当于pushl REG
来解释和容纳这些歧义(REG可以是%esp以及任何其他寄存器)?:
subl $4,%esp Decrement stack pointer
movl REG,(%esp) Store REG on stack
类似地,指令popl %esp
可以将%esp
设置为从存储器读取的值或增加的堆栈指针。如何更改此代码以适应这些歧义?:
movl (%esp),REG Read REG from stack
addl $4,%esp Increment stack pointer
y86基于x86。 x86 instruction-set reference manual entry for push
说(正确):
PUSH ESP指令按下执行指令之前存在的ESP寄存器的值。
在将旧堆栈顶部的数据写入目标之前,POP ESP指令递增堆栈指针(ESP)。
因此在pop %esp
案例中,增量会丢失。此序列具有相同的效果,但大多数实际CPU可能会加载到临时内部存储器中,而不是在寻址模式下实际使用更新的ESP值。
add $4, %esp
movl -4(%esp), %esp
但pop %esp
在没有更新FLAGS的情况下做到了这一点,并且没有在add和mov之间存在中断或信号处理程序的可能性。 (单独的add / mov序列在上下文中不安全,其中当前%esp
以下的任何内容都可以被中断处理程序异步覆盖。)
据推测,y86与x86完全相同。您可以轻松(并且应该)使用调试器检查您最喜欢的y86模拟器如何处理此角落情况。通过查看记忆(或在其后添加push %esp
),pop %eax
很容易测试。
一次测试会让人感到困惑,如果弹出的值与旧的堆栈指针相同,则无法区分。可能推动0
(或将0
存储到(%esp)
),然后pop %esp
并查看调试器中寄存器的值。 (如果您的代码事后崩溃并不重要,那么您只需使用调试器。)
我没有检查y86是否像x86那样支持push $0
或movl $0, (%esp)
。我想如果它得到支持(直接记忆),那将是immovl $0, (%esp)
。如果没有,那么将寄存器归零并推送它。
以上是关于pushl%esp是否在存储之前或之后更新ESP?的主要内容,如果未能解决你的问题,请参考以下文章