Year 12

AQA A level Computer Science [P1] Translation & Addressing Notes

Two-Way Translation & Symbolic Addressing

— Computer Science · AS / A Level (9618) · Paper 1 —
★ Exam Tip: Partial compilation + partial interpretation was a repeated query from students. It is asked via Java (w17 qp11 q3) and as “explain why high-level languages might be partially compiled and partially interpreted” — worth only 2 marks, so learn the 2 points by heart. The assembler part (symbol tables, relative addressing, trace table) comes as a full structured question.
Contents: A. Partial compilation & interpretation (Java, byte code, JVM, why)  |  B. Instruction set & addressing modes  |  C. Two-pass assembler & symbol table  |  D. Past-paper question fully solved (trace table, symbol tables, relative addresses)  |  E. Cheat-sheet

1. Translation Recap — Compiler vs Interpreter

Translation = turning your source code into something the CPU understands (machine code = the language the computer can understand). Two ways:

CompilerInterpreter
Howtranslates the whole program first, then it is runtranslates + runs it line by line while running
Outputcomplete machine code for that CPU / OSno separate executable produced
Good / badfast to run, but only runs where it was compiledportable, easy to test, but slower
Sir says: both have their own advantages & disadvantages — you already studied them in System Software. Today = the special case where we use both.

(recap row facts are the standard textbook ones from System Software; the recording only points back to them.)

2. Partial Compilation + Partial Interpretation

Idea: do half of the translation by compiling, then do the other half by interpreting ⇒ we combine the advantages of compilation and of interpretation.

Partial compilation + Partial interpretation = “Two-way translation process”
(“half compiled, half interpreted”)
Remember the NAME: sir stressed it — two-way translation process. The mark-scheme wording for Java says “two-step translation process” — same thing, so use the words partially compiled and partially interpreted in your answer.

3. Example — How Java Source Code is Translated

Java is the language that uses the two-way process. Past paper: “Describe how a Java source code program is translated.”

w17 qp11 q3structured · Java translation (reference as said on the recording)

Steps to remember:

  1. The code you write (source code) first goes into the Java compiler.
  2. The compiler does only an intermediate translation — not a complete translation into machine code. It leaves byte code.
  3. The byte code is then interpreted by the Java Virtual Machine (JVM).

Mark-scheme style answer:

  • Java uses a two-step translation process / is partially compiled and partially interpreted
  • code is first translated into byte code by compilation using the Java compiler
  • the byte code is then interpreted by using the Java Virtual Machine
Java sourcecode BYTE CODE(intermediate) machine code madeat run time → CPU Java compiler JVM (interprets) ① partial COMPILATION ② partial INTERPRETATION
source → (compile) → byte code → (interpret in JVM) → machine code for the actual CPU

What is byte code? (sir’s link to assembly)

Remember the assembly questions: LDM #97 → you wrote the binary op-code of LDM from the table, then converted 97 to binary in a second box. That pair of boxes is exactly the idea of a byte code: instruction + the data to work on, written in 0s and 1s.

Assemblybox 1 · op-codebox 2 · data
LDM #971100 00010110 0001

(LDM op-code from this paper’s table; 97 = 64 + 32 + 1 = 0110 0001. Used only as the analogy — real Java byte code has its own op-codes.)

The Java compiler makes this half-way (“intermediate”) code; it is not complete machine code, so nothing is run yet.

What is the JVM?

A virtual machine = a software “device” that behaves like a machine. Like running another OS on a normal PC, the JVM lets many different CPUs / PCs each interpret the same byte code. So: byte code → interpreted through the Java Virtual Machine.

Sir’s note: don’t go deeper than this in the exam — just Java compiler → byte code → JVM interprets. The benefits of byte code are the next section.

4. Why Partially Compile & Partially Interpret?

Recent past paper2-mark explain

“Explain why high-level languages might be partially compiled and partially interpreted.”

Answer (2 marks = 2 points):

  • ① Partially compiled programs (byte code) can be used on different platforms as they are interpreted when run.
  • ② The code is optimised for the CPU as the machine code is generated at run time.

