SECTION .text USE16 %include "gdt.asm" %include "thunk.asm" stage2.entry: mov si, stage_msg call print mov al, '3' call print_char call print_line ; enable A20-Line via IO-Port 92, might not work on all motherboards in al, 0x92 or al, 2 out 0x92, al protected_mode: ; disable interrupts cli ; load protected mode GDT lgdt [gdtr] ; set protected mode bit of cr0 mov eax, cr0 or eax, 1 mov cr0, eax ; far jump to load CS with 32 bit segment ; We need to do this because we are entering 32-bit mode, ; but the instruction pipeline still has 16-bit instructions. ; ; gdt.pm32_code is a multiple of 8, so it always ends with three zero bits. ; The GDT spec abuses this fact, and uses these last three bits to store other ; data (table type and privilege). In this case, 000 is what we need anyway. ; ; Also note that CS isn't an address in protected mode---it's a GDT descriptor. jmp gdt.pm32_code:protected_mode_inner ; We can now use 32-bit instructions! USE32 protected_mode_inner: ; load all the other segments with 32 bit data segments mov eax, gdt.pm32_data mov ds, eax mov es, eax mov fs, eax mov gs, eax mov ss, eax ; Place stage 3 stack at 448 KiB ; (512KiB minus 64KiB disk buffer) mov esp, 0x70000 ; push arguments to `start()` mov eax, thunk.int10 push eax ; Call `start()`. ; 0x18 skips ELF headers. mov eax, [stage3 + 0x18] call eax .halt: ; Halt if `start()` ever returns (it shouldn't, but just in case) ; Without this, we'll try to execute whatever comes next in memory. cli hlt jmp .halt