Lesson 6 of 8
The emulator
- 18 min
- 6 checks
- 3 hints
- Go to task
Goal
Run bytecode one step at a time
Explanation
A disassembler tells you what's in a program, and an emulator tells you what it does. Instead of reading the instructions, you execute them one by one on an accumulator in Python and collect whatever the program outputs. That's how researchers study programs written for processors they don't have: they run them step by step in an emulator and watch every value.
0x00 HALT break 0x01 LOAD imm acc = imm 0x02 ADD imm acc = (acc+imm) & 0xFF 0x03 XOR imm acc = acc ^ imm 0x04 SUB imm acc = (acc-imm) & 0xFF 0x05 OUT out.append(acc)
All the arithmetic happens in a single byte, that is, modulo 256. If the accumulator is 255 and you add 2, it becomes 1, not 257, and if it's 5 and you subtract 8, it becomes 253. The mask & 0xFF does this in Python: it keeps the lowest eight bits of any number, even a negative one.
Every emulator has the same structure: a program counter that points to the current instruction, and a loop that reads the instruction, executes it, then moves ahead by the instruction's length, one byte for an instruction without an operand and two bytes for one with an operand. HALT stops execution even if bytes remain after it.
Your task
Write the function run(program) that executes the program and returns the output of its OUT instructions as bytes. The program in the starter code prints a two-letter word, so run it with your emulator to find out what it is.
Checks
6 checks- Returns the output of the lesson's program
- Addition starts from zero and wraps modulo 256
- Subtraction wraps modulo 256
- XOR works
- A program that prints a word you haven't seen
- HALT stops execution