Article by Ayman Alheraki on January 11 2026 10:37 AM
This section presents practical, real-world examples of x86-64 machine code instruction encodings with detailed byte-level breakdowns. Understanding how instructions translate into machine code byte sequences is essential when designing an assembler. Each example demonstrates how prefixes, opcode bytes, ModR/M, SIB, displacement, and immediate fields combine to form the final binary encoding.
MOV RAX, RBXAssembly:
mov rax, rbxExplanation:
64-bit register-to-register move
Requires REX prefix for 64-bit operand size
Opcode 0x89 with ModR/M byte encoding destination and source registers
Byte Breakdown:
| Byte | Description | Binary | Hex |
|---|---|---|---|
| 1 | REX Prefix (01001000) W=1 | 01001000 | 0x48 |
| 2 | Opcode for MOV r/m64, r64 | — | 0x89 |
| 3 | ModR/M byte: Mod=11, Reg=011, R/M=000 (RBX → RAX) | 11011000 | 0xD8 |
Final encoding: 48 89 D8
MOV RAX, [RBP-0x10]Assembly:
mov rax, [rbp-0x10]Explanation:
Memory to register move
64-bit operand with REX prefix
ModR/M indicates 8-bit displacement with base register RBP
Byte Breakdown:
| Byte | Description | Binary | Hex |
|---|---|---|---|
| 1 | REX Prefix (W=1) | 01001000 | 0x48 |
| 2 | Opcode for MOV r64, r/m64 | — | 0x8B |
| 3 | ModR/M byte: Mod=01 (disp8), Reg=000 (RAX), R/M=101 (RBP) | 01000101 | 0x45 |
| 4 | Displacement (signed -0x10 = 0xF0) | — | 0xF0 |
Final encoding: 48 8B 45 F0
MOV RDX, 0x12345678Assembly:
mov rdx, 0x12345678Explanation:
Move immediate 32-bit value to 64-bit register RDX
Uses REX prefix with 64-bit operand
Opcode 0xBA for MOV r64, imm32 (B8 + reg, reg=2 for RDX)
Byte Breakdown:
| Byte | Description | Hex |
|---|---|---|
| 1 | REX prefix (W=1) | 0x48 |
| 2 | Opcode (B8 + reg=2) | 0xBA |
| 3-6 | Immediate value (little-endian) | 78 56 34 12 |
| 7-10 | Zero-extend upper 32 bits | 00 00 00 00 |
Final encoding: 48 BA 78 56 34 12 00 00 00 00
ADD RAX, RCXAssembly:
add rax, rcxExplanation:
Register-to-register 64-bit addition
Opcode 0x01 for ADD r/m64, r64
Requires REX prefix
Byte Breakdown:
| Byte | Description | Binary | Hex |
|---|---|---|---|
| 1 | REX prefix (W=1) | 01001000 | 0x48 |
| 2 | Opcode | — | 0x01 |
| 3 | ModR/M: Mod=11, Reg=001 (RCX), R/M=000 (RAX) | 11001000 | 0xC8 |
Final encoding: 48 01 C8
ADD RDX, 5Assembly:
xadd rdx, 5
Explanation:
Immediate 8-bit addition to RDX
Opcode 0x83 with opcode extension in ModR/M Reg field
ModR/M specifies ADD operation
Byte Breakdown:
| Byte | Description | Binary | Hex |
|---|---|---|---|
| 1 | REX prefix (W=1) | 01001000 | 0x48 |
| 2 | Opcode for ADD r/m64, imm8 | — | 0x83 |
| 3 | ModR/M: Mod=11, Reg=000 (ADD), R/M=010 (RDX) | 11000010 | 0xC2 |
| 4 | Immediate 8-bit value | — | 0x05 |
Final encoding: 48 83 C2 05
JMP +0x10Assembly:
jmp 0x10Explanation:
Near relative jump with 4-byte displacement
Opcode 0xE9 followed by signed 32-bit offset
Byte Breakdown:
| Byte | Description | Hex |
|---|---|---|
| 1 | Opcode for near jump | 0xE9 |
| 2-5 | Displacement (little-endian) | 10 00 00 00 |
Final encoding: E9 10 00 00 00
JMP +0x7Assembly:
jmp short 0x7Explanation:
Short relative jump (1-byte displacement)
Opcode 0xEB followed by 1-byte offset
Byte Breakdown:
| Byte | Description | Hex |
|---|---|---|
| 1 | Opcode for short jump | 0xEB |
| 2 | Displacement (1 byte) | 0x07 |
Final encoding: EB 07
CALL +0x20Assembly:
call 0x20Explanation:
Near relative call with 4-byte displacement
Opcode 0xE8 followed by 4-byte signed offset
Byte Breakdown:
| Byte | Description | Hex |
|---|---|---|
| 1 | Opcode for near call | 0xE8 |
| 2-5 | Displacement | 20 00 00 00 |
Final encoding: E8 20 00 00 00
CALL RAXAssembly:
call raxExplanation:
Indirect call via register
Opcode 0xFF with ModR/M specifying call opcode extension and register
Byte Breakdown:
| Byte | Description | Binary | Hex |
|---|---|---|---|
| 1 | Opcode for indirect call | — | 0xFF |
| 2 | ModR/M: Mod=11, Reg=010 (CALL), R/M=000 (RAX) | 11010000 | 0xD0 |
Final encoding: FF D0
REX Prefix is mandatory for 64-bit operand instructions and extended registers. Its bits control operand size (W), register extensions (R, X, B).
Opcode bytes differ based on operand types, and some instructions use opcode extensions encoded in the ModR/M Reg field.
ModR/M byte defines addressing modes, register operands, or memory indirect addressing modes.
SIB bytes, when present, further define scaled indexed addressing, but are not required in these simple examples.
Displacement and immediate values are encoded in little-endian format.
Relative jumps and calls encode offsets relative to the next instruction, requiring assembler calculation during assembly.
These real encoding examples with byte breakdowns illustrate the precise binary layout of common instructions, a vital foundation for building an x86-64 assembler. Mastery of these details ensures accurate encoding and decoding of machine instructions, enabling robust assembler functionality.