;; look at added segments descriptors for long mode
GDT:
; first descriptor must be null descriptor
NULLDescriptor:
dw 0x0000
dw 0x0000
db 0x0000
db 0x00
db 0x00
db 0x00
; IA-32e mode code descriptor for kernel
IA_32eCODEDESCRIPTOR:
; BASE: 0x00000000
; LIMIT: 0xFFFFF
; P=1, DPL=0, Code Segment, Execute/Read
; G=1, D=0, L=1
dw 0xFFFF ; Limit (16:0]
dw 0x0000 ; Base (32:16)
db 0x00 ; Base (40:32]
db 0x9A ; P/DPL/S/Type (48:40]
db 0xAF ; G/D/L/LIMIT (56:48]
db 0x00 ; BASE (64:56]
; IA-32e mode data and stack descriptor for kernel
IA_32eDATADESCRIPTOR:
; BASE: 0x00000000
; LIMIT: 0xFFFFF
; P=1, DPL=0, Data Segment, Read/Write
; G=1, B=0, L=1
dw 0xFFFF ; Limit (16:0]
dw 0x0000 ; Base (32:16)
db 0x00 ; Base (40:32]
db 0x92 ; P/DPL/S/Type (48:40]
db 0xAF ; G/D/L/LIMIT (56:48]
db 0x00 ; BASE (64:56]
; protected mode's code descriptor (CS)
CODEDESCRIPTOR:
; BASE: 0x00000000
; LIMIT: 0xFFFFF
; P=1, DPL=0, Code Segment, Execute/Read
; G=1, D=1, L=0
dw 0xFFFF ; Limit (16:0]
dw 0x0000 ; Base (32:16)
db 0x00 ; Base (40:32]
db 0x9A ; P/DPL/S/Type (48:40]
db 0xCF ; G/D/L/LIMIT (56:48]
db 0x00 ; BASE (64:56];; Because of added descriptors, far jmp instruction should be changed
;; change jmp dword 0x08:0x10200 to jmp dword 0x18:0x10200 and
;; change jmp dword 0x08: (PROTECTEDMODE - $$ + 0x10000) to
;; jmp dword 0x18: (PROTECTEDMODE - $$ + 0x10000)
START:
mov ax, 0x1000
mov ds, ax
mov es, ax
;; A20 Gate activation
; activate A20 by using BIOS service, if it fails
; try activating by using system control port
mov ax, 0x2401 ; 0x2401: activate
int 0x15 ; 0x15: miscellaneous system services
jc .A20GATEERROR ; if cflag is set, it fails
jmp .A20GATESUCCESS
.A20GATEERROR:
in al, 0x92 ; 0x92: system control port
or al, 0x02 ; set A20 Gate bit (set bit 1)
and al, 0xFE ; prevent reset (clear bit 0)
out 0x92, al
.A20GATESUCCESS:
cli ; ignore interrupt until interrupt handler is set
lgdt [GDTR]
; PG=0, CD=1, NW=0, AM=0, WP=0, NE=0, ET=1, EM=0, MP=1, PE=1
; CD means cache disable
; PE is protection enable
; EM, ET, MP, PE are FPU-related fields and they are set
; although their feature is not used in IA-32 mode. they will
; be explained in detail later. Don't worry about the fields now
mov eax, 0x4000003B
mov cr0, eax
; 0x18 is offset to the protected mode's code segment descriptor
; from GDT PROTECTEDMODE - $$ + 0x10000 is offset to the code from
; segment
jmp dword 0x18: (PROTECTEDMODE - $$ + 0x10000)
[BITS 32]
PROTECTEDMODE:
; set code and data segment
mov ax, 0x20 ; 0x20 = offset to IA-32 mode's data segment descriptor
mov ds, ax
mov es, ax ; it is not required to set es, fs, and gs
mov fs, ax
mov gs, ax
; set stack segment
; because bootloader is not used anymore stack is from 0x0C700 ~ 0xFFFE0
mov ss, ax ; data segment is also used as stack segment
mov esp, 0xFFFE
mov ebp, 0xFFFE
;; print message
; printMessage(success_message, 2, 0)
push (SWITCHSUCCESSMESSAGE - $$ + 0x10000)
push 2
push 0
call PRINTMESSAGE
add esp, 12 ; 4 bytes (Protected Mode) * 3
; 0x18 is offset to IA-32's code descriptor
jmp dword 0x18:0x10200
-
Because IA-32e mode supports compatibility mode, the structure of descriptor for long mode is the same as that for protected mode
-
Difference between long mode descriptor and protected mode descriptor comes from
L bitandD/B bit- In protected mode,
L bit must be clear - In long mode,
L bit must be setandD/B bit must be clear
- In protected mode,
-
Long mode ignores
base addressandlimitin descriptor- In long mode, base address is
0x00and limit is maximum of current mode - Basically, you cannot utilize segmentation feature in long mode. It is like vestigial organ. Segmentation feature exists, but does not work as intended.
- In long mode, base address is