I am learning MS-DOS source code during that i am in difficulty with some line of code:
BIOSSEG: EQU 40H
BIOSLEN: EQU 2048
DOSLEN: EQU 8192
In the next page there are some lines of code,
INIT:
XOR BP,BP ; Set up stack just
; below I/O system
MOV SS,BP
MOV SP,BIOSSEG*16
If we put the value 0000 to a segment, then how can we put that segment just after another segment?
Clearly BP and SS will contain hex values 0000H.
I want to understand how MOV SS,BP will set up stack just below I/O system.
Under the x86-16 architecture the segments are massively overlapping. They have a distance of 16 bytes (but a size of 64KiB). Each memory location can be addressed by 4096 combinations of segment address and offset.
The actual memory location can be calculated as
location = 16 * segment + offsetPutting 0 into SS generally makes the first 64KiB of memory accessible. Multiplying BIOSSEG with 16 and using it as the offset is the actual trick. It sets the offset address of the stack, which is stored in the stack pointer, to the beginning of the BIOS data segment. The stack extends downwards from there.
The start of the BIOS data is at memory location
400h = 16 * 40h + 0h.So
40h:0his equivalent to0h:400h. But you can only use the second notification for the stack (of the two shown, you could e.g. also use1h:3f0hor10h:300hto the same effect) to get a positive offset address (forSP) and being able to access addresses downwards.Normally the IVT (Interrupt Vector Table) is stored at the beginning of the memory. It contains 256 adresses (for the 256 interrupts) with 4 bytes each, taking 256 * 4 bytes = 400h.
So theoretically there would be no room for a stack.
Either the IVT is moved for this system in some way (if this is possible) or the higher interrupts are overwritten by the stack. The higher interrupts are only used by software, whereas the CPU and hardware typically use interrupts
0htofhand70hto77h, making the upper88hinterrupts potentially overwritable, if not called by any software with theintinstruction.So the stack could have
4 bytes * 88h = 520 bytes.Typically the 256 bytes beginning at
30h:0are used at POST and early bootup for a stack, overwriting the interrupt vectors for interruptsC0htoFFh.Alternatively hardware interrupts can be temporarily deactivated by a flag except the non-maskable interrupt (NMI), which is
int 2h.