8086 Architecture & Programmer's Model
The 8086 exposes sixteen-bit data, pointer, segment, instruction, and flag registers while its original implementation splits execution from bus access and overlaps both through a six-byte prefetch queue. The register contract survived far longer than that implementation.
The 8086 is useful because its architecturally visible machine is small enough to hold in one diagram, yet already contains the ideas that make x86 distinctive: variable-length instructions, overlapping register names, implicit operands, segmentation, a downward-growing stack, flags, and a separate port-I/O space. Its programmer's model is an ISA contract. The execution-unit/bus-interface split is one historical implementation of that contract.
Visible state and hidden machinery #
Intel partitioned the original CPU into two cooperating units:
- The Execution Unit (EU) decodes and executes instructions, operates the ALU, updates flags, and calculates effective offsets.
- The Bus Interface Unit (BIU) forms physical addresses, fetches instruction bytes, and performs memory and I/O bus cycles.
The 8086 BIU has a six-byte instruction queue. When bus capacity is free, it fetches ahead while the EU executes earlier bytes. A memory operand or empty queue makes the EU wait for the BIU. A taken control transfer invalidates prefetched bytes because the sequential fetch address is no longer correct.
This is early overlap, not a promise that one instruction completes every clock. The ISA defines final visible state. Queue fill, bus cycles, and timing belong to the original microarchitecture.
Register groups #
| Register | Programmer-visible role | Important implicit use |
|---|---|---|
AX = AH:AL |
accumulator, general data | multiply/divide, port I/O, many compact encodings |
BX = BH:BL |
general data and base | one of the memory-address bases |
CX = CH:CL |
general data and count | repeat, loop, and variable shift/rotate counts |
DX = DH:DL |
general data | high half of wide multiply/divide; variable I/O port number |
SP |
stack pointer | top of stack in SS |
BP |
base pointer | stack-relative data; defaults to SS for memory addressing |
SI |
source index | source of string operations, normally DS:SI |
DI |
destination index | destination of string operations, fixed to ES:DI on 8086 |
CS, DS, SS, ES |
segment bases | code, ordinary data, stack, and extra/string destination |
IP |
instruction offset | next instruction within CS; not a general operand register |
FLAGS |
status and control | condition codes, single step, interrupt mask, string direction |
The low and high bytes of AX, BX, CX, and DX are independently nameable. Writing AL changes only bits 7:0 of AX; writing AX changes both AH and AL. SP, BP, SI, and DI have no byte names in the original ISA.
FLAGS is both result and control state #
| Flag | Meaning | Question it answers |
|---|---|---|
CF |
carry/borrow | Did unsigned arithmetic exceed the operand width? |
PF |
parity | Does the low result byte contain even parity? |
AF |
auxiliary carry | Was there a carry/borrow across bit 3, used by decimal-adjust operations? |
ZF |
zero | Is the result zero? |
SF |
sign | What is the high result bit? |
OF |
signed overflow | Is the mathematical signed result outside the representable range? |
TF |
trap | Should execution generate a single-step trap? |
IF |
interrupt enable | May maskable external interrupts be recognized? |
DF |
direction | Do string indexes increment or decrement? |
CF and OF describe different interpretations of the same result bits. 0xFFFF + 1 overflows unsigned 16-bit arithmetic (CF=1) but is -1 + 1 = 0 in signed arithmetic (OF=0). 0x7FFF + 1 does not carry out of bit 15 (CF=0) but cannot be represented as a signed 16-bit result (OF=1).
Not every instruction defines every flag. Correct code asks the instruction reference which flags are written, preserved, or left undefined before branching on them.
Instruction execution crosses the partition #
Consider ADD [BX+SI+8], AX:
- The EU decodes the instruction bytes from the queue.
- It computes the 16-bit effective offset
BX + SI + 8. - The BIU combines that offset with the selected segment base and reads the word.
- The EU adds
AX, produces a 16-bit result, and updates defined status flags. - The BIU writes the result back to memory.
The syntax names one instruction. The machine performs address calculation, one or more bus cycles, an ALU operation, flag generation, and writeback. A register-register ADD avoids the operand bus cycles but has the same architectural arithmetic semantics.
8086 and 8088 share an ISA boundary #
The 8088 executes essentially the same 16-bit instruction set and exposes the same registers, but its external data bus is eight bits and its instruction queue is four bytes rather than six. A word transfer therefore uses different external bus behavior. Software compatibility does not imply identical throughput or board design.
This is a useful distinction:
- ISA compatibility asks whether the same instruction bytes have the same visible meaning.
- microarchitectural compatibility would require similar queues, execution resources, caches, and timing.
- platform compatibility additionally requires memory maps, peripherals, firmware, ABI, and operating environment.
What persists in current x86 #
Current Intel processors retain the lower 16-bit register names and a real-address mode that implements the 8086 programming environment with extensions. Reset enters real-address mode. Later x86 adds wider registers, more segment registers, protected and long modes, paging, caches, speculative out-of-order execution, and many new encodings.
The useful legacy is therefore the state contract and encoding ancestry. The original EU/BIU block diagram is not a model of a current core.
Reading an unknown state dump #
Use this order:
- Determine the execution mode and operand/address size.
- Form the next instruction address from
CS:IPin 8086 real mode. - Identify implicit register roles for the current instruction.
- Separate effective offset from final physical address.
- Decode only the flags that the previous instruction actually defined.
- If control arrived through a call or interrupt, validate the stack image before blaming the register values.
The dump becomes understandable when each field is tied to the operation that owns it.