Windows organizes memory in ”segments“—so before we proceed, let's quickly review the segmented memory architecture of the Intel 8086 family of microprocessors. This family includes the 8088 found in the PC and PC/XT, the 8086 and the 186 found in some compatibles, the 286 found in the PC/AT, and the 386 and 486.
When these processors run in real mode, a memory address consists of two parts, a 16-bit segment address and a 16-bit offset address. The 16-bit segment address is shifted 4 bits to the left and added to the offset address. The resultant 20-bit physical address can access 1 MB of data:
16-bit offset address xxxxxxxxxxxxxxxx
16-bit segment address + xxxxxxxxxxxxxxxx0000
20-bit physical address xxxxxxxxxxxxxxxxxxxx
Four internal registers of the microprocessor hold segment addresses. These segment registers are called CS (code segment), DS (data segment), SS (stack segment), and ES (extra segment). The 386 and 486 have two additional segment registers: FS and GS.
Software for the 8086 family runs most efficiently when the segment addresses are held constant and all addressing is done by varying the offset addresses. The offset addresses generated by the microprocessor include the instruction pointer (IP), which accesses code in combination with the CS register; the stack pointer (SP) and base pointer (BP), which access the stack in combination with the SS register; and the BX (base), SI (source index), and DI (destination index) registers, which access data, most often in combination with the DS or ES register. An address that uses only the offset address with an implied segment address (the current segment address) is called a ”near pointer“ or sometimes a ”short pointer.“ An address that uses both the segment and offset addresses is called a ”far pointer“ or a ”long pointer.“
For any particular segment address, the offset address can vary within a 64-KB range, from 0000H through FFFFH. A block of memory that is based on a particular segment address is called (appropriately enough) a ”segment.“ People used to think of segments as 64-KB blocks of memory, but this definition is becoming less common. Now we say that segments can be any size up to 64 KB. Sometimes the size of a segment (or the size of an area of memory larger than 64 KB) is given in terms of ”paragraphs.“ A paragraph is 16 bytes. Memory allocated for a segment is often a multiple of 16 bytes, because a segment must begin on a 16-byte boundary of physical memory. (When the segment register is shifted left 4 bits, the bottom 4 bits are 0.)
When the 286, 386, and 486 processors run in 286-compatible protected mode, the segment does not refer to a physical memory address. Instead, the segment is an offset into a ”descriptor table“ that provides a 24-bit base address in physical memory. The offset address is then added to this base address to generate a 24-bit physical address that can access up to 16 megabytes of memory.
The use of segments is central to Windows' memory organization. The entire memory space controlled by Windows is divided into segments of various lengths. Some of these segments contain code, and others contain data.