SimplifyC++ Article
x86-64 Machine Code Encoding Real encoding examples with byte breakdowns
x86-64 Machine Code Encoding: Real encoding examples with byte breakdowns
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.
5.1 MOV Instruction Encoding Examples
Example 1: MOV RAX, RBX
Assembly:
mov rax, rbxExplanation:
64-bit register-to-register move
Requires REX prefix for 64-bit operand size
Opcode
0x89with 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
Example 2: 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
Example 3: MOV RDX, 0x12345678
Assembly:
mov rdx, 0x12345678Explanation:
Move immediate 32-bit value to 64-bit register RDX
Uses REX prefix with 64-bit operand
Opcode
0xBAforMOV 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
5.2 ADD Instruction Encoding Examples
Example 1: ADD RAX, RCX
Assembly:
add rax, rcxExplanation:
Register-to-register 64-bit addition
Opcode
0x01forADD r/m64, r64Requires 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
Example 2: ADD RDX, 5
Assembly:
add rdx, 5
Explanation:
Immediate 8-bit addition to RDX
Opcode
0x83with opcode extension in ModR/M Reg fieldModR/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
5.3 JMP Instruction Encoding Examples
Example 1: JMP +0x10
Assembly:
jmp 0x10Explanation:
Near relative jump with 4-byte displacement
Opcode
0xE9followed 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
Example 2: JMP +0x7
Assembly:
jmp short 0x7Explanation:
Short relative jump (1-byte displacement)
Opcode
0xEBfollowed by 1-byte offset
Byte Breakdown:
| Byte | Description | Hex |
|---|---|---|
| 1 | Opcode for short jump | 0xEB |
| 2 | Displacement (1 byte) | 0x07 |
Final encoding: EB 07
5.4 CALL Instruction Encoding Examples
Example 1: CALL +0x20
Assembly:
call 0x20Explanation:
Near relative call with 4-byte displacement
Opcode
0xE8followed 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
Example 2: CALL RAX
Assembly:
call raxExplanation:
Indirect call via register
Opcode
0xFFwith 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
5.5 Summary and Insights
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.
Conclusion
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.
What did you think?
Sign in to react or comment.
Comments
0No comments yet.