Trace a given simple assembly language program

4.2 Assembly Language

Learning objectives

By the end of this lesson you will be able to:

  • Explain the relationship between assembly language and machine code.
  • Describe the two‑pass assembler process and illustrate how a symbol table is built.
  • Identify and use the five addressing modes required by the Cambridge syllabus (immediate, direct, indirect, indexed, PC‑relative).
  • Trace a simple assembly‑language program step‑by‑step, showing the contents of the program counter, registers, flags and memory after each instruction.
  • Classify instructions into the eight instruction‑set categories defined in the syllabus.

1. From assembly to machine code

Each assembly instruction is translated by the assembler into a binary word that the CPU can execute. A typical 16‑bit word consists of an opcode field (identifying the operation) and an operand field (specifying a register, a constant or a memory address).

AssemblyBinary machine code (16‑bit example)Explanation
LD 100001 0000 0000 1010Opcode 0001 = LD; operand 0000 0000 1010 = address 10 (direct).
ADD 110010 0000 0000 1011Opcode 0010 = ADD; operand = address 11.
ST 120011 0000 0000 1100Opcode 0011 = ST; operand = address 12.
HLT1111 0000 0000 0000Opcode 1111 = HLT; operand field unused.

2. The two‑pass assembler

Cambridge expects you to know that an assembler works in two distinct passes.

  1. Pass 1 – Symbol‑table construction

    The source program is scanned line‑by‑line. Every label is recorded together with the address of the instruction that follows it. No object code is generated yet.

  2. Pass 2 – Code generation

    The source is scanned a second time. Using the symbol table, each instruction is translated into binary, and forward references (e.g. jumps to a label defined later) are resolved.

Example symbol table (Pass 1)

LABEL ADDRESS

START 0

LOOP 4

END 9

During Pass 2 the assembler replaces JMP LOOP with the binary representation of the address 4 (or a PC‑relative offset, see Section 3).

Source → Pass 1 → Symbol table → Pass 2 → Object code → Loader → Executable

3. Addressing modes

The Cambridge syllabus requires you to recognise five modes. For each mode a short example is given; the examples use the same simple CPU as in the tables above.

ModeHow the operand is interpretedExample instructionResult (ACC after execution)
ImmediateThe operand is a constant value.LD #5 ; ACC ← 55
DirectThe operand is the exact memory address.LD 20 ; ACC ← M[20]M[20]
IndirectThe operand is a pointer; the address stored at that location is used.LD @30 ; ACC ← M[ M[30] ]M[ M[30] ]
IndexedEffective address = contents of an index register (X) + displacement.LD 5(X) ; ACC ← M[ X + 5 ]M[ X+5 ]
PC‑relative (relative)The operand is a signed offset added to the current PC to obtain the target address. Used for branches.JMP #‑3 ; PC ← PC + (‑3)PC moves three instructions back.

PC‑relative example with trace

; Program starts at address 0

START: LD #1 ; ACC ← 1

ADD #2 ; ACC ← 3

JMP #‑2 ; branch back to ADD (offset = –2)

HLT ; never reached

When the JMP #‑2 is fetched, the PC (which points to the JMP instruction) is incremented to the next address (3) and then the signed offset –2 is added, so the new PC becomes 1 – the address of the ADD instruction.

4. Processor registers and buses (required by the syllabus)

Only the registers that appear in the Cambridge specification are listed, together with the status flags that are used by branch instructions.

RegisterPurpose
PC (Program Counter)Holds the address of the next instruction to be fetched.
IR (Instruction Register)Temporarily stores the fetched instruction.
ACC (Accumulator)Main arithmetic/logic register.
MAR (Memory Address Register)Holds the address of the memory location to be accessed.
MDR (Memory Data Register)Transfers data between memory and the CPU.
ALU (Arithmetic‑Logic Unit)Performs arithmetic and logical operations on data from the ACC or other registers.
X (Index register)Used for indexed addressing; holds a small integer that is added to a displacement.
Flags (Zero, Carry, Sign, Overflow)Set by the ALU after an operation; consulted by conditional branch instructions (JZ, JC, etc.).

5. Instruction‑set categories (syllabus requirement)

