protected_gdt: .gdt_start: ; we need to start with a null gdt dd 0 dd 0 .gdt_code: dw 0xffff dw 0x0000 db 0x00 db 10011010b db 11001111b db 0x0000 .gdt_data: dw 0xffff dw 0x0000 db 0x00 db 10010010b db 11001111b db 0x0000 .gdt_end: .descriptor: dw .gdt_end - .gdt_start - 1 dq .gdt_start PROTECTED_CODE_SEGMENT equ .gdt_code - .gdt_start PROTECTED_DATA_SEGMENT equ .gdt_data - .gdt_start long_gdt: .gdt_start: ;and now we set up a temporary GDT creating a 1:1 mapping dw 0xffff dw 0 db 0 ;this is the invalid GDT db 0 db 1 db 0 ;now for the code GDT: .gdt_code: dw 0 ; segment limit 15:00 (I don't think this matters in 64 bit mode!) dw 0 ; base address 15:00 db 0 ; base address 23:16 db 10011010b ;1st flags and type. The first four bits (1010) are type, and the last are flags. See https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf db 10101111b ;1111 is segment limit continued. 0: available, 0: 64 bit (change?), 1: 32 bit segment, 1: granularity (shifts 3 hex didgets to get all of memory) db 0 .gdt_data: dw 0 dw 0 db 0 db 10010010b db 00000000b db 0 .gdt_end: ; later calculates offset in defs below .descriptor: dw .gdt_end - .gdt_start - 1 dq .gdt_start LONG_CODE_SEGMENT equ .gdt_code - .gdt_start LONG_DATA_SEGMENT equ .gdt_data - .gdt_start