pushl%esp在存储之前或之后会更新ESP吗? [英] Does pushl %esp update ESP before or after storing?

查看:217
本文介绍了pushl%esp在存储之前或之后会更新ESP吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Y86指令pushl都将堆栈指针减4,并将寄存器值写入内存.因此,尚不清楚处理器执行指令pushl %esp时应执行的操作,因为要推送的寄存器正在由同一条指令更改.可能发生两个事件:

The pushl Y86 instruction both decrements the stack pointer by 4 and writes a register value to memory. So it's not clear what the processor should do when it executes the instruction pushl %esp, since the register being pushed is being changed by the same instruction. Two possible events can occur:

(1)按下%esp的原始值,或(2)按下%esp的减小值.

(1) push the original value of %esp, or (2) push the decremented value of %esp.

有鉴于此,我们如何修改等同于pushl REG的代码,以解决并容纳这些歧义(因为REG可以是%esp以及任何其他寄存器)?

In light of this, how could we modify this code-equivalent of pushl REG to account for, and accomdate, these ambiguities (being that REG can be %esp as well as any other register)?:

subl $4,%esp                   Decrement stack pointer
movl REG,(%esp)                Store REG on stack


类似地,指令popl %esp可以将%esp设置为从内存读取的值或递增的堆栈指针.如何更改此代码以适应这些歧义?


Similarly, the instruction popl %esp could either set %esp to the value read from memory or to the incremented stack pointer. How could this code be changed to accommodate for these ambiguities?:

movl (%esp),REG                Read REG from stack
addl $4,%esp                   Increment stack pointer

推荐答案

y86基于x86. push x86指令集参考手册说(正确) :

y86 is based on x86. The x86 instruction-set reference manual entry for push says (correctly):

PUSH ESP指令将执行该指令之前存在的ESP寄存器的值压入.

The PUSH ESP instruction pushes the value of the ESP register as it existed before the instruction was executed.

pop :

POP ESP指令在将堆栈顶部的旧数据写入目标之前将堆栈指针(ESP)递增.

The POP ESP instruction increments the stack pointer (ESP) before data at the old top of stack is written into the destination.

因此,在pop %esp情况下,增量丢失.尽管大多数实际的CPU可能会加载到临时内部存储中,而不是在寻址模式下实际使用更新的ESP值,但此顺序具有相同的效果.

So in the pop %esp case, the increment is lost. This sequence has the same effect, although most real CPUs probably load into temporary internal storage instead of actually using an updated ESP value in the addressing mode.

add   $4, %esp
movl  -4(%esp), %esp

但是pop %esp这样做不需要更新FLAGS,并且在add和mov之间没有中断或信号处理程序的可能性. (单独的添加/移动序列在上下文中不安全,在当前上下文中,低于%esp的任何内容都可以被中断处理程序异步覆盖.)

But pop %esp does that without updating FLAGS, and without a possibility of an interrupt or signal-handler between the add and mov. (The separate add/mov sequence isn't safe in contexts where anything below the current %esp can be asynchronously overwritten by an interrupt handler.)

大概y86与x86的功能相同. 您可以轻松(并且应该)与调试器联系,以了解您最喜欢的y86模拟器如何处理这种极端情况.通过查看内存(或在其后添加pop %eax),可以轻松测试push %esp.

Presumably y86 does the same thing as x86. You can easily (and should) check with a debugger to see how your favourite y86 simulator handles this corner case. push %esp is easy to test by looking at memory (or adding a pop %eax after it).

同时测试这两者会造成混淆,并且如果您弹出的值与旧的堆栈指针相同,您将无法分辨出两者之间的区别.可能先按0(或将0存储到(%esp)),然后按pop %esp,然后使用调试器查看寄存器中的值. (之后是否崩溃代码都没有关系,您只是在使用调试器.)

Testing both at once would get confusing, and if the value you pop is the same as the old stack pointer, you can't tell the difference. Probably push a 0 (or store a 0 to (%esp)), then pop %esp and see what value is in the register with a debugger. (It doesn't matter if your code crashes afterwards, you're just using a debugger.)

我没有检查y86是否支持x86之类的push $0movl $0, (%esp).我想如果它被支持(直接到内存),它将是immovl $0, (%esp).如果不是,则将寄存器清零并将其推入.

I didn't check if y86 supports push $0 or movl $0, (%esp) like x86. I guess it would be immovl $0, (%esp) if it's supported (immediate to memory). If not, then zero a register and push that.

这篇关于pushl%esp在存储之前或之后会更新ESP吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