2

What's the physical consequence of PUSH to a FULL stack Amazingly When allocating only 2 bytes [1 word] for the stack and PUSH three words then pop them into different registers ,it's done without any errors What could I say about the stack contents when PUSHing the second item

Here's the stack segment definition :

Stack_segment_name segment para stack
db 2 dup(0) ;define your stack segment
Stack_segment_name ends

Here's the code :

Code_segment_name segment
Main_prog PROC FAR

assume     SS:Stack_segment_name,CS:Code_segment_name,DS:Data_segment_name,ES:Data_segment_name

MOV AX,Data_segment_name ; load the starting address of the data
MOV DS,AX ; segment into DS reg.

MOV AX,1715H
MOV BX,1518H
MOV CX,2944H
PUSH AX
PUSH BX
PUSH CX
POP SI 
POP DI  
POP DX



MOV AH,4CH
INT 21H


Main_prog endp
Code_segment_name ends
    end Main_prog

After Executing the code:

SI=2944H
DI=1518H
DX=1715H
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 2
    The stack segment on an 8086 (like ALL segments on an 8086) is 64K. The SP (stack pointer) is a 16-bit register, so it wraps around if/when you exceed the 64K stack. – Chris Dodd Jan 02 '16 at 07:58
  • OK it wraps around but this conflicts with the declared size of 2 bytes in the stack segment definition of the actual program. – Abdelrhman Abotaleb Jan 02 '16 at 08:22
  • 3
    The size of the stack in assembler doesn't translate to the same fixed size in memory.All physical segments are 64k in size.The size you specified is a minimum guarantee of a number of bytes before the stack wraps.So if you specify a stack with 2 bytes in it SS will be automatically set to the beginning of the paragraph in memory where your 2 bytes are. _SP_ will be set to the size of the stack -in your case 2. So you end up with something like SS:0002h as your starting stack position. The first word you push will be at SS:0000h and the second word you push will wrap and be placed at SS:0fffeh – Michael Petch Jan 02 '16 at 08:37
  • And my comments are in the context of 8086 real mode. – Michael Petch Jan 02 '16 at 08:52
  • 2
    I don't think you ran the experiment you think you ran. I don't see how you set the stack pointer the stack area you declared. I think your program is running with a stack area provided by the loader, which is generally pretty big. (If you do set SP to the area you defined, your pushes will overwrite some bytes beyond the end of it. If those bytes are critical to something, your program will fail. If not, it will succeed by accident, which answers your original question). See http://stackoverflow.com/a/34546569/120163 – Ira Baxter Jan 02 '16 at 10:17
  • @IraBaxter : `segment para stack` is the old way of defining a stack segment. The alternative in newer (at the time) assemblers was to use the simplified directive `.stack`. The DOS EXE loader will fill in the stack segment (*SS:SP*) automatically based on such a definition in the assembly code. This stack information becomes part of the EXE header. – Michael Petch Jan 10 '16 at 13:30
  • @MichaelPetch: Are you saying that the program as presented gets it ESP set to the declared stack segment by the loader (interpreting the EXE header)? – Ira Baxter Jan 10 '16 at 14:56
  • @IraBaxter Well in the case of 8086 which this is tagged it would be SS and SP that are set (no ESP) based on the `segment para stack`. Of course SS is relative to the file, so gets fixed up before being set by the EXE loader. And masm/tasm when generating DOS apps usually set SP to the size of the stack segment. But yes, the EXE header contains an SS segment that gets fixed up and a value for SP, and both will be set by the EXE loader if instructed to. – Michael Petch Jan 10 '16 at 15:08

1 Answers1

5

The stack that you declare in your program is different from how the CPU sees the stack.

On 8086 the CPU treats a 64KB chunk of memory that starts at linear address SS*16 as the stack.

When you declared a stack of only 2 bytes, the 1st push landed where you expected it, but hereafter the stackpointer SP was 0. The next push therefore subtracted 2 (giving 0xFFFE) and stored its operand there in memory. Similarly for the 3rd push. Since there were no memory conflicts all seemed well...

Fifoernik
  • 9,779
  • 1
  • 21
  • 27