An operand is a register, an immediate value in the instruction, or a memory location. For memory, the CPU computes a 16-bit offset, the effective address, from up to three parts: a base register (BX or BP), an index register (SI or DI) and a displacement, a constant stored in the instruction. Any one, two or all three can be used. The offset is then combined with a segment register to form the physical address.
| Mode | Example | Address |
|---|---|---|
| Direct | MOV AX, [N1] | DS:N1 |
| Register indirect | MOV AL, [BX] | DS:BX (also SI, DI) |
| Based | MOV AX, [BP+4] | SS:BP+4 |
| Indexed | MOV AL, TABLE[SI] | DS:TABLE+SI |
| Based indexed | MOV AL, [BX+DI] | DS:BX+DI |
| Based indexed + displacement | MOV AL, [BP+SI+2] | SS:BP+SI+2 |
MOV AL, [NUMS] ; direct: 1MOV BX, OFFSET NUMSADD AL, [BX+1] ; base + displacement: + 2MOV SI, 2ADD AL, [BX+SI] ; base + index: + 3ADD AL, NUMS[SI+1] ; index + displacement: + 2MOV DI, OFFSET NUMSADD AL, [DI] ; register indirect: + 1ADD AL, '0' ; digit -> characterMOV DL, ALMOV AH, 02h ; DOS: print DLINT 21hNUMS DB 1, 2, 3, 2
Default segments
An address that uses BP is in the stack segment SS; every other one is in DS. This fits the usual layout: BP points into a stack frame, the other registers point at data. A segment prefix such as ES: overrides the default for one operand. String instructions have fixed rules: the source is DS:SI and the destination ES:DI.
Writing them in MASM
TABLE[SI], [TABLE+SI] and [SI+TABLE] all mean the same thing, as do [BX][SI] and [BX+SI]. The displacement is stored as one signed byte when it fits in -128..127, otherwise as a word.
What does not exist
MOV AX, [BP] ; fine: encoded as [BP+0], segment SS; MOV AX, [AX] ; no: only BX, BP, SI and DI address memory; MOV AX, [BX+BP] ; no: two base registers; MOV AX, [SI+DI] ; no: two index registers; MOV AX, [BX+SI*2] ; no: scaling came with the 80386
An instruction has at most one memory operand. The offset is 16 bits and wraps around: [BX+SI] with a sum above FFFFh lands at the start of the segment, not beyond it.
Later CPUs
With 32-bit addressing on the 80386, any general register can be the base, any but ESP the index, and the index can be multiplied by 1, 2, 4 or 8: [EBX+ESI*4+8].