CPU Binary Instructions

How Instructions Are Encoded as Binary and Decoded by Your Processor

Every program you've ever run — from a simple calculator to a 3D game — is stored in memory as a sequence of binary numbers. These numbers are the machine code instructions that your CPU fetches, decodes, and executes. When I first learned that the human-readable assembly code I was studying gets turned into raw bits before the CPU sees it, the whole process felt magical. But the encoding scheme is remarkably logical once you understand the pattern.

In this article I'll break down how CPU instructions are structured in binary, walk through real examples from the x86-64 and ARM architectures, and explain the fetch-decode-execute cycle that makes it all work.

Instruction Encoding: Opcode + Operands

Every CPU instruction consists of two main parts:

  • Opcode (Operation Code): A binary pattern that tells the CPU what operation to perform — add, subtract, load from memory, store to memory, branch, etc.
  • Operands: The data the operation works on — register identifiers, memory addresses, or immediate values.

The simplest instruction format looks like this:

[ Opcode (4-12 bits) ] [ Operand 1 (3-5 bits) ] [ Operand 2 (3-5 bits) ] [ Optional Immediate ]

For example, a RISC-V instruction that adds registers R1 and R2 and stores the result in R3 might encode as:

ADD R3, R1, R2  →  0000000 00001 00010 000 00011 0110011
                       |--funct7--| |rs1| |rs2| |f3| |-rd-| |-opcode-|

In this 32-bit instruction, the opcode (0110011) identifies it as an arithmetic operation, the funct3 and funct7 fields specify that it's an ADD (not SUB, XOR, or another operation), and the three 5-bit fields identify the source and destination registers.

RISC vs. CISC: Different Encoding Philosophies

The two dominant instruction set architectures take very different approaches to binary encoding:

RISC (Reduced Instruction Set Computer) — ARM, RISC-V:

  • Fixed instruction width (32 bits in ARM, 32 bits in RISC-V with a 16-bit compressed extension).
  • Every instruction is exactly one word, making decode simple and fast.
  • Fewer instruction formats (typically 4-6 for RISC-V: R-type, I-type, S-type, B-type, U-type, J-type).
  • All arithmetic operates on registers only (load-store architecture).

CISC (Complex Instruction Set Computer) — x86, x86-64:

  • Variable instruction width (1 to 15 bytes in x86-64).
  • Instructions can directly operate on memory (not just registers).
  • Denser code (fewer total bytes for the same program), but much more complex decode logic.
  • Modern x86 CPUs internally decode CISC instructions into RISC-like micro-ops (uops) for the execution pipeline.

Real-world example: The same function compiled for ARM and x86-64 produces very different binary patterns. An ARM ADD X0, X1, X2 is always a clean 32-bit instruction. The x86-64 equivalent ADD RAX, RBX is just 3 bytes (48 01 D8) but might decode into 5-6 micro-ops internally.

The Fetch-Decode-Execute Cycle

The CPU doesn't just blindly execute instructions — it follows a precise three-step cycle for each instruction:

  1. Fetch: The CPU reads the instruction from memory at the address stored in the Program Counter (PC). The instruction is loaded into the Instruction Register (IR), and the PC is incremented to point to the next instruction.
  2. Decode: The instruction decoder — a combinational logic circuit — examines the opcode bits and determines what operation to perform, which registers to read, and whether an immediate value or memory address is needed. In RISC CPUs, this is mostly a matter of routing the appropriate bits from the instruction word to the appropriate hardware units. In x86-64, the decoder must parse variable-length prefixes, opcode bytes, ModR/M bytes, SIB bytes, and displacement fields.
  3. Execute: The appropriate functional unit (ALU, memory controller, branch unit) performs the operation. The result is written back to a register or memory.

This cycle repeats billions of times per second. A 4 GHz CPU (common in modern laptops) completes roughly 4 billion fetch-decode-execute cycles per second, or about 0.25 nanoseconds per cycle.

Real Instruction Encodings: x86-64 Examples

Here are some real x86-64 instruction encodings in hexadecimal and binary:

MOV RAX, 42        →  48 C7 C0 2A 00 00 00
                        Binary: 01001000 11000111 11000000 00101010 ...

ADD RAX, RBX       →  48 01 D8
                        Binary: 01001000 00000001 11011000

JMP 0x400100       →  E9 FB 00 01 00
                        Binary: 11101001 11111011 00000000 00000001 00000000

CALL [RAX]         →  FF D0
                        Binary: 11111111 11010000

The prefix byte 48 appears in many x86-64 instructions — it's the REX.W prefix that tells the CPU to use 64-bit operand size instead of 32-bit. The ModR/M byte (C7 in the MOV example) encodes the addressing mode and register operands.

How the Decoder Works at the Gate Level

The instruction decoder is a large array of logic gates that translates opcode bits into control signals. Here's a simplified view of how an 8-bit opcode decoder works:

  • AND gate arrays: Each instruction's opcode pattern is detected by a dedicated AND gate that checks whether all opcode bits match. For example, the ADD detection AND gate fires when bits [6:0] equal 0110011 and funct3 bits [14:12] equal 000.
  • Control signal routing: The detected instruction activates specific control lines: "enable ALU," "select ADD operation," "read register file port 1," "read register file port 2," and "write register file port 3." These control signals travel to every functional unit in the CPU simultaneously.
  • Immediate extraction: The decoder routes specific bit positions from the instruction word to the ALU's immediate input. In a RISC-V I-type instruction, bits [31:20] are the immediate value, so the decoder connects those 12 bits to the sign-extender and then to the ALU.

A full instruction decoder in a modern OoO (Out-of-Order) CPU might contain tens of thousands of gates and consume significant chip area — especially in x86-64 where the variable-length encoding makes decoding considerably harder than in fixed-width RISC architectures.

Pipelining and Parallel Decode

Modern CPUs don't wait for one instruction to finish before starting the next. Instead, they use instruction pipelining — overlapping the fetch, decode, and execute stages for multiple instructions simultaneously.

A 5-stage pipeline looks like this:

Cycle 1: |F1|   |   |   |   |
Cycle 2: |F2|D1|   |   |   |
Cycle 3: |F3|D2|E1|   |   |
Cycle 4: |F4|D3|E2|M1|   |
Cycle 5: |F5|D4|E3|M2|W1|

During each clock cycle, the CPU is fetching instruction 5, decoding instruction 4, executing instruction 3, accessing memory for instruction 2, and writing back the result of instruction 1 — all simultaneously. This is why adding more pipeline stages (at the cost of handling hazards) has been a primary driver of CPU performance improvements over the past few decades.

Try It Yourself

Open the Binary Code Decoder in a new tab and enter some binary patterns to see the results instantly. All conversions happen in your browser — no data is sent to any server.