Tracing a program
Four instructions, step by step
A program trace hand-executes a program one step at a time, following the fetch-decode-execute cycle and watching the registers and bus change. Tracing a short LOAD, ADD, STORE, HALT program shows the accumulator CPU actually computing a sum.
You have the whole machine and its language. The last thing to do is run a program by hand, the way the hardware does: follow fetch-decode-execute, tracking each register as the control unit's steps fire. Do this once and the CPU stops being a diagram and becomes a thing you can predict. We will compute
5 + 10 and store the answer.The program and the memory
Recall the instruction set:
LOAD addr (0x1) copies memory[addr] into the accumulator ACC; ADD addr (0x2) adds memory[addr] to ACC; STORE addr (0x3) writes ACC back to memory[addr]; HALT (0xF) stops the clock. Here is memory, program at the bottom, data at the top, written in hex:| address | byte | meaning |
|---|---|---|
| 0 | 0x1E | LOAD 14 |
| 1 | 0x2F | ADD 15 |
| 2 | 0x3D | STORE 13 |
| 3 | 0xF0 | HALT |
| 13 | 0x00 | result slot (starts 0) |
| 14 | 0x05 | the value 5 |
| 15 | 0x0A | the value 10 |
0x2F is opcode 2 (ADD), operand 0xF (address 15). Addresses 14 and 15 hold the data 5 and 10; address 13 will receive the result.Notice there is no line between code and data: both are just bytes in the same RAM. The program counter decides which bytes are read as instructions (it walks 0, 1, 2, 3) and which the instructions treat as data (addresses 13, 14, 15). This is the *stored-program* idea, the foundation of every general-purpose computer.
Predict, then trace
Before reading the trace below: after this whole program halts, what value is in the accumulator, and what value is in memory address 13? (The data is
5 at address 14 and 10 at address 15.)Answer
The accumulator holds
15 and memory address 13 holds 15. The program loads 5 (ACC = 5), adds 10 (ACC = 15), stores ACC to address 13 (memory[13] = 15), then halts. You wrote 5 + 10; the machine left the answer 15 both in the accumulator and at address 13.The fetch that every instruction shares
Each instruction begins with the same fetch, driven by the control unit's step lines
T0, T1 (from the ring counter):- **
T0:** the program counter drives its address onto the bus; RAM reads that byte; the instruction register loads it. Now the IR holds the instruction and exposes its opcode and operand. - **
T1:** the program counter increments, so it already points at the *next* instruction. Then the steps branch on the opcode to do the execute phase.
Running it, instruction by instruction
Start with
PC = 0 and ACC undefined. Fetch reads address 0.- **Fetch
0x1E(PC 0 -> IR), PC becomes 1.** Opcode1= LOAD, operand14. Execute: put14on the address bus, RAM readsmemory[14] = 5onto the bus, the accumulator loads it. NowACC = 5. - **Fetch
0x2F(PC 1 -> IR), PC becomes 2.** Opcode2= ADD, operand15. Execute: put15on the address bus, RAM readsmemory[15] = 10into the ALU'sBinput; the ALU adds (ACC + B = 5 + 10); the accumulator loads the sum. NowACC = 15. - **Fetch
0x3D(PC 2 -> IR), PC becomes 3.** Opcode3= STORE, operand13. Execute: the accumulator drivesACC = 15onto the bus, RAM writes it intomemory[13]. Memory address 13 now holds15. - **Fetch
0xF0(PC 3 -> IR), PC becomes 4.** OpcodeF= HALT. Execute: the control unit stops the clock. The machine freezes withACC = 15andmemory[13] = 15.
That is a complete program run. You wrote
5 + 10; the machine fetched four bytes, decoded each opcode, and performed the transfers, and the answer 15 (0x0F) is sitting in memory at address 13. Every step was one micro-operation: one value crossing the bus, gated by control lines, clocked into a register. Nothing magic, just the loop, repeated.Watching the execute core do the arithmetic
The figure is the accumulator + ALU core, the part that does the LOAD and ADD execute steps. Driving its inputs over clocks reproduces the program's arithmetic directly: this is what the control unit makes happen once it has fetched an instruction. Step it to relive the trace.
- Hold
LD = 1(load on every edge) and set the functionF1 F0 = 00(add). - Put
5(0000 0101) onB, clear the accumulator first if needed, and clock: this is the LOAD/ADD that landsACC = 5. - Put
10(0000 1010) onBand clock again: the ALU adds,ACCbecomes15(0000 1111), exactly the program's result. - Try one more
ADDwithB = 0andZEROstays low; subtract15(setF0 = 1,B = 0000 1111) andACCreturns to0, lighting theZEROflag.
ACCALU): the accumulator wired into the ALU. B0-B7 is the operand the fetch step pulled from memory, F1 F0 is the operation the opcode chose, LD loads the result on a clock edge. Open it in the lab and replay the trace: add 5, then add 10, and read ACC = 15.To hand-trace any program, keep a small table of the machine's state, one column each for
PC, IR, ACC, and any memory you touch, and fill in a row per instruction. Fetch advances PC and reloads IR; execute changes ACC or memory per the opcode. That table is all a CPU really is: state, transformed one instruction at a time.This is the end of the climb. From a single transistor you built gates, then arithmetic and memory, then a register, ALU, counter, RAM, and control unit, and now you have traced a program executing on a computer you understand top to bottom. Open the lab and write your own four-instruction program; you know exactly what every byte will do.
Frequently asked
What is a program trace?
A program trace is hand-executing a program one step at a time, following the fetch-decode-execute cycle and watching the registers (
PC, IR, ACC) and memory change. Tracing a short LOAD / ADD / STORE / HALT program shows the accumulator CPU actually computing a sum: here, 5 + 10 = 15.How does fetch-decode-execute work in this CPU?
Every instruction starts with the same fetch: on step
T0 the program counter drives its address onto the bus, RAM reads that byte, and the instruction register loads it; on T1 the PC increments to point at the next instruction. The steps then branch on the opcode to run the execute phase (read the operand, run the ALU, load a register).What is the stored-program idea?
There is no line between code and data: both are just bytes in the same RAM. The program counter decides which bytes are read as instructions (it walks
0, 1, 2, 3) and which the instructions treat as data (here addresses 13, 14, 15). This stored-program idea is the foundation of every general-purpose computer.How do you hand-trace any program?
Keep a small state table with a column for
PC, IR, ACC, and any memory you touch, then fill one row per instruction: fetch advances PC and reloads IR, and execute changes ACC or memory per the opcode. That table is all a CPU really is: state, transformed one instruction at a time.Every lesson here builds toward one thing: a working CPU, from the transistor up.
Open the free lab →Builds towardAssembly language