HALICERY

free-time coding, hardware dev, articles

Top
Home 8042 Blogs About
Home IntelEssential The 386: IA-32 Addressing Modes

Last modified: Sun Jun 21 20:07:00 UTC+0200 2026 © A. Tarpai


386 Addressing Modes and Effective Address calculation

The 386 is both a 32- and a 16-bit CPU at the same time: 32- and a 16-bit addressing modes and data movements can be mixed between- and even within one instruction using 66h/67h prefix bytes.

  1. D-bit determines the default addressing style and default data movement size
  2. 67h address-prefix: switches between 8086 Legacy MODR/M or 386 MODR/M+SIB style addressing modes (along with 16- or 32-bit EA calculation)
  3. 66h operand-prefix: switches between 16- or 32-bit data movement size, when W=1 in opcode or as implied

Addressing Modes

When 16-bit addressing mode is used, the MODR/M byte is interpreted as a 16-bit addressing mode specifier.
When 32-bit addressing mode is used, the MODR/M byte is interpreted as a 32-bit addressing mode specifier.

SIB = SCALE-INDEX-BASE

16-BIT MEMORY ADDRESSING MODES       32-BIT MEMORY ADDRESSING MODES
______________________________       ___________________________________

D=0 or                               D=1 or
D=1 and 67h address-prefix           D=0 and 67h address-prefix


16-bit                               32-bit
EFFECTIVE ADDRESS CALCULATION:       EFFECTIVE ADDRESS CALCULATION:

[BP/BX + SI/DI + D8/D16]             [BASE + INDEX*SCALE + D8/D32]

 X X X X  BP/BX BASE REG              X X X X X X X X  BASE REG
 X X X X  SI/DI INDEX REG             X X X X X X X X  SCALED INDEX REG
 X X X X  DISPLACEMENT                X X X X X X X X  DISPLACEMENT
---------------------------          ------------------------------------
 X X X X  16-BIT OFFSET               X X X X X X X X  32-BIT OFFSET


Legacy 8086-MODR/M byte:             386-MODR/M + optional SIB byte:

 7  6  5  4  3  2  1  0               7  6  5  4  3  2  1  0      7  6  5  4  3  2  1  0
+-----+--------+-------+             +-----+--------+-------+    +-----+--------+-------+
| MOD |        |  R/M  |             | MOD |        |  BASE |    |SCALE|  INDEX |  BASE |
+-----+--------+-------+             +-----+--------+-------+    +-----+--------+-------+
      MODR/M BYTE                          MODR/M BYTE                  SIB BYTE

                                                                        EAX ECX EDX EBX  -  EBP ESI EDI
R/M    OPERAND ADDRESS               R/M    OPERAND ADDRESS      INDEX: 000 001 010 011 100 101 110 111

000    BX + SI + DISP                000    EAX + DISP           EAX 000
001    BX + DI + DISP                001    ECX + DISP           ECX 001
010    BP + SI + DISP                010    EDX + DISP           EDX 010
011    BP + DI + DISP                011    EBX + DISP           EBX 011
100    SI + DISP                     100    sib + DISP     --->  ESP 100    SIB-BASE + INDEX << SCALE
101    DI + DISP                     101    EBP + DISP*          EBP 101*
110    BP + DISP*                    110    ESI + DISP           ESI 110
111    BX + DISP                     111    EDI + DISP           EDI 111


MOD    DISPLACEMENT                  MOD    DISPLACEMENT                       SCALE:

00     NO DISPLACEMENT               00     NO DISPLACEMENT                    00  NO SCALING
01     1 byte DISP (sign-extend)     01     1 byte DISP (sign-extend)          01  2
10     2 byte DISP                   10     4 byte DISP                        10  4
11     REGISTER ADDRESSING           11     REGISTER ADDRESSING                11  8

* Direct Memory Addressing           * Direct Memory Addressing               - 100 means NO INDEX
  MOD=00: 2 byte DISP ONLY             MOD=00: 4 byte DISP ONLY



8/16-BIT REGISTER ADDRESSING         8/32-BIT REGISTER ADDRESSING
______________________________       ___________________________________

D=0 or                               D=1 or
D=1 and 66h operand-prefix           D=0 and 66h operand-prefix

 7  6  5  4  3  2  1  0               7  6  5  4  3  2  1  0
+-----+--------+-------+             +-----+--------+-------+
| 1 1 |        |  REG  |             | 1 1 |        |  REG  |
+-----+--------+-------+             +-----+--------+-------+
      MODR/M BYTE                          MODR/M BYTE


