Assembly Language
1. What is Assembly Language?
Definition: Assembly language is a low-level language — a type of programming language we use to directly manipulate hardware, e.g. reading / writing to a specific memory address.
It is one step above machine code — machine code is the series of binary numbers (0 and 1).
Memory = a table of locations
| Location / Address | Content |
|---|---|
| 15 | 25 |
| 16 | 35 |
| 17 | 19 |
| 18 | 55 |
| 19 | 30 |
| 29 | 22 |
| 30 | 15 |
| 31 | 7 |
Location / Address → the place used to access the memory.
Content → the data / value stored at that location.
(We use this same memory table in all the examples below.)
2. Addressing Modes
What are addressing modes? Methods of accessing memory are known as addressing modes.
④ Indexed addressing ⑤ Relative addressing
Concept of Accumulator (ACC): a place (register) where the results are stored. Every load instruction below ends with a value in ACC.
3. Immediate Addressing — LDM
No memory is accessed.
4. Direct Addressing — LDD
Note: memory will be involved.
LDD <address> = Direct addressing.
- Step 1: go to the given address
- Step 2: load the value on that address into the Accumulator.
| Location / Address | Content |
|---|---|
| 15 | 25 |
| 16 | 35 |
| 17 | 19 |
| 18 | 55 |
| 19 | 30 |
| 29 | 22 |
| 30 | 15 |
| 31 | 7 |
5. Indirect Addressing — LDI
Note: memory will be involved (2 addresses).
LDI <first address> = Indirect addressing.
- Step 1: go to the given address — it holds the address of the address
- Step 2: go to the second address and load the value in ACC.
| Location / Address | Content |
|---|---|
| 15 | 25 |
| 16 | 35 |
| 17 | 19 |
| 18 | 55 |
| 19 | 30 |
| 29 | 22 |
| 30 | 15 |
| 31 | 7 |
6. Indexed Addressing — LDX
Note: calculation is required. There is a special register called the Index Register (IX).
LDX <initial address> = Indexed addressing.
- Step 1: add the initial address with IX and create a new address
- Step 2: use the new address and load that value in ACC.
| Location / Address | Content |
|---|---|
| 15 | 25 |
| 16 | 35 |
| 17 | 19 |
| 18 | 55 |
| 19 | 30 |
| 29 | 22 |
| 30 | 15 |
| 31 | 7 |
| IX | 9 |
7. Instruction Groups
| Group | What it does |
|---|---|
| Data movement | Accessing the value and loading it in the accumulator |
| Input and output of data | Takes an input from the user and outputs the character of a binary number (ASCII code) |
| Arithmetic operations | Perform addition and subtraction |
| Unconditional and conditional instructions | Move to another instruction (identified by labels / addresses) |
| Compare instructions | Compare the result to another value |
Instruction set (9618 reference table)
| Op Code | Operand | Explanation |
|---|---|---|
| LDM | #n | Immediate addressing. Load the number n to ACC |
| LDD | <address> | Direct addressing. Load the contents of the location at the given address to ACC |
| LDI | <address> | Indirect addressing. The address to be used is at the given address. Load the contents of this second address to ACC |
| LDX | <address> | Indexed addressing. Form the address from <address> + the contents of the index register. Copy the contents of this calculated address to ACC |
| LDR | #n | Immediate addressing. Load the number n to IX |
| STO | <address> | Store the contents of ACC at the given address |
| ADD | <address> | Add the contents of the given address to the ACC |
| INC | <register> | Add 1 to the contents of the register (ACC or IX) |
| DEC | <register> | Subtract 1 from the contents of the register (ACC or IX) |
| JMP | <address> | Jump to the given address |
| CMP | <address> | Compare the contents of ACC with the contents of <address> |
| CMP | #n | Compare the contents of ACC with number n |
| JPE | <address> | Following a compare instruction, jump to <address> if the compare was True |
| JPN | <address> | Following a compare instruction, jump to <address> if the compare was False |
| IN | Key in a character and store its ASCII value in ACC | |
| OUT | Output to the screen the character whose ASCII value is stored in ACC | |
| END | Return control to the operating system |
The board marked CMP and JPN in this table as the pair to watch: CMP sets True/False, then JPE / JPN decides whether to jump.
8. Tracing a Program (Past-paper style)
Trace table for this program (instruction addresses 20–36). Memory: 100→65, 101→67, 102→69, 103→69, 104→68, 301→33. IX starts at 0.
| Addr | Instruction | Addr | Instruction |
|---|---|---|---|
| 20 | LDM #0 | 29 | OUT |
| 21 | STO 300 | 30 | LDD 300 |
| 22 | CMP #0 | 31 | INC ACC |
| 23 | JPE 28 | 32 | STO 300 |
| 24 | LDX 100 | 33 | INC IX |
| 25 | ADD 301 | 34 | CMP #2 |
| 26 | OUT | 35 | JPN 22 |
| 27 | JMP 30 | 36 | END |
| 28 | LDX 100 |
| ASCII code | 65 | 66 | 67 | 68 | 69 | 97 | 98 | 99 | 100 | 101 |
|---|---|---|---|---|---|---|---|---|---|---|
| Character | A | B | C | D | E | a | b | c | d | e |
| Instr. addr | ACC | [300] | IX | OUTPUT | Why |
|---|---|---|---|---|---|
| 20 | 0 | LDM #0 | |||
| 21 | 0 | STO 300 | |||
| 22, 23 | ACC 0 = 0 True → JPE jumps to 28 | ||||
| 28 | 65 | LDX: 100 + IX(0) = 100 → 65 | |||
| 29 | A | OUT (65 = A) | |||
| 30 | 0 | LDD 300 | |||
| 31 | 1 | INC ACC | |||
| 32 | 1 | STO 300 | |||
| 33 | 1 | INC IX | |||
| 34, 35 | 1 = 2 False → JPN jumps to 22 |
| Instr. addr | ACC | [300] | IX | OUTPUT | Why |
|---|---|---|---|---|---|
| 22 | 1 = 0 False → JPE does not jump | ||||
| 24 | 67 | LDX: 100 + IX(1) = 101 → 67 | |||
| 25 | 100 | ADD 301: 67 + 33 = 100 | |||
| 26 | d | OUT (100 = d) | |||
| 27 | JMP 30 | ||||
| 30 | 1 | LDD 300 | |||
| 31 | 2 | INC ACC | |||
| 32 | 2 | STO 300 | |||
| 33 | 2 | INC IX | |||
| 34, 35 | 2 = 2 True → JPN does not jump | ||||
| 36 | END |
Final output: A d
9. Relative Addressing — LDV
Source: Papers Dock · Paper 1 · 9618 · "Relative and Symbolic Addressing" (past-paper example).
target address = (address of LDV) + n
| Op code | Operand | Binary | Explanation |
|---|---|---|---|
| LDM | #n | 1100 0001 | Immediate addressing. Load number n to ACC. |
| LDD | <address> | 1100 0010 | Direct addressing. Load the contents of the given address to ACC. |
| LDV | #n | 1100 0011 | Relative addressing. Move to the address n locations from the address of the current instruction. Load the contents of this address to ACC. |
| STO | <address> | 1100 0100 | Store the contents of ACC at the given address. |
| DEC | 1100 0101 | Decrement the contents of ACC. | |
| OUTCH | 1100 0111 | Output the character corresponding to the ASCII character code in ACC. | |
| JNE | <address> | 1110 0110 | Following a compare instruction, jump to <address> if the compare was False. |
| JMP | <address> | 1110 0011 | (Unconditionally) jump to the given address. |
| CMP | #n | 1110 0100 | Compare the contents of ACC with number n. |
The processor has one general-purpose register, the Accumulator (ACC), and an Index Register (IX).
Complete the trace table for the program below. ASCII: <Space> = 32, 3 = 51, B = 66, C = 67, X = 88. The teacher numbered each line 0–16 (instruction/data position) to count relative distances.
| # | Label | Instruction | # | Label | Instruction |
|---|---|---|---|---|---|
| 0 | StartProg: | LDV #CountDown | 9 | Finish: | LDM #88 |
| 1 | CMP Num1 | 10 | OUTCH | ||
| 2 | JNE CarryOn | 11 | END | ||
| 3 | JMP Finish | 12 | CountDown: | 15 | |
| 4 | CarryOn: | OUTCH | 13 | 32 | |
| 5 | LDD CountDown | 14 | 51 | ||
| 6 | DEC | 15 | 67 | ||
| 7 | STO CountDown | 16 | Num1: | 32 | |
| 8 | JMP StartProg |
Key idea: the operand of LDV is the value held in CountDown (15 at first), so LDV #15 from address 0 moves to address 15 → 67. Each loop CountDown goes 15 → 14 → 13, so LDV reaches address 15, then 14, then 13 (teacher wrote "LDV #13" for the last).
CMP / jump decisions the teacher wrote:
51 = 32 → False (jumps again → prints 3)
32 = 32 → True (no jump → JMP Finish → LDM #88 → prints X)
| ACC | CountDown | OUTPUT | Why |
|---|---|---|---|
| 15 | initial value | ||
| 67 | C | LDV → address 15 = 67; ≠ 32 so JNE → OUTCH prints C | |
| 15 | LDD CountDown | ||
| 14 | 14 | DEC, STO CountDown | |
| 51 | 3 | LDV → address 14 = 51; ≠ 32 → prints "3" (51) | |
| 14 | LDD CountDown | ||
| 13 | 13 | DEC, STO CountDown | |
| 32 | LDV → address 13 = 32; = 32 True, no JNE jump | ||
| 88 | X | JMP Finish → LDM #88 → OUTCH prints X (88) |
Output: C 3 X
10. Two-Pass Assembler & Symbol Table
The program from (b) is translated using a two-pass assembler. It starts with a directive ORG #0100 which tells the assembler to load the first instruction at address 100.
The teacher's advice: read the code line by line and number each line from 100.
| Addr | Label | Instruction | Addr | Label | Instruction |
|---|---|---|---|---|---|
| 100 | StartProg: | LDV #CountDown | 109 | Finish: | LDM #88 |
| 101 | CMP Num1 | 110 | OUTCH | ||
| 102 | JNE CarryOn | 111 | END | ||
| 103 | JMP Finish | 112 | CountDown: | 15 | |
| 104 | CarryOn: | OUTCH | 113 | 32 | |
| 105 | LDD CountDown | 114 | 51 | ||
| 106 | DEC | 115 | 67 | ||
| 107 | STO CountDown | 116 | Num1: | 32 | |
| 108 | JMP StartProg |
Teacher's marks: ✗ beside JMP Finish (Finish not defined yet → still UNKNOWN), ✓ beside the Finish: line (label found → fill it in).
Symbol table — order of entries (circled numbers)
| Symbolic address | Absolute address |
|---|---|
| StartProg ① | 100 ② |
| CountDown ③ | UNKNOWN ④ → 112 ⑬ |
| Num1 ⑤ | UNKNOWN ⑥ → 116 ⑭ |
| CarryOn ⑦ | UNKNOWN ⑧ → 104 ⑪ |
| Finish ⑨ | UNKNOWN ⑩ → 109 ⑫ |
Explain how the assembler made these entries to the symbol table.
- The assembler scans the assembly language instructions in sequence
- When it meets a symbolic address it checks to see if it is already in the symbol table
- If not, it adds it to the symbol table in the symbolic address column
- If it is already in the symbol table, check if its absolute address is known
- If the absolute address is known, it is entered in the appropriate cell
- If the absolute address is not known, then leave it UNKNOWN
The assembler then completes the second pass, building up the executable file. Name the second table needed.
Answer: Instruction table (maps each mnemonic → its binary op code; the 2nd pass uses it plus the symbol table to produce machine code)
11. Practice — Relative Address Symbol Table
Program translated with a two-pass assembler. The symbol table (symbolic → relative address) shows only the first five entries: StartProg ①, 0 ②, Offset ③, UNKNOWN ④, Value ⑤. Complete the symbol table; use circled labels to show the order of entries.
| # | Label | Instruction | # | Label | Instruction |
|---|---|---|---|---|---|
| 0 | StartProg: | LDV #Offset | 6 | STO Offset | |
| 1 | CMP Value | 7 | JMP StartProg | ||
| 2 | JPE EndProg | 8 | EndProg: | END | |
| 3 | OUTCH | 9 | Offset: | 10 | |
| 4 | LDD Offset | 10–13 | 50, 65, 89, 32 | ||
| 5 | INC | 14 | Value: | 32 |
The board shows this question but the teacher did not write an answer on it.
| Symbolic address | Relative address |
|---|---|
| StartProg ① | 0 ② |
| Offset ③ | UNKNOWN ④ → 9 ⑩ |
| Value ⑤ | UNKNOWN ⑥ → 14 ⑪ |
| EndProg ⑦ | UNKNOWN ⑧ → 8 ⑨ |
Order: ⑦⑧ EndProg met at JPE (line 2); ⑨ EndProg: label at line 8 = 8; ⑩ Offset: label at line 9 = 9; ⑪ Value: label at line 14 = 14. (The 6 remaining entries ⑥–⑪ = the [6] marks.)
12. Quick Recap
- LDM #n — immediate: load the number itself (LDM #100 → ACC 100)
- LDD addr — direct: go to address, load its content (LDD 17 → 19)
- LDI addr — indirect: address holds another address; load from that (LDI 17 → 19 → 30)
- LDX addr — indexed: operand + IX = new address, load from it (LDX 10, IX 9 → addr 19 → 30)
- LDV #n — relative: n locations from the current instruction's address
- Assembly = low-level; one step above machine code (binary)
- OPCODE = instruction; OPERAND = data / address it works on; ACC = where results are stored
- CMP then JPE (jump if True) / JPN or JNE (jump if False)
- Two-pass assembler: pass 1 builds the symbol table, pass 2 (instruction table) builds the executable
- Trace tables: go line by line, record every ACC / memory / IX / OUTPUT change