An instruction with two operands typically has a Mod/RM byte. This enables register-memory and memory-register operations, a flag within the opcode byte indicates the direction (register-memory or memory-register). Both operands are encoded in the ModR/M byte, one is in the Reg field (and msut be a register) and the other is in the Mod and R/M fields. Which may be a register (Mod = 11) or a memory location (Mod selects if a displacement is used for example). R/M selects the register to use (either directly or as the base for a memory computation). There are 3 bits and 8 32-bit registers, however since esp cannot be used in a memory operand the bit pattern 100 means that a SIB byte will follow the ModR/M byte.

In 16-bit instructions (not necessarily 16-bit mode, but an instruction that operates on 16-bit values) these R/M bits are interpreted differently and enable access combinations of two registers.

When a SIB byte is present it provides the more complex addressing modes that take a scale, an index and a base. If the Index field has the bit pattern 100 it means there is no index*scale component (esp cannot be used as an index), and when base is 101 the behaviour depends on the Mod field. These combinations allow for a couple of different addressing modes with optional bases, indexes and displacements, and even allow the ebp register to be used as a base which it could not before the SIB byte was added (prior to 386, although that was just the bp register, don’t @-me!).