2025-06-11 03:41:51 +00:00
;C main function for our kernel
;See: kernel.c
bits 3 2
extern k e r n _ m a i n
;This will be our entrypoint function name - gotta initialize it now as global so the linker knows later.
global s t a r t
2025-05-23 05:18:12 +00:00
2025-06-11 03:41:51 +00:00
;multiboot for GRUB to boot it. Ideally stage01_bootloader will be able to support the multiboot standard.
;regardless of who's doing it, we have to set the required stuff
MB_ M A G I C e q u 0 x1 B A D B 0 0 2 ; bytes that bootloader will use to find this place
MB_ F L A G S e q u ( 1 < < 0 ) | ( 1 < < 1 ) ; flags request the following from the bootloader: maintain page boundaries + provide a memory map
MB_ C H E C K S U M e q u ( 0 - ( M B _ M A G I C + M B _ F L A G S ) ) ; Fails if checksum doesn't pass. Kind of arbitrary, but required.
2025-05-23 05:18:12 +00:00
2025-06-11 03:41:51 +00:00
;Now we actually place the multiboot stuff into the resulting executable...
section . m u l t i b o o t a l i g n =4
dd M B _ M A G I C
dd M B _ F L A G S
dd M B _ C H E C K S U M
2025-05-23 05:18:12 +00:00
2025-06-11 03:41:51 +00:00
; Set up for C code. Practically the only requirement for C-generated assembly to work properly is alignment and the presence of a stack.
section . b s s a l i g n =16
2025-05-23 05:18:12 +00:00
stack_bottom :
2025-06-11 03:41:51 +00:00
resb 4 0 9 6 ; 4096 bytes (4kb) large stack. by skipping some amount of data (and eventually filling it with zeroes?), we've essentially just reserved space for our stack.
;Remember, stack grows DOWNWARD! So the last thing in the section -> the highest memory address -> the very first thing on the stack!
;Therefore, we put a label here to represent the top of our stack for later.
2025-05-23 05:18:12 +00:00
stack_top :
2025-06-10 13:17:21 +00:00
tss :
2025-06-11 03:41:51 +00:00
resb 1 0 4
2025-05-23 05:18:12 +00:00
2025-06-10 13:17:21 +00:00
2025-06-11 03:41:51 +00:00
;We're putting the GDT here. I'll be thoroughly commenting the first entry for my own understanding. Rest will be minimal.
section . g d t _ s e c t
gdt :
;Null descriptor
dd 0 x00 0 0 0 0 0 0
dd 0 x00 0 0 0 0 0 0
;Kernel code segment.
;Limit: in 4kib pages. 0xFFFFF * 4K = full address space.
dw 0 x F F F F
;Base: Start at 0. We want the whole thing.
dw 0
;ALSO BASE: bits 16-23. All zeroes, still.
db 0
;Access byte. Defines flags for access permissions to the segment. This segment is:
;RX, and code/data segment
db 0 b10 0 1 1 0 1 0
;Next two segments are nibbles so I put them together (cant db only a nibble at once).
;Upper limit bits (right hand nibble) is all ones to fill out the full 4gib in pages
;Flags (left hand nibble) are set to say that the limit is meant to be read as pages, and we're working in 32bit.
db 0 b11 0 0 1 1 1 1
;Final upper base bits. Still zero lol.
db 0
;Done! Now we move onto our next table entries, they are back to back.
;Kernel Data Segment
dw 0 x F F F F
dw 0
db 0
db 0 b10 0 1 0 0 1 0
db 0 b11 0 0 1 1 1 1
db 0
;User Code Segment
dw 0 x F F F F
dw 0
db 0
db 0 b11 1 1 1 0 1 0
db 0 b11 0 0 1 1 1 1
db 0
;User Data Segment
dw 0 x F F F F
dw 0
db 0
db 0 b11 1 1 0 0 1 0
db 0 b11 0 0 1 1 1 1
db 0
;Task State Segment
;For a lot of this it's going to be zeroes so we can do it dynamically later (such as finding &tss).
;Really, we just want to set the access bytes correctly.
dd 0
db 0
db 0 b10 0 0 1 0 0 1
dw 0
gdtr :
dw g d t r - g d t - 1
dd g d t
2025-05-23 05:18:12 +00:00
2025-06-11 03:41:51 +00:00
;Actual code. Entry point goes here!
section . t e x t
;Here it is!
2025-05-23 05:18:12 +00:00
start :
2025-06-11 03:41:51 +00:00
;We made a GDT! Let's use it!
2025-06-11 03:58:28 +00:00
lgdt [ g d t r ]
;Now we start by setting the code segment (CS) with a far jump...
jmp 0 x08 : s e g m e n t _ b e _ g o n e
2025-06-11 03:41:51 +00:00
2025-06-11 03:58:28 +00:00
segment_be_gone :
;Now we go ahead and dump our kernel mode data segment (0x10) into the rest of our segments.
;Also preserving eax because it has the bootloader's multiboot magic in it and I want to check it in main.
mov c x , 0 x10
mov d s , c x
mov e s , c x
mov s s , c x
mov f s , c x
mov g s , c x
;Lets set up the stack. Stack grows downward on x86. We did the work earlier of defining where the top of the stack is, so just tell esp.
2025-06-11 03:41:51 +00:00
mov e s p , s t a c k _ t o p ;set the stack pointer
push e b x
push e a x
;To C-land!
2025-05-23 05:18:12 +00:00
call k e r n _ m a i n
2025-06-11 03:41:51 +00:00
;You should never get here, but in case you do, we will just hang.
2025-05-23 05:18:12 +00:00
hang :
2025-06-11 03:41:51 +00:00
cli ;Interrupts: off
hlt ;Halt!
jmp h a n g ;just in case...
2025-05-23 05:18:12 +00:00
2025-06-11 03:58:28 +00:00