[bits 16] switch_to_protected_mode: cli ; We disable interrupts... lgdt [gdt_descriptor] ; ... load the GDT descriptor... mov eax, cr0 or eax, 0x1 ; ... set 32-bit mode in CR0 mov cr0, eax jmp CODE_SEG:switch32 ; ... and perform a far jump using a different segment [bits 32] switch32: ; We're not in 32 bit mode, yay! mov ax, DATA_SEG ; Time to update the segment registers with their new values mov ds, ax mov ss, ax mov es, ax ; Bonus: we have two more user-defined ; segment registers when in 32-bit mode mov fs, ax mov gs, ax mov ebp, 0x90000 ; We also move the stack further up mov esp, ebp call BEGIN_32BIT ; We call back into mbr.s which loads the kernel