Advantage ① — runs on ANY platform, no re-compiling

  • Normal full compilation on Windows ⇒ complete machine code for that CPU/OS only. It will not work on Linux or iOS (it works only where it was compiled).
  • Byte code is just numbers / bits (0s and 1s) ⇒ platform-neutral ⇒ can be used on any platform.
  • The same Java program runs on Windows, Mac or Linux without re-compiling (no “compile on Windows, then compile again for Linux”). Compile once to byte code and you are done.
Source machine code(Windows) Windows ✓Linux ✗iOS ✗
full compile on Windows = stuck on Windows
Source byte code(once) JVM · Windows ✓JVM · Linux ✓JVM · Mac ✓
one byte code, interpreted by a JVM on each platform

Advantage ② — optimised for each CPU

  • The byte code is optimised for that particular CPU (whatever OS / hardware is installed) during the interpretation phase.
  • The virtual machine can use information about the hardware architecture: number of cores, memory system / RAM, memory consumption, storage — different for every CPU.
  • It uses this to generate the most efficient machine code = the code that makes the CPU run fastest.
  • So the same byte code executes on different CPUs, but the machine code is generated at run time for that particular CPU ⇒ optimised.
Common mistake: saying the optimised machine code is made when you compile. No — compile only gives byte code. Machine code is generated at run time (while interpreting).
✓ Quick Recap — Part A
  • Partial compilation + partial interpretation = two-way translation process
  • Java: source → Java compiler → byte code → JVM interprets
  • Benefit 1: byte code runs on any platform, no re-compiling
  • Benefit 2: machine code made at run time ⇒ optimised for that CPU

5. Instruction Set & Addressing Modes (Board)

Processor has one general-purpose register — the Accumulator (ACC) — and an Index Register (IX). Part of its instruction set:

MnemonicOperandOp code (binary)Explanation
LDM#n1100 0001Immediate addressing. Load number n to ACC.
LDD<address>1100 0010Direct addressing. Load the contents of the given address to ACC.
LDV#n1100 0011Relative addressing. Move to the address n locations from the address of the current instruction; load the contents of that address to ACC.
STO<address>1100 0100Store the contents of ACC at the given address.
DEC—1100 0101Decrement the contents of ACC.
OUTCH—1100 0111Output the character for the ASCII code in ACC.
JNE<address>1110 0110After a compare, jump to <address> if the compare was False.
JMP<address>1110 0011(Unconditionally) jump to the given address.
CMP#n1110 0100Compare the contents of ACC with number n.
Three kinds of address:
Absolute = the actual fixed memory address (e.g. 112).  |  Symbolic = a label / name used instead of a number (e.g. CountDown) — the assembler converts it.  |  Relative = a position given as a distance (offset) from a reference point — in LDV the reference is the current instruction; in the part-(e) symbol table it is the start of the program (0).
Careful: in the programs below CMP Num1 has no # ⇒ it compares ACC with the contents of the address Num1, not with a number.

Each instruction and each data line takes one memory location ⇒ one line = one address (add 1 per line).

6. Two-Pass Assembler & Symbol Table

An assembler translates assembly language into machine code. A two-pass assembler reads the program twice because a label can be used before it is defined (e.g. JMP Finish comes before the line Finish:).

Assemblyprogram PASS 1build SYMBOLTABLE PASS 2replace labels +mnemonics machinecode symbol table is handed to pass 2
pass 1 makes the symbol table; pass 2 builds the executable file

