I'm getting confused on what does pop
actually do in assembly. Does pop
move the value PUSH
ed onto the stack last (meaning it doesn't apply if we MOV
a value after the the last element PUSH
ed) or does it just pop whatever value that's last on the stack (thus, applying to both MOV
and PUSH
), or does it pop what ever value pointed to by the stack pointer? Consider the following code:
push $4
mov $5, -4(%esp)
add $4, %esp (esp pointing to an unknown value)
pop %ebp
So in this code will the value poped into ebp
be 4, 5, or the unknown value pointed to by esp
?
The latter
POP EBP
is equivalent to
MOV EBP, [ESP]
ADD ESP, 4 ; but without modifying flags, like LEA ESP, [ESP+4]
(in Intel syntax - target on the left, source on the right)
PUSH does:
ESP := ESP-4 ; for x86; -8 for x64
MEMORY[ESP]:=<operandvalue>
POP does:
<operandtarget>:=MEMORY[ESP];
ESP:=ESP+4 ; for x86; +8 for x64
It is much easier to understand what machine instructions do if you write their descriptions down in pseudo code like this. The Intel reference manuals are full of such pseudo code,
and it is worth your time and trouble to get them, and read the details for yourself.
Regarding your specific question: Your store of $5 into -4(%esp) is a valid machine instruction, and the processor will execute it without complaint, but it is really extremely unsafe programming. If the processor takes a trap or interrupt just after that instruction, the processor state (is usually) saved "on top of the stack", and will overwrite your value. Since interrupts occur asynchronously, the behaviour you will see is that, rarely, the $5 gets lost. That makes for an extremely hard program to debug.
The "add $4" moves the ESP back to the place before the push instruction. So, you cannot say anything about the value popped into ebp except it is "unknown" as you suggested as one of your options.