Intel x86 Assembly Language & Microarchitecture Real vs Protected modes Switching into Protected Mode


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:

    1. The zeroeth, NULL Descriptor;
    2. Another Descriptor for a Code Segment;
    3. Another Descriptor for a Data Segment.

      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
         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 upper memory areas may have to be enabled - turning off the A20 gate;
  • The Interrupts should definitely be disabled - but perhaps the various Fault Handlers could be set up before entering Protected Mode, to allow for errors early on in the processing.

The original author of this section wrote an entire tutorial on entering Protected Mode and working with it.