Switching into Protected Mode is easy: you just need to set a single bit in a Control Register. But staying in Protected Mode, without the CPU throwing up its hands and resetting itself due to not knowing what to do next, takes a lot of preparation.
In short, the steps required are as follows:
An area of memory for the Global Descriptor Table needs to be set up to define a minimum of three Descriptors:
NULL
Descriptor;This can be used for both Data and Stack.
The Global Descriptor Table Register (GDTR
) needs to be initialised to point to this defined area of memory;
GDT_Ptr dw SIZE GDT
dd OFFSET GDT
...
lgdt [GDT_Ptr]
The PM
bit in CR0
needs to be set:
mov eax, cr0 ; Get CR0 into register
or eax, 0x01 ; Set the Protected Mode bit
mov cr0, eax ; We're now in Protected Mode!
The Segment Registers need to be loaded from the GDT to remove the current Real Mode values:
jmp 0x0008:NowInPM ; This is a FAR Jump. 0x0008 is the Code Descriptor
NowInPM:
mov ax, 0x0010 ; This is the Data Descriptor
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x0000 ; Top of stack!
Note that this is the bare minimum, just to get the CPU into Protected Mode. To actually get the whole system ready may require many more steps. For example:
A20
gate;The original author of this section wrote an entire tutorial on entering Protected Mode and working with it.