bits 32 %define MULTIBOOT_PAGE_ALIGN 0x00000001 %define MULTIBOOT_MEMORY_INFO 0x00000002 %define MULTIBOOT_HEADER_MAGIC 0x1BADB002 %define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO) %define CR0_MP 0x00000002 /* bit 01 -> enable monitor coprocessor */ %define CR0_NE 0x00000020 /* bit 05 -> enable native x87 FPU mode */ %define CR0_WP 0x00010000 /* bit 16 -> enable write protect (for CoW) */ %define CR0_AM 0x00040000 /* bit 18 -> enable alignment checking */ %define CR0_PG 0x80000000 /* bit 31 -> enable paging */ %define PAGE_OFFSET 0xC0000000 %define GDT_BASE (0xFFFFFFFF - (PAGE_OFFSET - 1)) %define KERNEL_CS 0x8 %define KERNEL_DS 0x10 section .setup align 4 tmp_gdtr: dw ((3 * 8) - 1) tmp_gdta: dd tmp_gdt align 4 tmp_gdt: ; NULL DESCRIPTOR dw 0x0000 dw 0x0000 dw 0x0000 dw 0x0000 ; KERNEL CODE dw 0xFFFF ; segment limit 15-00 dw 0x0000 ; base address 15-00 db 0x00 ; base address 23-16 db 0x9A ; P=1 DPL=00 S=1 TYPE=1010 (exec/read) db 0xCF ; G=1 DB=1 0=0 AVL=0 SEGLIM=1111 db (GDT_BASE >> 24) ; base address 31-24 (0x40) ; KERNEL DATA dw 0xFFFF ; segment limit 15-00 dw 0x0000 ; base address 15-00 db 0x00 ; base address 23-16 db 0x92 ; P=1 DPL=00 S=1 TYPE=0010 (read/write) db 0xCF ; G=1 DB=1 0=0 AVL=0 SEGLIM=1111 db (GDT_BASE >> 24) ; base address 31-24 (0x40) align 4 multiboot_header: dd MULTIBOOT_HEADER_MAGIC dd MULTIBOOT_HEADER_FLAGS dd -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) dd 0 ; header_addr dd 0 ; load_addr dd 0 ; load_end_addr dd 0 ; bss_end_addr dd 0 ; entry_addr dd 0 ; mode_type dd 0 ; width dd 0 ; height dd 0 ; depth section .text global _start extern setup_tmp_pgdir extern bss_init extern gdt_init extern get_last_boot_addr extern kmain _start: cli lgdt [tmp_gdtr] ; load GDTR with the temporary GDT mov cx, KERNEL_DS mov ds, cx mov es, cx mov fs, cx mov gs, cx mov ss, cx jmp KERNEL_CS:setup_kernel align 4 global setup_kernel setup_kernel: mov esp, PAGE_OFFSET + 0x10000 ; default stack address (0xC0000000 + 0x10000) push 0 ; reset EFLAGS popf push ebx ; save Multiboot info structure push eax ; save Multiboot magic value call setup_tmp_pgdir mov cr3, eax mov eax, cr0 and eax, 0x00000011 ; disable all, preserve ET & PE (GRUB) or eax, 0x80000000 ; CR0_PG ; enable PG or eax, 0x40000 ; CR0_AM ; enable AM or eax, 0x10000 ; CR0_WP ; enable WP or eax, 0x20 ; CR0_NE ; enable NE or eax, 0x02 ; CR0_MP ; enable MP mov cr0, eax call bss_init ; initialize BSS segment call gdt_init ; setup and load the definitive GDT call get_last_boot_addr pop ecx ; restore Multiboot magic value pop ebx ; restore Multiboot info structure push eax ; save the last boot address push ebx ; save Multiboot info structure push ecx ; save Multiboot magic value call kmain jmp $