REG     W=0    W=1                    REG     W=0    W=1

000     AL     AX                     000     AL     EAX
001     CL     CX                     001     CL     ECX
010     DL     DX                     010     DL     EDX
011     BL     BX                     011     BL     EBX
100     AH     SP                     100     AH     ESP
101     CH     BP                     101     CH     EBP
110     DH     SI                     110     DH     ESI
111     BH     DI                     111     BH     EDI

(67h has no effect)

EFFECTIVE ADDRESS CALCULATION with implied DS or SS

16-BIT MEMORY ADDRESSING MODES     32-BIT MEMORY ADDRESSING MODES
______________________________     _________________________________________________________________________

D=0 or                             D=1 or
D=1 and 67h address-prefix         D=0 and 67h address-prefix

                                                                          WITH SCALED INDEX      NO INDEX
MOD R/M      Effective              MOD R/M      Effective       SIB      Effective              Effective
             Address                    BASE     Address         BASE     Address                Address†

00  000      [BX + SI]              00  000      [EAX]           000      [EAX + IDX]            [EAX]
00  001      [BX + DI]              00  001      [ECX]           001      [ECX + IDX]            [ECX]
00  010   SS:[BP + SI]              00  010      [EDX]           010      [EDX + IDX]            [EDX]
00  011   SS:[BP + DI]              00  011      [EBX]           011      [EBX + IDX]            [EBX]
00  100      [SI]                   00  100      SIB --------->  100   SS:[ESP + IDX]         SS:[ESP]
00  101      [DI]                   00  101      [D32]*          101      [D32 + IDX]**          [D32]*
00  110      [D16]*                 00  110      [ESI]           110      [ESI + IDX]            [ESI]
00  111      [BX]                   00  111      [EDI]           111      [EDI + IDX]            [EDI]

01  000      [BX + SI + D8]         01  000      [EAX + D8]      000      [EAX + IDX + D8]       [EAX + D8]
01  001      [BX + DI + D8]         01  001      [ECX + D8]      001      [ECX + IDX + D8]       [ECX + D8]
01  010   SS:[BP + SI + D8]         01  010      [EDX + D8]      010      [EDX + IDX + D8]       [EDX + D8]
01  011   SS:[BP + DI + D8]         01  011      [EBX + D8]      011      [EBX + IDX + D8]       [EBX + D8]
01  100      [SI + D8]              01  100      SIB --------->  100   SS:[ESP + IDX + D8]    SS:[ESP + D8]
01  101      [DI + D8]              01  101   SS:[EBP + D8]      101   SS:[EBP + IDX + D8]    SS:[EBP + D8]
01  110   SS:[BP + D8]              01  110      [ESI + D8]      110      [ESI + IDX + D8]       [ESI + D8]
01  111      [BX + D8]              01  111      [EDI + D8]      111      [EDI + IDX + D8]       [EDI + D8]

10  000      [BX + SI + D16]        10  000      [EAX + D32]     000      [EAX + IDX + D32]      [EAX + D32]
10  001      [BX + DI + D16]        10  001      [ECX + D32]     001      [ECX + IDX + D32]      [ECX + D32]
10  010   SS:[BP + SI + D16]        10  010      [EDX + D32]     010      [EDX + IDX + D32]      [EDX + D32]
10  011   SS:[BP + DI + D16]        10  011      [EBX + D32]     011      [EBX + IDX + D32]      [EBX + D32]
10  100      [SI + D16]             10  100      SIB --------->  100   SS:[ESP + IDX + D32]   SS:[ESP + D32]
10  101      [DI + D16]             10  101   SS:[EBP + D32]     101   SS:[EBP + IDX + D32]   SS:[EBP + D32]
10  110   SS:[BP + D16]             10  110      [ESI + D32]     110      [ESI + IDX + D32]      [ESI + D32]
10  111      [BX + D16]             10  111      [EDI + D32]     111      [EDI + IDX + D32]      [EDI + D32]

                                    ESP cannot be R/M BASE       ESP cannot be INDEX
                                    (100 means SIB)              (100 means NO INDEX)


idx = scaled index register
SS marked only. Otherwise DS implied

* BP- or EBP-relative addressing without DISPLACEMENT (MOD=00) always means Direct Memory: full DISPLACEMENT follows with implied DS, and that is the Effective Address.

** Also Direct Memory with implied DS + scaled index. A funny one. It does not mean SS:[EBP+idx]. This can be encoded by [EBP+idx+0] using zero-byte displacement – similar to [EBP+0] for [EBP].

