On the wikpedia page about .COM files https://en.wikipedia.org/wiki/COM_file it reads:
.COM files in DOS set all x86 segment registers to the same value and the SP (stack pointer) register to 0xFFFE, thus the stack begins at the very top of the memory segment and works down from there.
But this actually sets the stack to begin one word below the top of the segment. When pushing a value on the stack the CPU will decrement SP to 0xFFFC and store the value there, thus wasting the top word of the segment. What is the reason for DOS not setting SP to 0 instead?
This is for compatibility with CP/M.
In CP/M you could simply return from your program using ret
and your program would exit cleanly. This was achieved by having a 0x0000
at the top of the stack, and having an int 20h
instruction at address 0x0000
. Even though int 20h
is DOS' official way to quit a program, the option to quit the program using call 0
was kept from CP/M, and the outermost-scope ret
works the same as well since it returns to 0
.
In order to have that 0x0000
word at the top of the stack, you need to start the usable stack 2 bytes further down, obviously. That's why SP
is initially at 0xFFFE
, pointing to that 0x0000
word which in turn points to the int 20h
instruction.