push和pop如何在程序集中工作

Gam*_*anA 8 x86 assembly callstack

我对pop组装中的实际操作感到困惑.是否pop将值PUSHed最后移动到堆栈上(意味着如果我们MOV在最后一个元素之后的值,它不适用PUSH)或者它只是弹出堆栈中最后一个值(因此,应用于两个MOVPUSH),或者它会弹出堆栈指针指向的值吗?请考虑以下代码:

push $4
mov $5, -4(%esp)
add $4, %esp (esp pointing to an unknown value)
pop %ebp
Run Code Online (Sandbox Code Playgroud)

所以在这段代码中,值的值ebp是4,5,还是指向的未知值esp

500*_*ror 17

后者

POP EBP
Run Code Online (Sandbox Code Playgroud)

相当于

MOV EBP, [ESP]
ADD ESP, 4           ; but without modifying flags, like  LEA ESP, [ESP+4]
Run Code Online (Sandbox Code Playgroud)

(在Intel语法中 - 左侧为目标,右侧为源)

  • 这是正确的,但是ESP的增加有效地阻止了它进一步访问.从理论上讲,中断可能会立即发生并重新使用堆栈中的那个区域进行存储,但我实际上并不认为中断会再次使用环3堆栈. (3认同)

Ira*_*ter 15

PUSH:

 ESP := ESP-4  ; for x86; -8 for x64
 MEMORY[ESP]:=<operandvalue>
Run Code Online (Sandbox Code Playgroud)

POP确实:

 <operandtarget>:=MEMORY[ESP];
 ESP:=ESP+4    ; for x86; +8 for x64
Run Code Online (Sandbox Code Playgroud)

如果用这样的伪代码写下它们的描述,那么理解机器指令会更容易.英特尔参考手册中充满了这样的伪代码,值得您花时间和麻烦来获取它们,并自己阅读详细信息.

关于你的具体问题:你的商店5美元到-4(%esp)是一个有效的机器指令,处理器将执行它没有抱怨,但它真的是非常不安全的编程.如果处理器在该指令之后接受陷阱或中断,则处理器状态(通常)保存在"堆栈顶部",并将覆盖您的值.由于中断是异步发生的,因此您将看到的行为很少会导致$ 5丢失.这使得调试程序非常困难.

"add $ 4"将ESP移回推送指令之前的位置.所以,你不能说ebp中弹出的值,除非它是你所建议作为你选择之一的"未知".