MBOOT_PAGE_ALIGN equ 1<<0 MBOOT_MEM_INFO equ 1<<1 MBOOT_HEADER_MAGIC equ 0x1badb002 MBOOT_HEADER_FLAGS equ MBOOT_PAGE_ALIGN | MBOOT_MEM_INFO MBOOT_CHECKSUM equ -(MBOOT_HEADER_MAGIC + MBOOT_HEADER_FLAGS) section .multiboot dd MBOOT_HEADER_MAGIC dd MBOOT_HEADER_FLAGS dd MBOOT_CHECKSUM dd 0x00000000; header_addr dd 0x00000000; load_addr dd 0x00000000; load_end_addr dd 0x00000000; bss_end_addr dd 0x00000000; entry_addr dd 0x00000000; mode_type dd 0x00000000; width dd 0x00000000; height dd 0x00000000; depth [bits 32] section .xos_boot_text extern main extern PREKERNEL_STACK_TOP global _start _start: global prekernel_entry prekernel_entry: cli cld ; Setting up the stack. mov ebp, PREKERNEL_STACK_TOP mov esp, ebp ; Save entry point to one of callee-saved regs. mov esi, ecx ; PAE is required for x86_64 call check_for_pae ; Checking for long mode. call check_for_long_mode ; x86_64 required paging enabled, thus 1GB of physical memmory is mapped ; for booting the kernel without any problems. call setup_tables ; Enabling long mode with a 32-bit compatibility submode. call enable_long_mode ; Just give control to jumper. jmp jump_to_entry64 CPUID_FEATURE_PAE equ (1 << 6) check_for_pae: push ebp mov ebp, esp push ebx mov eax, 0x1 cpuid test edx, CPUID_FEATURE_PAE jz pae_unsupported pop ebx pop ebp ret pae_unsupported: push pae_unsupported_msg call early_boot_print_string hlt CPUID_FEATURE_LONG_MODE equ (1 << 29) check_for_long_mode: push ebp mov ebp, esp push ebx mov eax, 0x80000001 cpuid test edx, CPUID_FEATURE_LONG_MODE jz long_mode_unsupported pop ebx pop ebp ret long_mode_unsupported: push long_mode_unsupported_msg call early_boot_print_string hlt setup_tables: push ebp mov ebp, esp push edi mov edi, table0 xor eax, eax mov ecx, 4096 rep stosb mov edi, table1 xor eax, eax mov ecx, 4096 rep stosb mov edi, table2 xor eax, eax mov ecx, 4096 rep stosb mov eax, table1 add eax, 0x3 mov DWORD [table0], eax mov eax, table2 add eax, 0x3 mov DWORD [table1], eax mov edi, table2 mov eax, 0x83 mov ecx, 512 .table_fillup_last: mov DWORD [edi], eax add eax, 0x200000 add edi, 8 loop .table_fillup_last pop edi pop ebp ret enable_long_mode: push ebp mov ebp, esp ; Setting table mov eax, table0 mov cr3, eax ; Enabling PAE mov eax, cr4 or eax, 1 << 5 mov cr4, eax ; Enabling Long Mode mov ecx, 0xc0000080 rdmsr or eax, 1 << 8 wrmsr mov eax, cr0 or eax, 1 << 31 mov cr0, eax pop ebp ret VIDEO_MEMORY equ 0xb8000 WHITE_ON_BLACK equ 0x0f global early_boot_print_string early_boot_print_string: push ebp mov ebp, esp push esi push ecx mov esi, [ebp+8] mov ecx, VIDEO_MEMORY mov ah, WHITE_ON_BLACK _print_string_loop: lodsb; Load from esi to al then increment esi test al, al jz _print_string_end mov [ecx], ax add ecx, 2 jmp _print_string_loop _print_string_end: mov eax, esi sub eax, [ebp+8] pop ecx pop esi mov esp, ebp pop ebp ret ; Access bits PRESENT equ 1 << 7 NOT_SYS equ 1 << 4 EXEC equ 1 << 3 DC equ 1 << 2 RW equ 1 << 1 ACCESSED equ 1 << 0 ; Flags bits GRAN_4K equ 1 << 7 SZ_32 equ 1 << 6 LONG_MODE equ 1 << 5 align 32 gdt_begin: gdt_null: dq 0x0 gdt_code: dd 0xffff db 0x0 db PRESENT | NOT_SYS | EXEC | RW db GRAN_4K | LONG_MODE | 0xF db 0x0 gdt_data: dd 0xffff db 0x0 db PRESENT | NOT_SYS | RW db GRAN_4K | SZ_32 | 0xF db 0x0 gdt_tss: dd 0x00000068 dd 0x00cf8900 gdt_end: gdt_descriptor: dw gdt_end - gdt_begin - 1 dd gdt_begin dd 0x0 CODE_SEG equ gdt_code - gdt_begin DATA_SEG equ gdt_data - gdt_begin jump_to_entry64: lgdt [gdt_descriptor] jmp CODE_SEG:main_entry64 [bits 64] main_entry64: cli mov ax, DATA_SEG mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax mov edi, esi mov esi, ebx call main hlt global set_cr3 set_cr3: mov cr3, rdi ret global jump_to_kernel jump_to_kernel: mov rax, cr3 mov cr3, rax call rsi jmp $ pae_unsupported_msg: db "Required PAE Feature is unavailable, stopping...", 0 long_mode_unsupported_msg: db "Required Long Mode Feature is unavailable, stopping...", 0 section .bss table0: align 4096 resb 4096 table1: align 4096 resb 4096 table2: align 4096 resb 4096