x86 is a CISC computer architecture created by Intel. It was created for the 16-bit 8086 processor, and has since developed into the 32-bit IA-32 processors, and the developed further by AMD in the 64-bit AMD64 processors. x86 is probably the most widely used architecture today; desktop computers and servers run on x86, as do some most laptops (though recently some laptops have started using ARM, such as Apple’s Mx series).
This wiki page references specific x86 registers and bits (for example, CR0.PE, or CR4.PAE). For more information on these, see the x86 CPU Registers page.
Depending on the CPU model, x86 CPUs can work in 16-bit, 32-bit, or 64-bit mode. All x86 CPUs start off in 16-bit (real) mode, but if they support 32-bit (protected) or 64-bit (long) mode, a boot program can enable specific CPU flags to enter that mode. The three modes are compared here:
| CPU Mode | Bitness | Addressable Memory | Memory Map Type |
|---|---|---|---|
| Real Mode | 16-bit | 1mb | Segmented |
| Protected Mode | 32-bit | 4gb1 | Segmented or Paged |
| Long Mode | 64-bit | 1tb or more | Paged |
Because of their origins in 16-bit processors, all x86 CPUs boot in real mode. Real mode is an extremely limited environment - code is exclusively 16-bit, and modern CPU features aren’t present. Memory has to be managed in the old segmented memory model via a GDT, and only 1mb of memory can be addressed. Generally the only code that runs in real mode is code to enter protected or long mode.
Protected mode is more modern than real mode, but is still lacking many modern CPU features. Memory is now limited to 4gb (unless PAE is enabled, or the A20 is disabled), and can be managed by paging instead of a GDT. Code is now 32-bit instead of 16-bit, allowing more data to be processed at once and thus faster program execution.
Entering protected mode requires a protected mode GDT and IDT. After that, protected mode can be enabled by setting CR0.PE to 1.
Even with protected mode enabled, the CPU will still actually be in 16-bit mode. Protected mode has to be activated after enabling it by long jumping to 32-bit code.
PAE stands for Physical Address Extension. It allows pointers to be larger than 32 bits, allowing more than 4gb of memory to be used in protected mode. PAE is required to enter long mode. PAE is controlled via the CR4.PAE bit.
The information below is taken almost entirely from the OSDev Wiki’s A20 page: https://wiki.osdev.org/A20_Line.
The A20 line is a leftover switch from old hardware that controlled if the computer could access more than 1mb of memory. When it’s disabled, only 1mb of memory can actually be accessed; trying to access memory above that will actually just wrap around back into the lower 1mb. The A20 needs to be enabled to access memory above 1mb and enter protected mode. Unfortunately, the process for doing this is not standardised. The OSDev Wiki has a recommended series of steps for enabling the A20 here: https://wiki.osdev.org/A20_Line#Enabling.
Note that some emulators, like QEMU, have the A20 line enabled on boot. UEFI will also enable the A20 for you, and it’s possible that other emulators or processors have it enabled on boot.
Long mode is what most modern desktops and servers run in. Up to 1tb of memory can be addressed, memory is managed by paging, code is 64-bit, and all the features of modern CPUs are available for use.
Entering long mode requires enabling PAE, loading a 64-bit page table, enabling long mode, then enabling paging.
Before enabling long mode, if paging was used in protected mode, it must be disabled so a new, 64-bit page table can be loaded.
After that, enable PAE. Then the 64-bit page table must be loaded by storing a pointer to the PML4 or PML5 in the CR3 register. Next, 64-bit mode must be enabled by setting EFER.LME to 1. Finally, to enter 64-bit mode, enable paging by setting CR0.PG to 1, then branch to 64-bit code.
On processors that support PAE (Physical Address Extension), PAE can be enabled, increasing addressable memory to the same size as long mode. ↩