2

I know the pop instruction does this:

Loads the value from the top of the stack to the location specified with the destination operand (or explicit opcode) and then increments the stack pointer

but I can't access the data when I pop it!

I have this code:

mov ah , 0x0e
mov bp, 0x8000
mov sp , bp
push 'A'

mov al , [0x7ffe]
int 0x10    ; print A

pop bx
mov al ,bl
int 0x10    ; print A

mov al , [0x7ffe]
int 0x10    ; **print random chare !**


jmp $
times 510-($-$$) db 0
dw 0xaa55

Why does the third int 0x10 not print 'A'?

  • 5
    Because the `int 0x10` itself uses the stack and by popping you released the ownership so it gets overwritten. – Jester May 25 '21 at 23:09
  • 1
    Related for the title question: [Is it valid to write below ESP?](https://stackoverflow.com/q/52258402) (moving (E)SP after a store is basically equivalent to storing below (E)SP in the first place). Of course, user-space under a modern OS means your stack won't get used for async interrupt handlers. e.g. under Linux, `int 0x80` system calls don't affect the stack of the user-space process. – Peter Cordes May 25 '21 at 23:55
  • 2
    @PeterCordes The stack will still get used for signal handler frames among other things when running under UNIX. – fuz May 26 '21 at 07:54
  • 1
    Right, that's what my answer on that linked question says. :P I probably shouldn't have mentioned async hardware interrupts, since the point I really wanted to make was no synchronous clobbering from the use of `int` or `syscall` instructions. – Peter Cordes May 26 '21 at 07:56

1 Answers1

3

At the first mov al, [0x7ffe] you have access to the memory at address 0x7FFE because you just reserved it for your stack with push, but after you used pop the stackpointer got increased and gave free that address. You no longer have ownership of it and so other processes can use that address and will overwrite your stored value. That's why you get an apparently random number at that address.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
Ambotz
  • 121
  • 7
  • 3
    If you read `[0x7ffe]` right away after `pop`, instead of running instructions that use the stack like `int`, then it's *likely* you'll still see your value. (Since this is 16-bit real-mode, there isn't a separate kernel stack for interrupt context). If you did remove int, then only if an external interrupt came in between the push and the load (or a debugger used that space while single stepping) would it have been messed up. DOS is not a multi-tasking OS so it's not "other processes" in the sense of operating-system processes like Unix has. Perhaps better to say "other things". – Peter Cordes May 27 '21 at 21:32