8086 Addressing Modes
Eight ways the 8086 finds its operands — from immediate values to complex memory calculations
Open interactive version (quiz + challenge)Real-world analogy
What is it?
Addressing modes define how the 8086 locates operands. The eight modes range from immediate (data in the instruction) and register (data in a register) to complex based-indexed with displacement (base register + index register + constant). Each mode computes an effective address (EA) that is combined with a segment register to form the 20-bit physical address.
Real-world relevance
Compilers choose addressing modes based on the data structure being accessed. A global variable uses direct addressing. A local variable on the stack uses BP-based addressing. Array traversal uses indexed addressing. A field in an array of structures uses based-indexed with displacement. Understanding these modes helps you read disassembled code and optimize assembly routines.
Key points
- Immediate Addressing — The operand is a constant value embedded directly in the instruction. Fast because no memory access is needed to get the operand — the data is part of the instruction itself. Used for loading constants, initializing counters, and setting bit masks.
- Register Addressing — Both operands are in CPU registers. The fastest mode because no memory access is needed — the ALU works directly with register contents. Registers are AX, BX, CX, DX (16-bit) or AH, AL, BH, BL, CH, CL, DH, DL (8-bit).
- Direct Addressing — The instruction contains the exact memory offset address. The physical address is computed as DS × 10h + offset. Used when you know the fixed location of a variable at assembly time, like global variables or lookup tables.
- Register Indirect Addressing — The offset address is held in a register (BX, SI, or DI). The register acts as a pointer. Useful for traversing arrays and data structures where the address changes at runtime. Default segment is DS (or SS if BP is used).
- Based Addressing — The effective address is computed as base register (BX or BP) plus a displacement constant. BX-based uses DS as default segment; BP-based uses SS. Ideal for accessing fields within structures or stack frame variables.
- Indexed Addressing — The effective address is an index register (SI or DI) plus a displacement. Default segment is DS. Ideal for accessing elements of an array where the displacement is the array base and SI/DI is the element offset.
- Based-Indexed Addressing — Combines a base register (BX or BP) with an index register (SI or DI). Effective address = base + index. Useful for 2D arrays or accessing elements within an array of structures. Optionally includes a displacement.
- Segment Override Prefix — By default, data accesses use DS, stack accesses use SS, and code fetches use CS. You can override the default segment with a prefix: ES:, CS:, SS:, DS:. This lets you access data in any segment regardless of the addressing mode.
- Addressing Mode Summary and EA Formula — Each mode has an effective address formula: Immediate=none, Register=none, Direct=disp, Register Indirect=reg, Based=base+disp, Indexed=index+disp, Based-Indexed=base+index+disp. The physical address is always segment × 10h + EA.
Code example
; Demonstrating all 8086 addressing modes
; Setup segment
MOV AX, 1000h
MOV DS, AX ; DS = 1000h
; 1. Immediate
MOV CX, 0064h ; CX = 100 decimal
; 2. Register
MOV DX, CX ; DX = CX = 0064h
; 3. Direct
MOV AX, [0200h] ; AX = word at DS:0200h (PA=10200h)
; 4. Register Indirect
MOV BX, 0200h
MOV AX, [BX] ; AX = word at DS:BX = DS:0200h
; 5. Based
MOV AX, [BX+04h] ; AX = word at DS:(BX+04h) = DS:0204h
; 6. Indexed
MOV SI, 0002h
MOV AX, [SI+0200h] ; AX = word at DS:(SI+0200h) = DS:0202h
; 7. Based-Indexed
MOV AX, [BX+SI] ; AX = word at DS:(BX+SI) = DS:0202h
; 8. Based-Indexed with Displacement
MOV AX, [BX+SI+10h] ; AX = word at DS:(BX+SI+10h) = DS:0212h
; Segment override
MOV AX, ES:[BX+SI] ; Same EA, but uses ES instead of DSLine-by-line walkthrough
- 1. MOV AX, 1000h / MOV DS, AX — loads DS with 1000h. We cannot MOV directly into a segment register, so we use AX as a bridge.
- 2. MOV CX, 0064h — immediate addressing: the value 0064h (100 decimal) is encoded directly in the instruction bytes.
- 3. MOV DX, CX — register addressing: both operands are in registers, no memory access needed, executes in minimum time.
- 4. MOV AX, [0200h] — direct addressing: the offset 0200h is in the instruction. Physical address = 1000h×10h + 0200h = 10200h.
- 5. MOV BX, 0200h / MOV AX, [BX] — register indirect: BX holds the offset. Same physical address as direct, but now we can change BX at runtime to access different locations.
- 6. MOV AX, [BX+04h] — based addressing: EA = 0200h + 04h = 0204h. Physical = 10204h. Good for accessing a field at offset 4 in a structure pointed to by BX.
- 7. MOV AX, [SI+0200h] — indexed addressing: EA = 0002h + 0200h = 0202h. Physical = 10202h. SI acts as an array index.
- 8. MOV AX, [BX+SI] — based-indexed: EA = 0200h + 0002h = 0202h. BX could be row base, SI the column offset.
- 9. MOV AX, [BX+SI+10h] — based-indexed with displacement: EA = 0200h + 0002h + 10h = 0212h. The most flexible mode.
- 10. ES:[BX+SI] — segment override: same EA calculation but uses ES instead of the default DS. Useful for accessing data in the extra segment.
Spot the bug
; Goal: Read byte from array at DS:2000h, index 5
; DS = 1000h, array base = 2000h
;
MOV SI, 5 ; index = 5
MOV AL, [SI+2000h] ; Read array[5]
;
; Programmer expects PA = 1000h*10 + 2000h + 5 = 12005h
; But the byte read is wrong!
;
; Separately, the programmer tries to access stack:
MOV AX, [BP] ; Read from stack
; But BP = 0, and programmer expects DS:0000hNeed a hint?
Show answer
Explain like I'm 5
Fun fact
Hands-on challenge
More resources
- 8086 Addressing Modes (GeeksforGeeks)
- All 8086 Addressing Modes Explained (YouTube)
- Addressing Modes with Examples (TutorialsPoint)
- Intel 8086 Programmer's Reference (Intel)