78 lines
1.9 KiB
NASM
78 lines
1.9 KiB
NASM
; 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
|
|
|
|
; Load the gdt_ptr
|
|
lgdt [gdt_ptr]
|
|
|
|
mov cr3, pml4_table
|
|
|
|
mov rax, cr4
|
|
or rax, 0x20 ; Enable PAE
|
|
mov cr4, rax
|
|
|
|
mov ecx, 0xC0000080 ; IA32_EFER MSR
|
|
rdmsr
|
|
or rax, 0x00000100 ; Set LME (Long Mode Enable) bit
|
|
wrmsr
|
|
|
|
; Enable long mode
|
|
mov rax, cr0
|
|
or rax, 0x80000000 ; Set the Long Mode Enable (LME) bit
|
|
mov cr0, rax
|
|
|
|
; 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:
|
|
|
|
gdt_ptr:
|
|
dw 0 ; Limit (set by linker/code later)
|
|
dq 0 ; Base Address (set by linker/code later)
|
|
gdt_start: ; Start of the actual GDT entries
|
|
; Entry 0: Null Descriptor
|
|
dq 0x0000000000000000
|
|
; Entry 1: 64-bit Code Segment Descriptor
|
|
; Entry 2: 64-bit Data Segment Descriptor
|
|
gdt_end:
|
|
|
|
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:
|
|
|
|
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
|
|
|
|
|