In both real and protected modes, the system uses 16-bit segment registers to derive the actual memory address.
The Intel 80386, introduced in 1985, adds two additional segment registers, FS and GS, with no specific uses defined by the hardware.
Therefore, real mode can just as well be imagined as having a variable length for each segment, in the range 1 to 65,536 bytes, that is just not enforced by the CPU.
This derived directly from the hardware design of the Intel 8086 (and, subsequently, the closely related 8088), which had exactly 20 address pins.
The use of this feature by programmers led to the Gate A20 compatibility issues in later CPU generations, where the linear address space was expanded past 20 bits.
The root of the problem is that no appropriate address-arithmetic instructions suitable for flat addressing of the entire memory range are available.
[citation needed] Flat addressing is possible by applying multiple instructions, which however leads to slower programs.
For example, in the tiny model CS=DS=SS, that is the program's code, data, and stack are all contained within a single 64 KB segment.
The 80286's protected mode extends the processor's address space to 224 bytes (16 megabytes), but not by adjusting the shift value.
This method was commonly used on Windows 3.x applications to produce a flat memory space, although as the OS itself was still 16-bit, API calls could not be made with 32-bit instructions.
Machines following the rising IBM PC/AT standard could feign a reset to the CPU via the standardised keyboard controller, but this was significantly sluggish.
That selector consists of a 2-bit Requested Privilege Level (RPL), a 1-bit Table Indicator (TI), and a 13-bit index.
Otherwise, the processor adds the 24-bit segment base, specified in descriptor, to the offset, creating a linear physical address.
A 386 CPU can be put back into real mode by clearing a bit in the CR0 control register, however this is a privileged operation in order to enforce security and robustness.
By way of comparison, a 286 could only be returned to real mode by forcing a processor reset, e.g. by a triple fault or using external hardware.
Four of the segment registers, CS, SS, DS, and ES, are forced to base address 0, and the limit to 264.
Unlike the global descriptor table mechanism used by legacy modes, the base address of these segments is stored in a model-specific register.
For instance, the Linux kernel sets up only 4 general purpose segments: Since the base is set to 0 in all cases and the limit 4 GiB, the segmentation unit does not affect the addresses the program issues before they arrive at the paging unit.
This is because the current privilege level (CPL) of the processor is stored in the lower 2 bits of the CS register.
The only ways to raise the processor privilege level (and reload CS) are through the lcall (far call) and int (interrupt) instructions.
[4] Of course, in real mode, there are no privilege levels; all programs have absolute unchecked access to all of memory and all CPU instructions.