These modes are redundant and used practically only for [ESP], [ESP + d8] and [ESP + d32] missing from MODR/M encoding.

386 MODR/M SIB:

Test: Redundant addressing mode

Compare [ebp + 8] with MODR/M and MODR/M + SIB NO INDEX. Manually _emit code bytes (VC++):

8B 45 08        mov  eax, [ebp + 8]
8B 44 25 08     mov  eax, [ebp + NOIDX + 8]    <-- not valid in assembler

_emit 8Bh                      // mov
_emit (1<<6) | (0<<3) | (4)    // MOD=01 REG=EAX R/M=SIB
_emit (0<<6) | (4<<3) | (5)    // SCALE=0 INDEX=NONE BASE=EBP
_emit 8h

Run code. Same as MODR/M without SIB (tested, same result).

66/67H Prefixes

This addressing style - and default operand size - can be switched between 16/32-bit modes on a by instruction-basis, even mixed within one instruction using 66/67H prefix bytes.

67H Address-Size Prefix

Address Size means legacy- or 32-bit ADDRESSING MODES, using 16- or 32-bit format MODR/M byte and to calculate a 16- or 32-bit Effective Address (EA offset):

                              32-bit     optional  optional BYTE- or
                              MODR/M     SIB       DWORD displacement

                              +-----+   +-----+   +-----+-----+-----+-----+
 D   32-bit addressing mode:  | M/R |   | SIB |   |     |                 |    --> 32-bit EA offset
  \   /                       +-----+   +-----+   +-----+-----+-----+-----+
   \ /
   / \
  /   \                       +-----+   +-----+-----+
67H  16-bit addressing mode:  | M/R |   |     |     |    --> 16-bit EA offset
                              +-----+   +-----+-----+

                              16-bit     optional BYTE- or
                              legacy     WORD displacement
                              MODR/M

The displacement size is 0, 1 or (2 or 4 bytes) based on MOD=00, 01 or 10.

66H Operand-Size Prefix

D=0: opcode W-bit encodes BYTE or WORD operation (16-bit legacy mode)
D=1: same opcode encodes BYTE or DWORD operation (32-bit mode)


                              +-----+-----+-----+-----+
  D    8/32-bit operand size  |     |                 |  BYTE or DWORD DATA
   \   /                      +-----+-----+-----+-----+
    \ /
    / \
   /   \                      +-----+-----+
66H    8/16-bit operand size  |     |     |  BYTE or WORD DATA
                              +-----+-----+

This is also true for every implicite data storage and manipulation:

Examples

Immediate example:
CPU interpretation of the same opcode (B8 move immediate to Accu) based on current CS D=0 or D=1. NASM assembler:

    opcodes      D=1                  opcodes      D=0
                [BITS 32]                         [BITS 16]

B8 FFFFFFFF     mov eax, -1           B8 FFFF     MOV AX, -1

Addressing Mode example:
CPU interpretation of the same opcodes with prefixes based on current CS D=0 or D=1. NASM assembler:

    opcodes      D=1
                [BITS 32]

      8B 00     mov  eax, [eax]        ; Native 32-bit: 32-bit addressing mode and moves 32-bit DWORD
   67 8B 00     mov  eax, [bx+si]      ; Moves 32-bit DWORD but uses 16-bit addressing mode
   66 8B 00     mov   ax, [eax]        ; 32-bit addressing mode but moves 16-bit WORD
66 67 8B 00     mov   ax, [bx+si]      ; Legacy 16-bit addressing mode and moves 16-bit WORD


    opcodes      D=0
                [BITS 16]

      8B 00     MOV   AX, [BX+SI]      ; Native 16-bit: 16-bit addressing mode and moves 16-bit WORD
   67 8B 00     MOV   AX, [EAX]        ; Moves 16-bit WORD but uses 32-bit addressing mode
   66 8B 00     MOV  EAX, [BX+SI]      ; 16-bit addressing mode but moves 32-bit DWORD
66 67 8B 00     MOV  EAX, [EAX]        ; Uses 32-bit addressing mode and moves 32-bit DWORD

These two prefixes are absolutely orthogonal:

CS Segment Default D-bit  |    0    0    0    0    1    1    1    1
Operand-Size Prefix 66H   |    N    N    Y    Y    N    N    Y    Y
Address-Size Prefix 67H   |    N    Y    N    Y    N    Y    N    Y
--------------------------+------------------------------------------
Effective Operand Size    |   16   16   32   32   32   32   16   16
Effective Address Size    |   16   32   16   32   32   16   32   16

(INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986)