CHAPTER 4. ENTERING 32-BIT PROTECTED MODE 39
lgdt [gdt_descriptor] ; Load our global descriptor table , which defines
; the protected mode segments (e.g. for code and data)
mov eax , cr0 ; To make the switch to protected mode , we set
or eax , 0x1 ; the first bit of CR0 , a control register
mov cr0 , eax
jmp CODE_SEG:init_pm ; Make a far jump (i.e. to a new segment) to our 32-bit
; code. This also forces the CPU to flush its cache of
; pre -fetched and real -mode decoded instructions , which can
; cause problems.
[bits 32]
; Initialise registers and the stack once in PM.
init_pm:
mov ax, DATA_SEG ; Now in PM, our old segments are meaningless ,
mov ds, ax ; so we point our segment registers to the
mov ss, ax ; data selector we defined in our GDT
mov es, ax
mov fs, ax
mov gs, ax
mov ebp , 0x90000 ; Update our stack position so it is right
mov esp , ebp ; at the top of the free space.
call BEGIN_PM ; Finally , call some well -known label
4.5 Putting it all Together
Finally, we can include all of our routines into a boot sector that demonstrates the switch
from 16-bit real mode into 32-bit protected mode.
; A boot sector that enters 32-bit protected mode.
[org 0x7c00]
mov bp, 0x9000 ; Set the stack.
mov sp, bp
mov bx, MSG_REAL_MODE
call print_string
call switch_to_pm ; Note that we never return from here.
jmp $
%include "../print/print_string.asm"
%include "gdt.asm"
%include "print_string_pm.asm"
%include "switch_to_pm.asm"
[bits 32]