SECTION .text
USE16

protected_mode:

.func: dd 0

.entry:
    ; 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 are in 32-bit mode, but instruction pipeline
    ; has 16-bit instructions.
    jmp gdt.pm32_code:.inner

    ; 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.
 


USE32

.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

    ; jump to specified function
    mov eax, [.func]
    jmp eax