SimplifyC++ Article
x86-64 Machine Code Encoding ModRM Encoding with Examples
x86-64 Machine Code Encoding : ModR/M Encoding with Examples
The ModR/M byte is a crucial component of x86-64 machine code encoding that specifies the addressing mode, the register operand, and the memory addressing details for many instructions. It acts as a flexible encoding scheme to select registers or memory operands, allowing the CPU to interpret instruction operands efficiently. Mastering ModR/M encoding is essential when designing an assembler, as it directly impacts the accuracy of generated machine code.
1. Structure of the ModR/M Byte
The ModR/M byte is a single 8-bit value divided into three fields:
| Bits | Name | Description |
|---|---|---|
| 7-6 | Mod | Specifies addressing mode |
| 5-3 | Reg | Register operand or opcode extension |
| 2-0 | R/M | Register or memory addressing mode |
Mod (2 bits): Determines whether the operand is a register or memory and the addressing displacement size.
Reg (3 bits): Usually encodes a register operand or an opcode extension field.
R/M (3 bits): Specifies the register or memory operand.
2. Meaning of Each Field
2.1 Mod Field
| Mod Value | Description |
|---|---|
| 00 | Memory addressing with no displacement (except when R/M = 101) |
| 01 | Memory addressing with 8-bit signed displacement |
| 10 | Memory addressing with 32-bit signed displacement |
| 11 | Register-direct addressing (no memory operand) |
Special case:
When Mod = 00 and R/M = 101, the R/M field encodes a 32-bit displacement-only address (i.e., no base register).
2.2 Reg Field
Encodes one of the registers, often serving as the source or destination register.
Alternatively, it can extend the opcode when certain instructions use it as an opcode extension.
Values range from 0 to 7, representing registers:
RAX,RCX,RDX,RBX,RSP,RBP,RSI,RDI(in legacy 3-bit form), extended by REX prefixes.
2.3 R/M Field
Specifies either a register operand or a memory addressing mode depending on the Mod field.
When Mod ≠ 11, the R/M value specifies the base register or special addressing modes, often combined with a Scale-Index-Base (SIB) byte for complex addressing.
3. Interaction with SIB Byte and Displacement
When R/M = 100 (binary
100), a SIB (Scale-Index-Base) byte follows to enable more complex addressing modes involving scaled index registers.Displacement bytes (8-bit or 32-bit) follow the ModR/M (and SIB if present) byte depending on the Mod field value.
4. REX Prefix and ModR/M Extension
The introduction of x86-64 and the REX prefix expands the Reg and R/M fields by adding an extra high bit, allowing access to registers
R8throughR15.The REX prefix bits
R,X, andBrespectively extend the Reg, Index (in SIB), and R/M fields from 3 bits to 4 bits.
5. Detailed Examples
Example 1: Register to Register Move — MOV RAX, RBX
Instruction:
MOV r64, r64Encoding requires ModR/M byte with Mod=11 (register-direct), Reg and R/M fields specifying registers.
RAXregister code: 000RBXregister code: 011Mod = 11 (register addressing)
Reg = RBX (011) — source
R/M = RAX (000) — destination
ModR/M byte: 11 011 000 binary = 0xD8 hex
Complete encoding includes the REX prefix to specify 64-bit operand size (
REX.W = 1).
Example 2: Memory Operand with 8-bit Displacement — MOV EAX, [RBX + 5]
Instruction: Move a 32-bit value from memory at
[RBX + 5]into EAX.Mod field = 01 (8-bit displacement)
Reg = EAX (000)
R/M = RBX (011)
Displacement: 0x05 (8-bit signed integer)
ModR/M byte: 01 000 011 binary = 0x43 hex
Displacement: 0x05
Example 3: Memory Operand with SIB — MOV EAX, [RAX + RDX*4 + 16]
Mod = 10 (32-bit displacement)
Reg = EAX (000)
R/M = 100 (indicates SIB byte follows)
SIB byte specifies: scale=4 (10), index=RDX (010), base=RAX (000)
Displacement: 16 (0x10) 32-bit
ModR/M byte: 10 000 100 binary = 0x84 hex
SIB byte: 10 010 000 binary = 0x90 hex
Displacement: 0x00000010
Example 4: RIP-Relative Addressing — MOV EAX, [RIP + offset]
In x86-64, RIP-relative addressing is used with Mod = 00 and R/M = 101 indicating a displacement relative to the instruction pointer (RIP).
Displacement is a signed 32-bit value relative to the next instruction.
ModR/M byte: 00 000 101 binary = 0x05 hex
Displacement: 32-bit signed offset
6. Summary of Key Points
ModR/M byte encodes operand addressing modes flexibly in 8 bits.
Modfield defines if the operand is register or memory and size of displacement.Regfield encodes a register operand or opcode extension.R/Mfield encodes register or memory operand; combined with SIB byte for complex addressing.REX prefix extends these fields to support more registers.
Correct ModR/M encoding is mandatory for correct operand decoding by the CPU.
7. Assembler Implementation Considerations
The assembler must decode instruction operands and determine the appropriate ModR/M byte based on operand types and addressing modes.
Displacement size (none, 8-bit, 32-bit) must be chosen carefully based on the target address.
SIB bytes must be generated when necessary to support scaled-index addressing modes.
REX prefix bits must be set to extend register fields when encoding registers R8–R15.
Edge cases such as RIP-relative addressing and special Mod/RM combinations require precise handling.
What did you think?
Sign in to react or comment.
Comments
0No comments yet.