Skip to main content

Instruction Set Architectures, RISC vs CISC, and the Fetch-Decode-Execute Cycle

What This Concept Is

An instruction set architecture (ISA) is the promise the processor makes to software. It defines:

  • the set of instructions the CPU can execute (add, load, branch, call, return, and so on)
  • the operands they take (registers, immediates, memory addresses)
  • the processor state visible to software (general-purpose registers, the program counter, flags)
  • how memory is addressed and how bytes are ordered

Two broad styles exist. RISC (Reduced Instruction Set Computer, e.g. RISC-V, ARM, MIPS) uses many simple, fixed-width instructions that each do one thing -- a load, a store, or a register-to-register op. CISC (Complex Instruction Set Computer, e.g. x86_64) exposes variable-length instructions that can read memory, compute, and write back in one opcode.

At runtime the CPU repeats one loop forever:

  1. Fetch the instruction at PC from memory.
  2. Decode its bits into a control signal plan.
  3. Execute the operation, possibly reading or writing registers and memory.
  4. Update PC (next instruction, or the branch target).

That loop is the stored-program machine. Everything else is elaboration.

Why It Matters Here

The ISA is the only stable contract between you and the machine. Compilers target it; debuggers decode it; perf counts it. Everything in this module -- caches, pipelines, virtual memory -- exists to make that fetch-decode-execute loop run faster while still behaving as the ISA says.

If you cannot name the parts of the cycle, you cannot reason about:

  • why a mov (%rsi), %rax counts as one x86 instruction but takes longer than a register move
  • what "1.3 instructions per cycle" even measures
  • why RISC-V decode is trivial and x86 decode needs a dedicated front-end

Concrete Example

Consider c = a + b; with all three in memory, compiled for x86_64:

mov    -0x8(%rbp), %eax       # load a into EAX
add -0xc(%rbp), %eax # add memory operand b to EAX
mov %eax, -0x10(%rbp) # store EAX into c

Now the same code compiled for RISC-V:

lw     t0, -8(s0)             # load a
lw t1, -12(s0) # load b
add t2, t0, t1 # register add
sw t2, -16(s0) # store c

Same computation. RISC-V forces the loads and stores to be explicit; x86 folds one of them into the add. The fetch-decode-execute loop runs three instructions on x86 and four on RISC-V, but the RISC-V instructions are uniform 32-bit words that decode in a single cycle.

Common Confusion / Misconception

"CISC is slower because instructions are complex." That was true in the 1990s and is not the right intuition today. Modern x86_64 cores translate each CISC instruction into one or more internal RISC-like micro-operations (µops) which then flow through a RISC-style back-end. The ISA is a language; the microarchitecture is the hardware that speaks it. Do not confuse the two.

How To Use It

When you see a piece of assembly:

  1. Identify the ISA (the syntax and register names give it away: %rax -> x86_64 AT&T, rax -> x86_64 Intel, x10/a0 -> RISC-V, r0-r15 -> ARM32).
  2. Walk the PC one instruction at a time: what does this fetch do to registers and memory?
  3. Note where the cycle leaves the straight line (any jmp, call, ret, b, or conditional branch).
  4. Ask what the microarchitecture might do under the hood (fuse, split, fold into µops), but do not let that distort your reading of the ISA-level semantics.

Check Yourself

  1. What are the four steps of the fetch-decode-execute cycle, in order?
  2. Name one architectural feature of RISC and one of CISC.
  3. Why does saying "x86 is CISC so it is slow" miss the point?
  4. What state makes a CPU "a stored-program machine" rather than a fixed-function calculator?

Mini Drill or Application

For each short snippet, name the likely ISA and count how many memory accesses the CPU performs for a single straight-line execution:

  1. addq $1, (%rdi)
  2. ldr r0, [r1]; add r0, r0, #1; str r0, [r1]
  3. addi a0, a0, 1
  4. lea 0x10(%rbx,%rcx,4), %rax

Now load each snippet into Compiler Explorer (write three-line C functions that compile to something similar) and confirm the instruction count.

Then compile the same C source for two ISAs (e.g. x86-64 gcc and RISC-V rv64gc gcc) and diff the assembly. Notice how the same computation fans out into different instruction mixes and different addressing modes. This side-by-side reading is the single best exercise for internalizing what "ISA" actually means.

Read This Only If Stuck