Segmentation and the BIU/EU Split
Twenty address lines and sixteen-bit registers do not fit together. One workaround was abandoned; the other became every modern pipeline.
Skip to the animationThe 8086's 16-bit registers cannot name an address on its 20-bit bus, so a physical address is assembled as segment × 16 + offset — and the same chip introduced a prefetch queue, one workaround that history discarded and one that became every modern pipeline.
The constraint
A 16-bit register names 64 KB. Twenty address lines reach 1 MB. No single register can name an arbitrary address, so one has to be assembled from more than one — and every peculiarity of the architecture follows from that arithmetic.
How an address is built
A segment register is shifted left four bits — multiplied by sixteen — to give a 20-bit base, and a 16-bit offset is added. physical = segment × 16 + offset. One shift and one addition of dedicated hardware.
| Register | Used for | Paired with |
|---|---|---|
| CS | Code | IP, for instruction fetch |
| DS | Data | The default for most operand accesses |
| SS | Stack | SP and BP, automatically |
| ES | Extra | String operations |
The processor selects the right one from the instruction's nature, so most code never mentions segments at all. They stay invisible until a program's code or data grows past 64 KB, at which point they become the dominant fact of the architecture.
The overlap problem
Segments start every 16 bytes and are 64 KB long, so they overlap massively. A single physical address has 4096 valid segment:offset representations — 1000:0000, 0FFF:0010 and 0F00:1000 are all 10000H.
So comparing two pointers for equality fails: they can differ and mean the same place. That is why DOS-era C had near and far pointers and normalisation routines, and why the memory model is remembered with so little affection.
The BIU/EU split
The 8086 divides into a bus interface unit that owns the buses and computes physical addresses, and an execution unit that decodes and executes and has no bus connection of its own.
Because they are separate, the BIU can fetch ahead while the EU is still executing. A six-byte prefetch queue sits between them: the EU takes from the front, the BIU refills whenever the bus would otherwise be idle. Fetch stops being a bottleneck.
This is pipelining in its simplest form — two stages, overlapped, with a decoupling buffer between units running at naturally different rates.
Branches flush the queue
A taken branch invalidates everything prefetched, since it all came from the path not taken. The queue is flushed and refilled from the new address, so a branch costs the refill on top of the jump itself.
On a modern deeply pipelined CPU that penalty is tens of cycles, which is why branch prediction justifies a large fraction of the transistor budget. The problem was visible in 1978 and has only grown more expensive.
What survived
Segmentation was a workaround for a register-width limit, and 64-bit x86 abandoned it almost entirely for a flat address space. Prefetching and overlapped execution went the other way, growing into deep pipelines, superscalar issue and out-of-order execution.
Both shipped on the same chip in 1978, and only one of them was the future. The instruction set, meanwhile, is still there underneath — nearly fifty years later.
The numbers you will be asked for
- Physical address
physical = (segment × 16) + offset
- Segment size
64 KB maximum
- Segment granularity
16 bytes — segments start every paragraph
- Representations per address
up to 4096 distinct segment:offset pairs
- Prefetch queue
6 bytes on the 8086, 4 on the 8088
Watch it work
Check yourself
question 1 / 4
One question at a time. Pick an answer to see why it is right or wrong, then move on — there is no score to keep and nothing is saved.