Anatomy of a CPU

Assembly Fundamentals

Chapter 2 · Anatomy of a CPU

assembly1-1 ended its own assemble-link-run pipeline with a shrug: "CPU execution takes over from there." This chapter opens that shrug up completely. Before writing a single real LC-3 instruction, you need to know what's actually sitting inside the box that's about to run it — the handful of components every CPU is built from, and the repeating loop, the fetch-decode-execute cycle, that those components run together to make anything happen at all.

The Building Blocks of a CPU

Strip away the marketing and a CPU is a small number of cooperating parts, each with one job:

ComponentIts jobLC-3 example
Register fileA small set of fast, on-chip storage slots — the CPU's own "scratch paper"R0–R7 (full detail in assembly1-4)
ALU (Arithmetic Logic Unit)Does the actual math and logic — addition, AND, NOT — on whatever values it's handedExecutes ADD and AND instructions
Control unitReads the current instruction and decides what everything else should do this cycleInterprets the opcode bits of every instruction
BusesThe shared "wires" that actually move bits between componentsAddress bus, data bus, control bus — see below
PC (Program Counter)A special register holding the memory address of the next instruction to fetchIncremented every cycle unless a branch changes it
IR (Instruction Register)Holds the instruction currently being decoded and executedLoaded fresh at the start of every fetch

None of these components do anything meaningful on their own. What makes a CPU a CPU is the specific, repeating sequence in which they hand work off to each other — which is exactly what the rest of this chapter walks through.

Buses — How Parts Talk to Each Other

A bus is nothing more exotic than a shared set of wires that one component can put a value onto, and another component can read a value off of. LC-3's design (and most simple CPUs) uses three logically distinct buses:

  • Address bus — carries a memory address: "I want to read or write this location."
  • Data bus — carries the actual value being read from or written to that address.
  • Control bus — carries signals like "this is a read" or "this is a write," coordinating when the other two buses' contents are valid.

Two registers act as the CPU's staging area for talking to memory over these buses: the MAR (Memory Address Register) holds the address about to go out on the address bus, and the MDR (Memory Data Register) holds the value coming back on the data bus. You'll see both of these by name in the very next section.

The Fetch-Decode-Execute Cycle, Step by Step

Every single instruction a CPU ever runs — no matter how simple or complex — passes through the same repeating cycle. LC-3 breaks it into six phases, though not every instruction needs all six:

  1. FetchMAR ← PC; the value at that address is read from memory into MDR; MDR's contents are copied into the IR; and PC is incremented so it's already pointing at the next instruction.
  2. Decode — the control unit examines the opcode bits sitting in the IR and determines exactly which operation this instruction represents, and which other registers or memory locations it will need.
  3. Evaluate Address (only for instructions that reference memory) — computes the actual memory address the instruction needs, using one of the addressing modes assembly1-3 covers in full.
  4. Fetch Operands (only if needed) — reads whatever values the instruction needs from the register file or from memory, using the address computed in the previous phase.
  5. Execute — the ALU actually performs the operation (addition, AND, NOT, and so on).
  6. Store Result — the result gets written back to wherever it belongs: a register, or a memory location.

Tracing a Real Instruction: ADD R1, R0, R2

Take the exact instruction from assembly1-1's own pipeline example. This is a register-only instruction — it never touches memory for its operands — so phases 3 and 4 are skipped entirely:

; Fetch
MAR <- PC              ; address of this instruction
MDR <- mem[MAR]         ; the instruction's bits
IR  <- MDR
PC  <- PC + 1           ; PC now points past this instruction

; Decode
control unit reads IR's opcode bits -> "this is ADD, register mode"

; Evaluate Address  -- SKIPPED, ADD (register mode) never touches memory
; Fetch Operands
read R0 and R2 from the register file

; Execute
ALU computes R0 + R2

; Store Result
write the ALU's result into R1

Now contrast that with a memory-referencing instruction like LD R1, VALUE (also from assembly1-1's own example). Fetch, Decode, Execute, and Store Result all still happen — but this time Evaluate Address and Fetch Operands aren't skipped: Evaluate Address computes the actual memory address VALUE refers to, and Fetch Operands reads the value sitting at that address into MDR before it's written into R1. assembly1-3 picks this exact distinction back up when it covers addressing modes in full.

The cycle never stops on its own
A CPU has no built-in concept of "the program is done" or "wait for input." It simply keeps running fetch-decode-execute, forever, one instruction after another — PC pointing at whatever comes next. A program only stops because it executes a specific instruction that tells the CPU to halt (LC-3's own HALT, previewed in assembly1-1's pipeline example, covered in full in assembly1-8). "The program finished" isn't something the CPU perceives — it's just one more instruction being fetched and executed like any other.
This chapter is conceptual, not cycle-accurate
Real hardware often overlaps or pipelines these phases for speed (a topic real CPUs like x86-64 lean on heavily). LC-3, and this course, deliberately treat the cycle as six clean, sequential phases — because the goal here is understanding what has to happen and in what order, not squeezing out performance. That's exactly the kind of historical/real-hardware complexity assembly1-1 named as a reason to start with a teaching ISA.

Hands-On Exercises

Exercise 1

List the six phases of the fetch-decode-execute cycle in order, and explain in your own words what MAR and MDR each hold at the moment the Fetch phase completes.

📄 View solution
Exercise 2

Using this chapter's own ADD R1, R0, R2 trace as a model, explain why the Evaluate Address and Fetch Operands phases are skipped for this instruction but are NOT skipped for LD R1, VALUE. What's the general rule that decides whether those two phases run?

📄 View solution
Exercise 3

A classmate says "the CPU knows when a program is done and stops running." Using this chapter's own tip-box reasoning, correct that statement — what does a CPU actually do at every single cycle, and how does a program actually come to a stop?

📄 View solution

Chapter 2 Quick Reference

  • Register file, ALU, control unit, buses, PC, IR — the core components every CPU is built from
  • Buses: address bus (where), data bus (what value), control bus (read vs. write, timing)
  • MAR holds an address about to go to memory; MDR holds the value coming back
  • The six-phase cycle: Fetch → Decode → Evaluate Address → Fetch Operands → Execute → Store Result
  • Evaluate Address / Fetch Operands only run for instructions that actually reference memory
  • The CPU has no concept of "done" — it fetches forever until an instruction like HALT explicitly stops it
  • This chapter's six clean phases are conceptual — real chips like x86-64 pipeline/overlap them for speed