Pass 1 — building the symbol table

  1. ORG directive: tells the assembler to load the first instruction at that address (e.g. ORG #0100 ⇒ first instruction at address 100). With no ORG the program starts at relative address 0.
  2. Read line by line, counting the address (+1 per line).
  3. A label on a line (e.g. StartProg:) → enter label + that line’s address.
  4. A label used in an operand before its line has been reached → enter it with UNKNOWN (address not known yet).
  5. When the assembler later reaches the line that defines it → cross out UNKNOWN and write the real address.

Pass 2 — building the executable

  • Uses the symbol table to replace every symbolic operand with its address.
  • Uses the opcode table (the second table needed) to replace each mnemonic with its binary op code → machine code.
Exam Q — (d)(i): “Name the second table needed when the assembler carries out the second pass.” → Opcode table (mnemonic → binary op code) [1]. The first table is the symbol table.

7. Question (b) — Trace Table with LDV (Relative Addressing)

9618 P1 · (b)trace table [5]

Complete the trace table for the assembly program (columns ACC · CountDown · OUTPUT). The first two rows are given: CountDown = 15 at the start, then ACC = 67 and output C.

ASCII table given (character = code): space = 32 · “3” = 51 · B = 66 · C = 67 · X = 88 (B = 66 is never used — a distractor).

LDV ⋯ 1532516732 100112113114115116 +15 → 115 → ACC = 67 +14 → 114 → ACC = 51 +13 → 113 → ACC = 32 ← CountDown(112) Num1 = 116
each pass the offset gets 1 smaller, so the arc lands one cell to the left
AddrLabelInstruction
100StartProg:LDV #CountDown
101CMP Num1
102JNE CarryOn
103JMP Finish
104CarryOn:OUTCH
105LDD CountDown
106DEC
107STO CountDown
108JMP StartProg
109Finish:LDM #88
110OUTCH
111END
112CountDown:15
11332
11451
11567
116Num1:32
How LDV works here: the address is relative to the LDV line itself (100). Operand n = the value held in CountDown (starts at 15) ⇒ go to 100 + 15 = 115, load its contents (67) into ACC.
Check: this matches the given row — ACC = 67 then output C (67 = C). ✓ So the CountDown value is the offset, not 112.
Loop idea: CountDown goes 15 → 14 → 13, so LDV walks backwards through the data: 67, 51, 32. When ACC equals Num1 (32) the compare is True ⇒ JNE does not jump ⇒ JMP Finish.

Dry run — one round per column

Round 1 · CountDown = 15 LDV: 100 + 15 = 115 ACC = 67 CMP Num1: 67 ≠ 32 → False JNE → jump to CarryOn OUTCH → prints C LDD CountDown: ACC = 15 DEC: ACC = 14 STO: CountDown = 14 JMP StartProg
Round 2 · CountDown = 14 LDV: 100 + 14 = 114 ACC = 51 CMP: 51 ≠ 32 → False JNE → jump to CarryOn OUTCH → prints 3 LDD CountDown: ACC = 14 DEC: ACC = 13 STO: CountDown = 13 JMP StartProg
Round 3 · CountDown = 13 LDV: 100 + 13 = 113 ACC = 32 CMP: 32 = 32 → True JNE: no jump JMP Finish LDM #88: ACC = 88 OUTCH → prints X END

Whole output: C 3 X

Completed trace table:

ACCCountDownOUTPUTcaused by
15start (given)
67CLDV, OUTCH (given)
15LDD
14DEC
14STO
513LDV, OUTCH
14LDD
13DEC
13STO
32LDV (CMP equal)
88XLDM #88, OUTCH
★ Exam Tip: write a value only on the row where it changes (ACC for LDV/LDD/DEC/LDM, CountDown only at STO). CMP, JNE, JMP change nothing. The question gives 11 blank rows — this uses 10, so a spare is fine.

8. Question (c) — Symbol Table & Explanation

9618 P1 · (c)symbol table + explain [3] · (d)(i) [1]

The same program is translated by a two-pass assembler. It now begins with the directive ORG #0100, which loads the first instruction at address 100. Complete the symbol table (5 blank rows).

Count addresses from 100: ORG is only an instruction to the assembler — it takes no memory location (LDV = 100 ✓ board shows CarryOn = 104).

Symbolic addressAbsolute addresshow
StartProg1001st instruction (ORG)
CountDown112100 + 12 lines
Num1116last data line
CarryOn1045th instruction (OUTCH)
Finish109LDM #88 line

Board’s part-way table (first 11 entries) — what each circle means

CirclesSymbolic → AbsoluteWhy the assembler did it
① ②StartProg → 100first label on line 1; ORG #0100 puts the first instruction at 100
③ ④CountDown → UNKNOWNused in LDV #CountDown before its own line is reached
⑤ ⑥Num1 → UNKNOWNused in CMP Num1, line not reached yet
⑦ ⑧CarryOn → UNKNOWNused in JNE CarryOn, line not reached yet
⑨ ⑩Finish → UNKNOWNused in JMP Finish, line not reached yet
⑪CarryOn: UNKNOWN → 104assembler now reaches the line labelled CarryOn (5th line: 100 + 4) → crosses out UNKNOWN, writes 104
Explain how the assembler made these entries[3]
  • ① StartProg is the first label, so it is entered with address 100 — the address of the first instruction given by the ORG directive.
  • ② CountDown, Num1, CarryOn, Finish are found in operands before the lines that define them (forward references), so each is entered with UNKNOWN.
  • ③ On reaching the line labelled CarryOn the assembler works out its address (104, counting one per line from 100) and replaces UNKNOWN; the same happens later for Finish, CountDown and Num1.

(d)(i) second table in pass 2: Opcode table

9. Question (e) — Relative-Address Symbol Table

9618 P1 · (e)symbol table, circled order [6]

A different program is translated by a two-pass assembler, with no ORG, so the table holds relative addresses (offset from the start, first instruction = 0). Complete the symbol table and use circled numbers for the order of entries. Given: ① StartProg, ② 0, ③ Offset, ④ UNKNOWN, ⑤ Value.

Rel.LabelInstruction
0StartProg:LDV #Offset
1CMP Value
2JPE EndProg
3OUTCH
4LDD Offset
5INC
6STO Offset
7JMP StartProg
8EndProg:END
9Offset:10
1050
1165
1289
1332
14Value:32

Completed symbol table

Symbolic addressRelative address
StartProg ①0 ②
Offset ③UNKNOWN ④  9 ⑩
Value ⑤UNKNOWN ⑥  14 ⑪
EndProg ⑦UNKNOWN ⑧  8 ⑨
Note: JPE (jump if compare True / equal) and INC (add 1 to ACC) are not in the table above, but for addressing they are just one line = one location.

Order of entries (circles)

  1. ① ② StartProg is the first label ⇒ relative address 0.
  2. ③ ④ LDV #Offset: Offset not seen yet ⇒ enter with UNKNOWN.
  3. ⑤ ⑥ CMP Value: Value not seen yet ⇒ UNKNOWN.
  4. ⑦ ⑧ JPE EndProg: EndProg not seen yet ⇒ UNKNOWN (4th row of the table).
  5. ⑨ reaches line EndProg: END = line 8 ⇒ UNKNOWN → 8.
  6. ⑩ reaches Offset: (first data line) = line 9 ⇒ UNKNOWN → 9.
  7. ⑪ reaches Value: (last data line, 6 data items 9–14) ⇒ UNKNOWN → 14.
Common mistake: filling the final addresses but not the circled order, or giving 100-style absolute addresses. Here the program has no ORG, so start counting at 0.
✓ Full Cheat-Sheet
  • Two-way translation = partially compiled + partially interpreted. Java: source → Java compiler → byte code → JVM interprets.
  • Why: ① byte code works on any platform / no re-compile ② machine code generated at run time ⇒ optimised for the CPU.
  • Addressing: immediate LDM #n · direct LDD addr · relative LDV #n (n locations from the current instruction) · symbolic = labels · absolute = fixed address.
  • ORG #0100 = first instruction at address 100 (no memory used). No ORG ⇒ relative addresses from 0.
  • Pass 1: build symbol table (count +1 per line; forward references = UNKNOWN, replaced when the label’s line is reached).
  • Pass 2: swap symbols for addresses (symbol table) and mnemonics for binary (opcode table) ⇒ executable machine code.
  • (c) answer: StartProg 100 · CountDown 112 · Num1 116 · CarryOn 104 · Finish 109.
  • (b) output: C 3 X; ACC sequence 67, 15, 14, 51, 14, 13, 32, 88; CountDown 15 → 14 → 13.
  • (e) answer: StartProg 0 · Offset 9 · Value 14 · EndProg 8 (order ①–⑪).