3

I'm learning assembly and wondering what happend when you pop an empty stack or increasing SP (Stack Pointer) when it's already FFFE for example:

seg1 segment 
       org 100h 
       pop ax
       mov ah,4ch 
       int 21h
seg1 ends

When I run the program through the debugger I saw that SP wil point to SP = 0000 after pop command is executed. Why the SP point to 0000? Is it because the max SP in the memory is FFFF and it just loop to the first point? (I know that SP will only increase or decrease by 2 because push and pop is always 2 byte) And will the program pop anythign at SP = 0000 when the command is executed?

I'm using a86 macro assembler, Oracle VM VirtualBox. Thank you.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Andre
  • 41
  • 1
  • 6

3 Answers3

4

This effect is called "wraparound". FFFE plus 2 would be 10000, but the first bit is just cut away, so the result is 0000.

This is useful, among others, for signed operations: FFFE is equivalent to -2. -2 + 2 = 0.

And yes, the next pop will load the value at SS:0000 and increment SP, whereas a push will also cause a wraparound and store a value at SS:FFFE.

rkhb
  • 14,159
  • 7
  • 32
  • 60
3

SP is 16 bit register.

When you POP, SP has "2" added to it. FFFE+2 produces the value 0.

This happens without error on older architectures (e.g., X8086) and probably in x86-32 running in 16 bit real mode (I'd have to check the manuals). While it does happen, you should consider this to be programming error on your part, as it violates the intent of the stack pointer, to linearly scan the stack area.

On x86-32 or -64 in protected mode, falling of the edge of the stack area will generally produce an illegal memory access, caused by the OS very carefully marking the area beyond your valid stack is "not valid".

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
2

You should really make it a habit consulting the CPU documentation. It should all be in there.

In short, in 16-bit and 32-bit CPU modes push and pop generally don't care much about the value of the stack pointer register for the purpose of incrementing or decrementing. The register value simply wraps around 0, the same way as when adding or subtracting a value to/from any other general purpose register. The only thing that matters is whether or not the address in the stack pointer register is within the stack segment limits when the stack memory is accessed. In real mode, which seems to be the case, all segments have the size of 64KB and all offsets from 0 to 0xFFFF are valid. Therefore, if your SP is always properly aligned (that is, it's a multiple of 2), pushing or popping a single 16-bit word should never cause any problem. However, you should remember that in real mode the current stack is used by interrupt service routines and you should always have enough space for them (unless you're operating with interrupts disabled). And you should remember that a bug in your code may make the stack pointer point into the code or the data of your program and therefore corrupt it.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180