; File: boot.asm global _start extern kmain section .multiboot ; Multiboot header dd 0x1BADB002 ; magic number dd 0x00000003 ; flags dd -(0x1BADB002 + 0x00000003) ; checksum section .text [bits 32] _start: mov esp, kernel_stack_top cli ; Clear interrupts ; Load the gdt_ptr lgdt [gdt_ptr] mov eax, pml4_table mov cr3, eax ; Load the PML4 table into CR3 ; Link PML4 -> PDPT mov dword [pml4_table], pdpt_table + 0x3 mov dword [pml4_table + 4], 0x0 ; Link PDPT -> PD mov dword [pdpt_table], pd_table + 0x3 mov dword [pdpt_table + 4], 0x0 ; Link PD -> 2MB Physical Page 0 mov dword [pd_table], 0x83 mov dword [pd_table + 4], 0x0 mov eax, cr4 or eax, 0x20 ; Enable PAE mov cr4, eax mov ecx, 0xC0000080 ; IA32_EFER MSR rdmsr or eax, 0x00000100 ; Set LME (Long Mode Enable) bit wrmsr ; Enable long mode mov eax, cr0 or eax, 0x80000000 ; Set the Long Mode Enable (LME) bit mov cr0, eax ; Jump to 64-bit code Segment jmp 0x08:long_mode_start section .bss ; We define the stack size and labels in the uninitialized data section (.bss) kernel_stack_bottom: ; Reserve 16 KB for the stack resb 16 * 1024 kernel_stack_top: pml4_table: ; Define a simple PML4 table here (identity mapping for simplicity) ; In a real kernel, you would set up proper paging structures resb 4096 ; Reserve 4 KB for the PML4 table pml4_end: pdpt_table: resb 4096 ; Reserve 4 KB for the PDPT table pdpt_end: pd_table: resb 4096 ; Reserve 4 KB for the PD table pd_end: section .data gdt_ptr: dw (gdt_end - gdt_start - 1) ; Limit (set by linker/code later) dq gdt_start ; Base Address (set by linker/code later) gdt_start: ; Start of the actual GDT entries ; Entry 0: Null Descriptor dq 0x0000000000000000 dq 0x00AF9A000000FFFF dq 0x00AF92000000FFFF gdt_end: section .text [bits 64] ; Tell NASM to assemble in 64-bit mode long_mode_start: ; 1. Pass GRUB's Multiboot info (in ebx) as the first C argument (in rdi) ; We must use the 64-bit register RDI, but the data is in the 32-bit EBX. ; Moving ebx to rdi automatically clears the upper 32 bits of rdi. mov rdi, rbx ; 2. Call the C kernel's main function call kmain ; 3. If kmain ever returns, halt the CPU hlt