Cambridge AS & A Level · Part 1 · Chapter 6
Assembly Language Programming
The language one step above the 1s and 0s the processor actually runs. Learn how instructions are built, how an assembler turns them into machine code, and how each addressing mode finds its data. Then run the book's programs one instruction at a time on a working accumulator machine.
Guru Jazzy🎯 Learning objectives
By the end of this chapter you should be able to:
- explain how assembly language relates to machine code
- describe the stages of a two-pass assembler
- Trace a simple assembly language program
- describe the instruction groups: data movement, input and output, arithmetic, unconditional and conditional jumps, and comparisons
- describe the different modes of addressing
- Show your understanding of binary shifts
🔢 6.01 Machine code instructions
A processor only understands one thing: machine code, its own binary instructions. Programs written any other way have to be translated before they can run.
An instruction can have no operand, or up to three. Every processor family has its own instruction set, so machine code written for one kind of processor will not run on another.
When designers create an instruction set, they decide:
- How many bits make up one instruction
- How many of those bits are the opcode
- how many operands there are, and how many bits each one gets
- whether the opcode sits in the most significant bits or the least significant bits
This chapter uses a simple system: a 16-bit address bus and just one general-purpose register, the accumulator (ACC). Its instructions are 24 bits long.
The instruction format Figure 6.01
| Opcode (8 bits, most significant) | Operand | ||
|---|---|---|---|
| Operation 4 bits | Address mode 2 bits | Register addressing 2 bits | 16 bits |
Four bits of operation allow 16 different operations, and each can be used with up to four addressing modes (two bits). The last two opcode bits pick a register.
In the decode stage of the fetch–execute cycle (Chapter 5) the control unit reads just the opcode. In register transfer notation that is:
CU ← [CIR(23:16)] Bits 23 down to 16 of the current instruction register are the 8 opcode bits.
🎮 Lab: decode the machine code
A 24-bit instruction from the book's opcode table (Table 6.04) is shown as opcode | operand. Which instruction is it?
🔤 6.02 Assembly language
Writing raw binary is slow and easy to get wrong. A programmer can work at the same level, one instruction per machine instruction, but with readable text instead.
An assembly instruction has the same two parts as a machine code instruction: a mnemonic for the opcode, and a character representation of the operand. On top of that, an assembler usually lets the programmer use:
- Comments, to explain the code
- Symbolic names for constants
- Labels in place of addresses
- macros: a named sequence of instructions that is written once and used more than once
- directives, such as where in memory to start the program
For: complete control of the hardware; very small, very fast code, which matters for device drivers, embedded systems with tiny memories, and the hottest loops in games or codecs; access to special processor instructions a compiler may not use; understanding what a compiler produces, which helps when debugging and in security work.
Against: slow to write and hard to read; easy to make mistakes; not portable, because it is tied to one instruction set; modern optimising compilers often produce code as good as a person's; a high-level language has libraries, type checking and tools that save huge amounts of time.
🏷️ 6.03 Symbolic, relative and absolute addressing
The same program can be written with three styles of address. The program below takes a number typed at the keyboard as MAX, then reads and adds up that many more single-digit numbers.
Symbolic addressing Table 6.01
Labels name addresses. A label ends with a colon where it is defined; the colon is left off where it is used.
IN
SUB #48
STO MAX
LDM #0
STO TOTAL
STO COUNT
STRTLP: IN
SUB #48
ADD TOTAL
STO TOTAL
LDD COUNT
INC ACC
CMP MAX
JPN STRTLP
END
MAX:
TOTAL:
COUNT: INC ACC the new count is never stored back in COUNT, so COUNT stays 0 and the loop never ends. A fixed version adds STO COUNT straight after INC ACC. You can run both versions in the simulator tab.SUB #48 appear in the program?
IN puts the ASCII code of the key pressed in ACC, not the number itself. The digit characters '0' to '9' have codes 48 to 57, so taking away 48 turns the character code into the digit's value. For example, '7' is 55, and 55 − 48 = 7.
Relative and absolute addressing Table 6.02
With relative addressing, every address is an offset from the address of the first instruction. That start address is held in a base register, BR, so [BR] + 15 means "15 places after the start". With absolute addressing, the program is fixed at real addresses, here 200 to 217.
| Offset | Relative | Address | Absolute |
|---|---|---|---|
| 0 | IN | 200 | IN |
| 1 | SUB #48 | 201 | SUB #48 |
| 2 | STO [BR] + 15 | 202 | STO 215 |
| 3 | LDM #0 | 203 | LDM #0 |
| 4 | STO [BR] + 16 | 204 | STO 216 |
| 5 | STO [BR] + 17 | 205 | STO 217 |
| 6 | IN | 206 | IN |
| 7 | SUB #48 | 207 | SUB #48 |
| 8 | ADD [BR] + 16 | 208 | ADD 216 |
| 9 | STO [BR] + 16 | 209 | STO 216 |
| 10 | LDD [BR] + 17 | 210 | LDD 217 |
| 11 | INC ACC | 211 | INC ACC |
| 12 | CMP [BR] + 15 | 212 | CMP 215 |
| 13 | JPN [BR] + 6 | 213 | JPN 206 |
| 14 | END | 214 | END |
| 15 | MAX | 215 | MAX |
| 16 | TOTAL | 216 | TOTAL |
| 17 | COUNT | 217 | COUNT |
[BR] + 7 and JPN 207. Counting from offset 0, the line labelled STRTLP is at offset 6, and the book's own machine code for JPN STRTLP (Table 6.05) has operand 0110 = 6, so 6 is used here.A relative program can be loaded anywhere: only BR changes. An absolute program only works at the addresses it was written for.
⚙️ 6.04 The two-pass assembler
Before translation starts, the assembler pre-processes the source:
- Comments are removed
- macros are expanded: each use of a macro name is replaced by its instructions
- directives are removed and their information stored for the assembler to use
The problem is the forward reference. STO MAX is the third instruction, but MAX is not defined until the end of the program. When the assembler first meets MAX it has no idea what address it stands for. The answer is to read the program twice.
Symbol table Table 6.03
| Symbol | Offset |
|---|---|
| MAX | +15 |
| TOTAL | +16 |
| COUNT | +17 |
| STRTLP | +6 |
The book prints +7 for STRTLP; see the note above.
Opcode lookup Table 6.04
| Mnemonic | Opcode |
|---|---|
| IN | 0001 0000 |
| SUB # | 0110 0001 |
| STO | 0100 0100 |
| LDM # | 0010 0001 |
| ADD | 0100 0101 |
| LDD | 0010 0101 |
| INC ACC | 0101 0101 |
| CMP | 1000 0100 |
| JPN | 1010 0100 |
| END | 1111 1111 |
🔬 Lab: watch the two passes Tables 6.03 – 6.05
Step through pass 1 to build the symbol table. A ? marks a forward reference that is not resolved yet. Then step through pass 2 to produce the machine code (opcode | 16-bit operand).
| Off | Label | Instruction | Machine code |
|---|
| Symbol | Offset |
|---|
The assembled program Table 6.05
The lab above produces the book's Table 6.05. Points to notice:
- Most operands are 16-bit addresses, but for
SUB #48andLDM #0the operand is the value itself. INandENDhave no operand.INC ACChas none either, because the register is coded inside the opcode.- Addresses start at 0. This is valid output from an assembler but it cannot run as it stands: the addresses must be adjusted when the program is loaded into its real place in memory.
- The last three words are the zeroed storage for MAX, TOTAL and COUNT.
🎮 Your turn: build the symbol table
A fresh program each time. Work out the address of every label, as pass 1 would.
🎯 6.05 Addressing modes
The four modes Table 6.06
| Mode | What the operand is | Example |
|---|---|---|
| Immediate | The value itself | SUB #48 |
| Direct | The address that holds the value | ADD TOTAL |
| Indirect | An address that holds the address of the value | LDI 106 |
| Indexed | An address; add the index register (IX) to it to get the address of the value | LDX 102 |
An immediate value can be written three ways. These all mean the same number:
| Written as | Base |
|---|---|
| #48 | denary |
| #B00110000 | binary |
| #&30 | hexadecimal |
Relative addressing (section 6.03) is a fifth way to find an address: the operand is an offset added to the base register.
🎮 Name the mode
🧪 Addressing-mode drill
A new memory snapshot every time. Work out what ends up in the accumulator, then check. The path the processor follows is highlighted.
| Address | Contents |
|---|
🧰 6.06 Assembly language instructions
The instructions here are typical of a simple processor. They do not belong to any real one, but exam questions use this set. The mnemonic alone tells you the type of instruction, which register it uses and which addressing mode.
Data movement Table 6.07
| Instruction | What it does |
|---|---|
| LDM #n | Load the number n into ACC (immediate) |
| LDR #n | Load the number n into IX (immediate) |
| LDD <address> | Copy the contents of the address into ACC (direct) |
| LDI <address> | The address holds a second address; copy the contents of that second address into ACC (indirect) |
| LDX <address> | Add IX to the address to form a new address; copy its contents into ACC (indexed) |
| MOV <register> | Copy the contents of ACC into the register (IX) |
| STO <address> | Store the contents of ACC at the address |
Worked examples on one memory snapshot Figure 6.02
| Address | Contents |
|---|---|
| 100 | 234 |
| 101 | 208 |
| 102 | 201 |
| 103 | 110 |
| 104 | 108 |
| 105 | 206 |
| 106 | 101 |
| 107 | 102 |
| INDEXVALUE | 3 |
LDD 103copies 110 into ACC.LDI 106: address 106 holds 101, and address 101 holds 208, so ACC becomes 208.STO 106then writes 208 into address 106.LDD INDEXVALUEputs 3 into ACC.MOV IXcopies the 3 into the index register.LDX 102: 102 + 3 = 105, which holds 206, so ACC becomes 206.
Load the Figure 6.02 program in the simulator tab to watch these happen one by one.
Input and output
INwaits for a key press and stores that character's ASCII code in ACC.OUTdisplays the character whose ASCII code is in ACC.
Compare and jump Table 6.08
| Instruction | What it does |
|---|---|
| JMP <address> | Jump to the address (unconditional) |
| CMP <address> | Compare ACC with the contents of the address |
| CMP #n | Compare ACC with the number n |
| CMI <address> | Compare ACC with the contents of the address held at the address (indirect) |
| JPE <address> | After a compare, jump if the compare was True (equal) |
| JPN <address> | After a compare, jump if the compare was False (not equal) |
A compare only tests for equality. The True/False result is kept as a flag in the status register. A jump works by overwriting the program counter, which was already incremented during the fetch.
Arithmetic Table 6.09
| Instruction | What it does |
|---|---|
| ADD <address> | Add the contents of the address to ACC |
| ADD #n | Add the number n to ACC |
| SUB <address> | Subtract the contents of the address from ACC |
| SUB #n | Subtract the number n from ACC |
| INC <register> | Add 1 to ACC or IX |
| DEC <register> | Subtract 1 from ACC or IX |
There is no multiply or divide. You have to build them from adds and loops, as in Figure 6.03, which finds how many times 5 goes into 75:
100 LDD 200 ; ACC = 0 101 STO 202 ; count = 0 102 STO 203 ; running total = 0 103 LDD 202 ; loop starts here 104 INC ACC 105 STO 202 ; count + 1 106 LDD 203 107 ADD 201 108 STO 203 ; total + 5 109 CMP 204 ; reached 75? 110 JPN 103 ; no: go round again 111 LDD 202 112 OUT ; output the count 113 END 200 0 201 5 202 203 204 75
- 100–102 set up: the count and the total both start at 0.
- 103 is where each loop starts.
- 104–105 add 1 to the count.
- 106–108 add 5 to the total.
- 109–110 check whether the total has reached 75; if not, jump back.
- 111–113 output the count, 15, and stop.
Load Figure 6.03 in the simulator. Notice that OUT sends ASCII code 15, which is a control character, not the digits "15". The simulator shows the code so you can see it.
Shift instructions
| Instruction | What it does |
|---|---|
| LSL #n | Shift the bits in ACC n places to the left; zeros enter on the right |
| LSR #n | Shift the bits in ACC n places to the right; zeros enter on the left |
- A logical shift left by one multiplies an unsigned number by 2, as long as the top bit was 0.
- A logical shift right by one is integer division by 2; the remainder ends up in the carry bit. For example, 0011 0001 (49) becomes 0001 1000 (24) with carry 1.
- Logical shifts do not work for signed (two's complement) numbers, because the sign bit gets changed.
Bitwise logic Table 6.10
| Instruction | What it does |
|---|---|
| AND #Bn / AND <address> | Bitwise AND of ACC with the operand; result in ACC |
| XOR #Bn / XOR <address> | Bitwise XOR of ACC with the operand; result in ACC |
| OR #Bn / OR <address> | Bitwise OR of ACC with the operand; result in ACC |
The operand is called a mask. AND with a 1 keeps a bit and with a 0 clears it; OR with a 1 sets a bit; XOR with a 1 flips it. You will use masks properly in Chapter 7 (section 7.03).
🔬 Lab: the 8-bit register
Tap bits to set the value, then shift or mask it. The dashed box is the carry bit.
🎮 Predict the result
🎮 Which group?
Sort each instruction into its group.
🔍 6.07 Further consideration of the instructions
Register transfer notation
RTN from section 6.01 can describe what an instruction does. For LDD:
ACC ← [[CIR(15:0)]] Only the 16-bit operand in the CIR matters here. It is an address; the contents of that address are copied into the accumulator.
LDI instruction executes.
ACC ← [[[CIR(15:0)]]] Read it from the inside out: CIR(15:0) is the operand address; one pair of brackets gives the contents of that address, which is a second address; the next pair gives the contents of that second address, which is copied into ACC. One more level of brackets than LDD, because indirect addressing needs one more memory look-up.
Computer arithmetic and the status register
Chapter 1 (section 1.03) showed that arithmetic can overflow and give a wrong answer. Chapter 5 (section 5.02) introduced the status register. Three of its flags let the processor spot an overflow:
- C, the carry flag: set to 1 if there is a carry out of the top bit
- N, the negative flag: set to 1 if the result is negative
- V, the overflow flag: set to 1 if overflow is detected
Worked Example 6.01 · Using the status register in an arithmetic operation
1 Add 66 and 68 in 8-bit two's complement Figure 6.04
0100 0010 (66) + 0100 0100 (68) --------- 1000 0110 (-122) Flags: N V C = 1 1 0
Two positive numbers have produced a negative answer, which is impossible. The negative flag and the overflow flag are both 1; the processor checks the flags, spots the problem and generates an interrupt.
2 Add −66 and −68 Figure 6.05
1011 1110 (-66) + 1011 1100 (-68) --------- (1)0111 1010 (+122) Flags: N V C = 0 1 1
Two negatives have given a positive. This time the negative flag is 0 while overflow and carry are both 1.
1011 1110 (-66) + 0100 0100 (68) --------- (1)0000 0010 (+2) Flags: N V C = 0 0 1
The 8-bit answer, 2, is correct. There is a carry out of the top bit, but no overflow, because a positive and a negative number can never overflow when added. For signed (two's complement) arithmetic the processor should simply ignore the carry; it is the V flag that signals an error. The carry only matters for unsigned arithmetic, or when adding numbers bigger than one byte in several steps.
🔬 Lab: flags after an 8-bit addition
🎮 Predict the flags
🖥️ The accumulator machine
This runs the book's instruction set. Choose one of the book's programs, or write your own, then Step through it one instruction at a time. Memory, ACC, IX and the program counter update as you go, and every step is added to the trace table underneath.
- One instruction or data value per line. A line can start with an address (
100 LDD 200) or a label (STRTLP: IN), or both. Lines without an address follow on from the line before. - A data line is just a value (
204 75,TOTAL: 0). A label or address on its own is an empty word. - Values can be denary
48, binaryB0011or hex&30; immediate operands start with#. ;starts a comment..ACC nand.IX nset the registers before the run;.START asets where it begins.INtakes from the Input box. Choose whether each key gives its ASCII code, or whether the box holds whole numbers.- Shifts and logic work on 8 bits, like the book's examples.
| Addr | Label | Contents |
|---|
| Step | Addr | Instruction | ACC | IX | Memory | Output |
|---|
🧾 Tracing an assembly language program
A dry run checks a program for errors by following it by hand. The main thing to record is how the accumulator changes, in a trace table.
Worked Example 6.02 · Tracing a program
The trace table needs a column for the accumulator, one for each of two memory locations, and one for output. The inputs are 15, then 27, then 31.
| Address | Instruction |
|---|---|
| 100 | IN |
| 101 | STO 200 |
| 102 | IN |
| 103 | STO 201 |
| 104 | IN |
| 105 | ADD 200 |
| 106 | STO 200 |
| 107 | ADD 201 |
| 108 | INC ACC |
| 109 | OUT |
| 110 | END |
| ACC | 200 | 201 | Output |
|---|---|---|---|
| 15 | |||
| 15 | |||
| 27 | |||
| 27 | |||
| 31 | |||
| 46 | |||
| 46 | |||
| 73 | |||
| 74 | |||
| 74 |
Figure 6.06 (program) and Figure 6.07 (trace table)
Here each instruction gets its own row, which makes checking easy. It is also correct to write each value in the next free space in its column, so the 200 column could just read 15, 46. You only record changes: if an instruction leaves a column alone, you do not copy the old value down.
Worked Example 6.03 · A trace with a jump
Instructions are in 100 upwards and 4-bit data values in 200 upwards. ACC already holds 1000 from an earlier instruction.
| Address | Contents |
|---|---|
| 100 | LDD 200 |
| 101 | INC ACC |
| 102 | ADD 201 |
| 103 | CMP 202 |
| 104 | JPE 106 |
| 105 | DEC ACC |
| 106 | INC ACC |
| 107 | STO 203 |
| 200 | 0001 |
| 201 | 0011 |
| 202 | 0101 |
| 203 |
| PC | ACC | 203 |
|---|---|---|
| 100 | 1000 | |
| 101 | 0001 | |
| 102 | 0010 | |
| 103 | 0101 | |
| 104 | ||
| 106 | ||
| 107 | 0110 | |
| 108 | 0110 |
Figure 6.08 (memory before the run) and Figure 6.09 (trace table)
Because there is a jump, the program counter gets a column too.
- Row 1 is the state before this part runs: ACC holds a value left by an earlier instruction.
- Row 2: the instruction at 100 loads ACC, and the PC is incremented automatically.
- Rows 3 and 4: the instructions at 101 and 102 change ACC, and the PC goes up each time.
- Row 5: just a compare, so ACC does not change, but the PC still increments.
- Row 6: the PC jumps to 106, because the JPE found the compare was True.
- Row 7: the instruction at 106 has incremented ACC.
- Row 8: the value has been stored in 203.
Yes, it could. Instructions and data share the same memory (the von Neumann model), so a STO with an address between 100 and 107 would overwrite an instruction with a data value. This program does not do that, because its only store is to 203. Try adding STO 105 in the simulator: it warns you when an instruction gets overwritten.
The keys typed are '3', '7', '8', '9', which arrive as ASCII 51, 55, 56, 57. MAX becomes 3. TOTAL goes 0 → 7 → 15 → 24.
COUNT is the catch. It is loaded (0), incremented to 1 and compared with MAX, but it is never stored back. Every loop it is reloaded as 0, so it never reaches 3: after the third input the program waits for a fourth key, forever. With STO COUNT added after INC ACC, COUNT goes 1, 2, 3, the compare is True after the third number and the program ends with TOTAL = 24.
Load Table 6.01 and Table 6.01 (fixed) in the simulator to compare the two traces.
🎮 Trace it yourself
A new program and data every time. Fill in ACC after each instruction, and the value written by each STO. Leave ACC blank when it does not change, as in the book.
| Addr | Instruction | ACC | Stored |
|---|
📌 Summary
- A machine code instruction is made of an opcode and an operand.
- An assembly language program holds assembly instructions plus directives that give information to the assembler.
- In its first pass, a two-pass assembler works out the relative addresses of the symbolic addresses.
- The processor's addressing modes are immediate, direct, indirect and indexed.
- Instructions fall into groups: data movement, input/output, compare and jump, arithmetic, shift and logical.
🃏 Key-term flashcards
Tap a card to flip it.
✅ Quick quiz
📝 Exam-style questions
Write your answer first, then open the model answer. These are my mark-scheme-style points, not official mark schemes.
Question 1 uses three instructions for a processor whose only general-purpose register is the accumulator: LDD <address> (direct), LDI <address> (indirect) and LDX <address> (indexed). All values are denary. Memory and registers are:
| Address | Content |
|---|---|
| 100 | 116 |
| 101 | 114 |
| 102 | 112 |
| 103 | 110 |
| 104 | 108 |
| 105 | 106 |
| 106 | 104 |
| 107 | 102 |
Accumulator: empty
Index register: 3
(i) An arrow from the operand 103 to memory address 103; an arrow from the contents of 103 (110) into the accumulator.
(ii) 110
(i) Arrow from the operand to address 107; its contents, 102, are used as an address, so an arrow from 107's contents to address 102; an arrow from the contents of 102 (112) into the accumulator.
(ii) 112
(i) Arrow from the index register (3) and the operand 103 to an addition: 103 + 3 = 106; an arrow to address 106; an arrow from its contents (104) into the accumulator.
(ii) 104
Any three, each named (1) and its use described (1):
- Comments: notes that explain what the code does, for people reading it; removed before translation.
- Directives: instructions to the assembler, e.g. the address to load the program at, or reserving and initialising memory for data; acted on by the assembler, not translated.
- Macros: a named block of instructions defined once; each use of the name is replaced (expanded) by the full block before translation.
- Labels / symbolic addresses: names for addresses that are swapped for real (relative) addresses using the symbol table.
- Symbolic constants: names given to fixed values, replaced by the values during assembly.
100 LDD 201 101 INC ACC 102 STO 202 103 LDI 203 104 DEC ACC 105 STO 201 106 ADD 204 107 STO 201 108 END 201 10 202 0 203 204 204 5
| ACC | 201 | 202 | 203 | 204 |
|---|---|---|---|---|
| 0 | 10 | 0 | 204 | 5 |
| 10 | ||||
| 11 | ||||
| 11 | ||||
| 5 | ||||
| 4 | ||||
| 4 | ||||
| 9 | ||||
| 9 |
LDI 203: 203 holds 204, and 204 holds 5, so ACC = 5. The book's listing numbers two lines 105; the second is 106. Try it as an auto-marked trace in the simulator tab (Exam question 2b).
Question 3 refers to this program:
IN
STO CHARACTER
IN
SUB #48
START: CMP #0
JPN OUTPUT
END
OUTPUT: OUT
DEC ACC
JMP START
CHARACTER: - Two key presses.
- The first is any character; its ASCII code is stored in CHARACTER.
- The second should be a digit, 0–9.
- 48 is subtracted from its ASCII code to turn it into the number it represents, which is used as a counter.
- The loop runs once for each count from the digit down to 1, so it outputs that many characters.
- If the digit is 0, nothing is output.
- The intended output is the first character repeated that many times (e.g. "A" then "3" gives AAA).
OUT sends whatever is in ACC, which is the counter, not CHARACTER. So it actually outputs the characters with ASCII codes n, n−1, … 1 (non-printing control codes). To print the character you would need to keep the counter in memory and LDD CHARACTER before OUT. Run both versions in the simulator to see the difference. Either reading should earn the marks if you explain it.| Label | Address |
|---|---|
| START | 4 |
| OUTPUT | 7 |
| CHARACTER | 10 |
Count the lines from 0: IN (0), STO (1), IN (2), SUB (3), CMP (4) is START, JPN (5), END (6), OUT (7) is OUTPUT, DEC (8), JMP (9), and CHARACTER is the next word, 10.
Question 4 uses this instruction set for a processor with one general-purpose register, the accumulator (ACC), and an index register (IX):
| Op code | Operand | Explanation |
|---|---|---|
| LDD | <address> | Direct addressing: load the contents of the address into ACC |
| LDX | <address> | Indexed addressing: form the address from <address> + IX, then copy the contents of that address into ACC |
| STO | <address> | Store ACC at the address |
| ADD | <address> | Add the contents of the address to ACC |
| INC | <register> | Add 1 to ACC or IX |
| DEC | <register> | Subtract 1 from ACC or IX |
| CMP | <address> | Compare ACC with the contents of the address |
| JPE | <address> | After a compare, jump to the address if it was True |
| JPN | <address> | After a compare, jump to the address if it was False |
| JMP | <address> | Jump to the address |
| OUT | Output the character whose ASCII value is in ACC | |
| END | Return control to the operating system |
| Address | Contents |
|---|---|
| 60 | 0011 0010 |
| 61 | 0101 1101 |
| 62 | 0000 0100 |
| 63 | 1111 1001 |
| 64 | 0101 0101 |
| 65 | 1101 1111 |
| 66 | 0000 1101 |
| 67 | 0100 1101 |
| 68 | 0100 0101 |
| 69 | 0100 0011 |
| … | |
| 1000 | 0110 1001 |
Index register: 0000 1000
Accumulator: 0100 0101
IX holds 0000 1000 = 8. The address used is 60 + 8 = 68, and address 68 holds 0100 0101, which is copied into ACC.
Index register: 0000 0111 (8 − 1 = 7)
Cambridge International AS & A Level Computer Science 9608, Paper 11 Q9a, June 2016
Guru Jazzy · Cambridge AS & A Level Computer Science · Chapter 6 Assembly Language Programming · Opener photo from the Cambridge coursebook (Langfield & Duddell)