-; Everything between real mode and the C kernel
-
- bits 16
-
-switch_to_pm
- mov bx, 0B800h
- mov es, bx ; set extra segment to starting address of video RAM
- mov byte [es:0], 'L' ; print an L to screen, to let us know that we actually got here
-
- cli ; disable interrupts
- xor ax, ax ; clear accumulator
- mov ds, ax ; clear data segment, this makes sure the next instruction reads from the right place
- lgdt [gdt_desc] ; load the Global Descriptor Table
-
- mov eax, cr0 ; move Control Register 0 to accumulator
- or eax, 1 ; flip the bit which controls memory protection
- mov cr0, eax ; move the accumulator back to CR0
- jmp CODE_SEG:protected ; not quite there yet, need to do a far jump to clean the pipeline from any 16-bit instructions
- ; note that the jump does not have to be physically far away, it just needs to use a segmented address
-
- bits 32 ; we are finally in 32-bit mode
-protected
- mov ax, DATA_SEG ; put the selector for the data segment in the accumulator
- ; in real mode, segmentation works by taking one of these segment registers, shifting it right by 4 bits or 1 hex digit
- ; and then adding a 16-bit offset to form a 20-bit address
- ; example: 1234h:5678h
- ; 1234h is shifted to 12340h, 12340h + 5678h is 179B8h
- ; in 32-bit protected mode, these segment registers do not hold the segment address itself, but a selector in the GDT
- ; so we have to update the segment registers accordingly
- mov ds, ax
- mov ss, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
-
- ; reinitialize the stack at a safe location
- mov ebp, 090000h
- mov esp, ebp
-
- ; transfer control to the kernel
- call KERNEL_OFFSET
-
- ; above call should not return in normal circumstances, but if it does hang forever
- jmp $
-
-video_memory equ 0B8000h
-
-; the actual Global Descriptor Table
-; refer to Volume 3, Chapter 2, 2.1.1 of Intel's 64 and IA-32 Software Developer's Manual for more info
-gdt_start
-null_seg
- dq 0
-code_seg
- dw 0FFFFh
- dw 0
- db 0
- db 10011010b
- db 11001111b
- db 0
-data_seg
- dw 0FFFFh
- dw 0
- db 0
- db 10010010b
- db 11001111b
- db 0
-gdt_end
-gdt_desc
- dw gdt_end - gdt_start - 1
- dd gdt_start
-CODE_SEG equ code_seg - gdt_start
-DATA_SEG equ data_seg - gdt_start
-