For Paper 2 and Paper 4 candidates must be able to identify the category to which an instruction belongs. The categories are listed below together with a typical opcode and a short example that uses one of the five addressing modes.

CategoryTypical opcodesExample (addressing mode)
Data‑movementLD, STLD 20 ; direct
ArithmeticADD, SUB, MUL, DIVADD #3 ; immediate
LogicalAND, OR, NOT, XORAND @15 ; indirect
Input/OutputIN, OUTIN 0 ; read from input port 0
Compare / TestCMP, TSTCMP 25 ; direct (sets flags)
Jump / BranchJMP, JZ, JNZ, JC, JNCJZ #2 ; PC‑relative
Sub‑routineCALL, RETCALL 100 ; direct address of sub‑routine
ControlHLT, NOPHLT

6. Sample program (direct addressing) – addition of two numbers

The program adds the contents of two memory locations (M[10] and M[11]) and stores the result in M[12].

; Simple addition – direct addressing

LD 10 ; ACC ← M[10]

ADD 11 ; ACC ← ACC + M[11]

ST 12 ; M[12] ← ACC

HLT ; stop

6.1 Initial memory contents

AddressContent (decimal)
107
115
120

6.2 Trace table

StepPCIR (fetched instruction)ACCFlags (Z C S V)Memory change
0000 0 0 0Initial state
11LD 1070 0 0 0
22ADD 11120 0 0 0
33ST 12120 0 0 0M[12] ← 12
44HLT120 0 0 0Program stops

6.3 Step‑by‑step explanation

  1. Step 0 – Initialisation: All registers cleared; PC points to address 0.
  2. Step 1 – LD 10: Instruction fetched into IR, PC increments to 1, ACC receives M[10] = 7.
  3. Step 2 – ADD 11: Next instruction fetched, PC becomes 2; M[11] = 5 is added to ACC (7 + 5 = 12). Flags are updated (Zero = 0, Carry = 0, …).
  4. Step 3 – ST 12: ACC (12) is written to memory location 12.
  5. Step 4 – HLT: Processor halts; final state ACC = 12, M[12] = 12.

7. Common mistakes when tracing

  • Forgetting to increment the PC after the fetch phase.
  • Reversing source and destination for ST (it stores ACC → memory, not the opposite).
  • Neglecting to record memory changes caused by store operations.
  • Mixing up addressing modes – e.g. treating an indirect operand as direct.
  • Ignoring the status flags that are set by arithmetic or compare instructions; conditional branches depend on them.

8. Practice exercises

Exercise 1 – Direct addressing (review)

Initial memory: M[20]=3, M[21]=4, M[22]=0.

LD 20

SUB 21

ST 22

HLT

Provide a trace table similar to the one in Section 6.2 and state the final value stored in M[22].

Exercise 2 – Mixed addressing modes (including PC‑relative)

Initial memory and registers (decimal):

AddressContent
3040
408
412
423
500

Index register X is preset to 1.

LD #5 ; immediate – ACC = 5

ADD @30 ; indirect – address = M[30] (=40); ACC ← ACC + M[40] (=8)

SUB 41(X) ; indexed – effective address = 41 + X = 42; ACC ← ACC – M[42] (=3)

ST 50 ; store result in M[50]

HLT

Complete a trace table showing PC, IR, ACC, flags and any memory changes. What value is finally stored in M[50]?

Exercise 3 – PC‑relative branch

Assume the following program starts at address 0. All registers are cleared initially.

START: LD #0 ; ACC ← 0

LOOP: ADD #1 ; ACC ← ACC + 1

CMP #5 ; set Zero flag when ACC = 5

JNZ #‑2 ; if not zero, branch back two instructions (to ADD)

HLT

Trace the program until it halts. Record the value of ACC after each iteration and indicate how the PC‑relative offset changes the PC.

9. Suggested diagram – simple CPU datapath

Textual representation of a minimal datapath used for the examples above

PC ──► Instruction Memory ──► IR ──► Decoder

│ │

▼ ▼

MAR ◄───► Address Bus ◄───► Control Unit

│ │

▼ ▼

MDR ◄───► Data Bus ◄──────► ACC / ALU

│ │

▼ ▼

X (Index Register) ──► Flags Register