Operating systems, software and translators · A level · OCR H446 1.2.2, AQA 7517 4.6.2.1, Eduqas A500QS 1.8 · about 45 min
Machine code, assembly and imperative high-level languages, the Little Man Computer, and choosing an assembler, compiler, interpreter or bytecode.
[1 mark]Which describes assembly language?
[1 mark]Which are advantages of writing in assembly language rather than a high-level language?
Tick every answer that is true.
[1 mark]In the Little Man Computer, what does the instruction BRZ 12 do?
[1 mark]Why do most assemblers make two passes over the source code?
[1 mark]A company is releasing a game to the public and does not want players to see how it works. Which translator should it use, and why?
[1 mark]Why do some compilers produce bytecode rather than machine code?
Write a two-pass assembler for the LMC program in source, a list of strings, one line per address starting at address 0. Each line is one of: a mnemonic alone ("OUT"); a mnemonic and an operand ("BRZ end"); a label and a mnemonic ("end HLT"); or a label, a mnemonic and an operand ("one DAT 1"). A word is a label if it is not a key in OPCODES. An operand is either a label or a whole number.
- Pass 1: for each line that has a label, store the label and its address in a dictionary, and print <label> = <address>.
- Pass 2: for each line, the machine code is the opcode from OPCODES plus the operand's value (the label's address, or the number, or 0 if there is no operand). Print <address>: <code>, with the code as three digits, so 0 prints as 000 and 1 as 001.
The robot stays still.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
OPCODES = {"ADD": 100, "SUB": 200, "STA": 300, "LDA": 500, "BRA": 600, "BRZ": 700,
"BRP": 800, "INP": 901, "OUT": 902, "HLT": 0, "DAT": 0}
source = [
"INP",
"STA count",
"loop LDA count",
"OUT",
"BRZ end",
"SUB one",
"STA count",
"BRA loop",
"end HLT",
"count DAT",
"one DAT 1",
]The hint students can ask for: The first pass only needs to notice labels and remember which address each is on. The second pass looks up the opcode for each mnemonic and adds the operand, which is either a number or a label to look up. A word is a label if it is not a mnemonic.
from bugbot import *
connect()
OPCODES = {"ADD": 100, "SUB": 200, "STA": 300, "LDA": 500, "BRA": 600, "BRZ": 700,
"BRP": 800, "INP": 901, "OUT": 902, "HLT": 0, "DAT": 0}
source = [
"INP",
"STA count",
"loop LDA count",
"OUT",
"BRZ end",
"SUB one",
"STA count",
"BRA loop",
"end HLT",
"count DAT",
"one DAT 1",
]
def split_line(line):
parts = line.split()
label = None
if parts[0] not in OPCODES:
label = parts.pop(0)
mnemonic = parts[0]
operand = parts[1] if len(parts) > 1 else None
return label, mnemonic, operand
symbols = {}
for address, line in enumerate(source):
label, mnemonic, operand = split_line(line)
if label is not None:
symbols[label] = address
print(f"{label} = {address}")
for address, line in enumerate(source):
label, mnemonic, operand = split_line(line)
if operand is None:
value = 0
elif operand in symbols:
value = symbols[operand]
else:
value = int(operand)
code = OPCODES[mnemonic] + value
print(f"{address}: {code:03d}")
Any program that meets the task's checks is marked correct in the simulator; this is one way, not the only way.