2025-06-28 06:11:09 +00:00
;start.s
;Entrypoint for kernel, hello world!
2025-06-11 03:41:51 +00:00
bits 3 2
2025-06-11 04:27:15 +00:00
;Some symbols we'll need from other files...
2025-06-11 03:41:51 +00:00
extern k e r n _ m a i n
2025-06-11 04:27:15 +00:00
extern g d t r
2025-07-15 18:52:48 +00:00
extern _ k e r n e l _ s t a r t
extern _ k e r n e l _ e n d
2025-06-11 03:41:51 +00:00
;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
; 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-11 04:27:15 +00:00
;We're gonna throw the TSS here too.
2025-07-15 18:52:48 +00:00
section . t s s a l i g n =16 n o b i t s
2025-06-10 13:17:21 +00:00
tss :
2025-06-11 03:41:51 +00:00
resb 1 0 4
2025-07-15 18:52:48 +00:00
section . b o o t s t r a p _ t a b l e s n o b i t s a l i g n =4096
bootstrap_PD :
resb 4 0 9 6
bootstrap_PT :
resb 4 0 9 6
2025-06-10 13:17:21 +00:00
2025-06-11 03:41:51 +00:00
;Actual code. Entry point goes here!
2025-07-15 18:52:48 +00:00
section . l o w e r _ t e x t e x e c
2025-06-11 03:41:51 +00:00
;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-07-15 18:52:48 +00:00
lgdt [ g d t r - 0 x C 0 0 0 0 0 0 0 ]
2025-06-11 03:58:28 +00:00
;Now we start by setting the code segment (CS) with a far jump...
2025-07-15 18:52:48 +00:00
jmp 0 x08 : g d t _ l o a d
2025-06-11 03:41:51 +00:00
2025-06-11 03:58:28 +00:00
2025-07-15 18:52:48 +00:00
gdt_load :
2025-06-11 03:58:28 +00:00
;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
2025-07-15 18:52:48 +00:00
;So, we want to set up a page table and page directory. Let's take inventory.
;eax - preserve, mb_magic
;ebx - preserve, mb_info
;ecx,edx,esi - can use
;Can technically use esp as the stack is set to stack_top later.
;ecx = our current indexing for pages, this is a 4K-aligned address
mov e c x , 0 x0
;edi = our pointer to the current page table entry. Array of 4byte entries. It's at, of course, where we put it earlier.
;Worth noting that it's actually physically at ~1M with the kernel. The pointer, however, is virtually inclined. So we need to adjust.
mov e d i , b o o t s t r a p _ P T - 0 x C 0 0 0 0 0 0 0
page_alloc_loop :
;If we're lower than our kernel, skip this page. If we've passed our kernel, we're done mapping.
cmp e c x , _ k e r n e l _ s t a r t
jl n e x t _ p a g e
cmp e c x , _ k e r n e l _ e n d - 0 x C 0 0 0 0 0 0 0
jge p a g e _ a l l o c _ d o n e
;Okay, we're in kernel zone. Let's map this one.
;Let's make a page table entry in edx.
;The top bits for the page table entry are just the upper bits of the address, so we dont need to touch it.
mov e d x , e c x
;Set last two bits, "present" and "writeable". Later on we'll make a proper page table with proper permissions, but we're bootstrapping here.
or e d x , 0 x00 3
;edi holds a pointer to the page table entry, so dereference it and throw our new entry (in edx) to it. Done!
mov [ e d i ] , e d x
next_page :
;address page + 1
add e c x , 0 x10 0 0
;page table entry + 1
add e d i , 4
jmp p a g e _ a l l o c _ l o o p
page_alloc_done :
;By now we've mapped the kernel in a page table! Let's map VGA too, we'll need that address later.
mov d w o r d [ b o o t s t r a p _ P T - 0 x C 0 0 0 0 0 0 0 + 1 0 2 3 * 4 ] , 0 x00 0 B 8 0 0 0 | 0 x27
;We have our page tables mapped to the phys addr of kernel + VGA. Time to add them to our page directory!
;First identity maps, second maps to higher half.
mov d w o r d [ b o o t s t r a p _ P D - 0 x C 0 0 0 0 0 0 0 ] , b o o t s t r a p _ P T - 0 x C 0 0 0 0 0 0 0 + 0 x00 3
mov d w o r d [ b o o t s t r a p _ P D - 0 x C 0 0 0 0 0 0 0 + 4 * ( 0 x C 0 0 0 0 0 0 0 > > 2 2 ) ] , b o o t s t r a p _ P T - 0 x C 0 0 0 0 0 0 0 + 0 x00 3
;Let's set it! You do this with cr3.
mov e c x , b o o t s t r a p _ P D - 0 x C 0 0 0 0 0 0 0
mov c r3 , e c x
;Enable paging in cr0
mov e c x , c r0
or e c x , 0 x80 0 1 0 0 0 0
mov c r0 , e c x
;Done! Leave to the higher half!
lea e c x , s e t u p _ c _ e n v
jmp e c x
section . t e x t
setup_c_env :
;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