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:
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]
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:
The original author of this section wrote an entire tutorial on entering Protected Mode and working with it.