How can a segment register with 16bit point to a segment descriptor in 32 protected mode

2026-06-13

Stack Overflow: View Question

Tags: memory, x86, operating-system, memory-segmentation, gdt

Score: 0 | Views: 64

The asker is wrestling with a classic protected-mode confusion: how can CS, a mere 16-bit register, possibly address a Global Descriptor Table entry that lives somewhere in a 32-bit (4 GiB) physical address space? Intuitively, 16 bits gives you only 64 KiB of reach, which is nowhere near enough to point anywhere in RAM.

Why the confusion is reasonable. In real mode, CS really does hold a value that participates directly in address generation (CS << 4 + IP). It feels natural to assume the same model carries into protected mode, just bigger. It doesn't. The architecture pivots on a subtle but crucial change of meaning for the segment register.

The key insight: the segment register is not a pointer, it's an index. In protected mode, the 16 bits of CS are split into three fields:

So CS doesn't address RAM directly. It picks one of up to 8192 entries from a table whose actual base address lives in the GDTR register — and GDTR is a 48-bit beast (32-bit linear base + 16-bit limit), loaded by LGDT. That is where the 32-bit reach comes from. The CPU computes GDTR.base + (index × 8) to find the 8-byte descriptor, then caches the descriptor's base, limit, and access rights in a hidden part of CS.

Sketch of an answer to give them:

  1. Real mode: segment register = high bits of a 20-bit physical address. Direct arithmetic.
  2. Protected mode: segment register = selector, a structured index into a table.
  3. The table's location is held in GDTR/LDTR, which are wider than 16 bits — that's how you reach anywhere in 32-bit space.
  4. Once loaded, the descriptor's 32-bit base + limit + flags are cached in the segment register's shadow (descriptor cache), so subsequent accesses don't re-walk the GDT.

Gotchas worth flagging:

The challenge: It hinges on recognizing that in protected mode the segment register stopped being an address and became a structured table index, with the real 32-bit reach hiding in GDTR.

All newsletters