global _start extern entry %define FLAGS 0b10 %define MAGIC 0x1BADB002 %define CHECKSUM -(MAGIC + FLAGS) section .multiboot align 4 dd MAGIC dd FLAGS dd CHECKSUM section .bss align 16 resb 32768 stack_top: section .bss align 4096 pml4: resb 4096 pdpt: resb 4096 pd: resb 4096 section .data align 8 gdt64: dq 0x0000000000000000 .code: dq 0x00AF9A000000FFFF .descriptor: dw .end - gdt64 - 1 dq gdt64 .end: section .data align 8 multiboot_info: dq 0 section .text bits 32 _start: mov esp, stack_top ; Multiboot will place a magic value in eax ; If this magic value is not present, then we might not have multiboot info in ebx, ; therefore we throw an error cmp eax, 0x2BADB002 jne error ; Save multiboot info pointer for later mov [multiboot_info], ebx ; Check if cpuid is available by flipping bit 21 ; in the eflags register and checking if the cpu flipped it back pushfd pop eax mov ecx, eax xor eax, 1 << 21 push eax popfd pushfd pop eax ; If cpuid is available, eax should be different than ecx xor eax, ecx jz error ; Finally restore eflags register to the original value push ecx popfd ; Check if extended cpuid is available by calling cpuid with 0x80000000, ; If cpuid is available, eax will be greater than 0x80000000 after the call mov eax, 0x80000000 cpuid cmp eax, 0x80000001 jb error ; Check if long mode is available by calling cpuid with 0x80000001 ; this will place the extended features of the cpu in edx ; Bit 29 tells us if long mode is supported or not mov eax, 0x80000001 cpuid test edx, 1 << 29 jz error ; Enable PAE by setting bit 5 in cr4 to 1 mov eax, cr4 or eax, 1 << 5 mov cr4, eax ; pml4[0] -> pdpt mov eax, pdpt or eax, 0x03 mov [pml4], eax ; pdpt[0] -> pd mov eax, pd or eax, 0x03 mov [pdpt], eax ; Map first 32 2mb pages for the kernel for a total of 64mb mov edi, pd mov eax, 0x83 mov ecx, 32 .setup_pd: mov [edi], eax add eax, 0x200000 add edi, 8 loop .setup_pd ; Load cr3 with the address of pml4 mov eax, pml4 mov cr3, eax lgdt [gdt64.descriptor] ; Enable long mode by setting bit 8 to 1 in EFER (Extended Feature Enable Register) mov ecx, 0xc0000080 rdmsr or eax, 1 << 8 wrmsr ; Enable paging by setting bit 31 in cr0 to 1 mov eax, cr0 or eax, 1 << 31 mov cr0, eax jmp 0x8:long_mode error: cli mov byte [0xb8000], 'E' mov byte [0xb8002], 'R' mov byte [0xb8004], 'R' .hang: hlt jmp .hang section .text bits 64 long_mode: ; Clear segment registers in long mode xor ax, ax mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax ; Finally, we call in to c mov rdi, [multiboot_info] call entry .hang: hlt jmp .hang