This page looks best with JavaScript enabled

MercuryOS Stack

 ·  🎃 kr0m

The CPU is capable of storing information in registers, but this limits us a lot in terms of size. To solve this problem, we use main memory (RAM). To read/write data in RAM, we need to know the memory address in question. Since this can be cumbersome, the stack was devised. This is nothing more than a memory region where data can be stacked and then unstacked.

Before we start, it is recommended that you read these previous articles:


The CPU has two instructions to access the stack, these are push/pop, which perform the functions of stacking and unstacking data respectively.

We can stack and unstack, but we still don’t know where. Through the bp/sp registers, we will know the memory addresses of the base and the top of the stack.

Something very important is that the stack grows towards lower memory addresses. If we stack data, it will be stored in RAM at the address bp up to sp = bp-size.

In the following program, we will “push” several values and then “pop” them.

vi boot_sect_stack.asm

mov ah, 0x0e ; tty mode

mov bp, 0x8000 ; this is an address far away from 0x7c00 so that we don't get overwritten
mov sp, bp ; if the stack is empty then sp points to bp

push 'A'
push 'B'
push 'C'

; recover our characters using the standard procedure: 'pop'
; We can only pop full words, but int10 uses al register
; so we need an auxiliary register to copy data to al
pop bx
mov al, bl
int 0x10 ; prints C

pop bx
mov al, bl
int 0x10 ; prints B

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

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

We generate the image:

nasm -f bin boot_sect_stack.asm -o boot_sect_stack.bin

We load it into qemu:

qemu-system-x86_64 boot_sect_stack.bin

SeaBIOS (version rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org)  
iPXE (http://ipxe.org) 00:03.0 C980 PCI2.10 PnP PMM+07F91410+07EF1410 C980  
                                                                                
Booting from Hard Disk...  
CBA

As we can see, the values have been popped off in reverse order of their insertion, as it should be. Someone might think that the bp register doesn’t add any value since we can push and pop using sp, and it’s true, but we wouldn’t be able to read the values of the function’s variables since their address is calculated based on the bp.

If you liked the article, you can treat me to a RedBull here