Lesson 17 of 48 intermediate

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

Addressing modes are like different ways to find a book. Immediate mode: someone hands you the book directly. Register mode: you already have it on your desk. Direct mode: you are given the exact shelf number. Register indirect: you have a card that says which shelf to check. Based-indexed: you combine a section number plus a shelf offset to find it — the more complex the address, the more flexible your search.

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

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 DS

Line-by-line walkthrough

  1. 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. 2. MOV CX, 0064h — immediate addressing: the value 0064h (100 decimal) is encoded directly in the instruction bytes.
  3. 3. MOV DX, CX — register addressing: both operands are in registers, no memory access needed, executes in minimum time.
  4. 4. MOV AX, [0200h] — direct addressing: the offset 0200h is in the instruction. Physical address = 1000h×10h + 0200h = 10200h.
  5. 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. 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. 7. MOV AX, [SI+0200h] — indexed addressing: EA = 0002h + 0200h = 0202h. Physical = 10202h. SI acts as an array index.
  8. 8. MOV AX, [BX+SI] — based-indexed: EA = 0200h + 0002h = 0202h. BX could be row base, SI the column offset.
  9. 9. MOV AX, [BX+SI+10h] — based-indexed with displacement: EA = 0200h + 0002h + 10h = 0212h. The most flexible mode.
  10. 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:0000h
Need a hint?
Think about the default segment for BP. Also, is the index calculation correct for multi-byte elements?
Show answer
Bug 1: If the array contains words (2-byte elements) rather than bytes, index 5 should be SI=5*2=10 (0Ah), not 5. MOV SI,5 accesses the 5th byte, not the 5th word. Fix: MOV SI, 000Ah for word arrays. Bug 2: MOV AX,[BP] uses SS as the default segment (not DS), so it reads from SS:0000h instead of DS:0000h. If SS and DS differ, this reads the wrong location. Fix: Use MOV AX, DS:[BP] to override the segment, or use BX instead of BP if you want DS as the default.

Explain like I'm 5

Imagine you need to find a toy. Immediate: someone just hands it to you. Register: it is already in your pocket. Direct: you are told 'shelf number 5.' Register indirect: you look at a card that says a shelf number. Based: your friend says 'go to section B, then 3 shelves over.' Indexed: 'go to the toy aisle, then 5 spots down.' Based-indexed: 'section B, aisle 3, spot 5.' More steps = more flexibility to find anything!

Fun fact

The based-indexed addressing mode with displacement was so flexible that it could encode a 2D array access in a single instruction — something many RISC architectures need multiple instructions to do. This 'CISC richness' is one reason Intel's x86 survived while simpler architectures came and went.

Hands-on challenge

Given DS=1000h, BX=0100h, SI=0020h, DI=0040h, BP=0200h, SS=2000h, calculate the effective address AND the 20-bit physical address for each: (a) MOV AX,[BX], (b) MOV AX,[BP+10h], (c) MOV AX,[BX+SI+08h], (d) MOV AX,ES:[DI+30h] where ES=3000h. Show all work.

More resources

Open interactive version (quiz + challenge) ← Back to course: Microprocessor A–Z