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

; the data GDT is the exact same, and it overlaps. We don't care, we'll be booting into long mode right after then programming in C
; TODO: clarify once you figure out what you're doing
.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
