-
Introduction
When I was a kid, I always loved toying with compilers, assemblers, and virtual machines. But it’s been years since I’ve had a chance. Since I’m stuck inside with the shelter-in-place order, I figured I’d dive in. Where to begin?
Read more » -
An instruction set
So far we have sketched an architecture for our CPU – it’s a 32-bit, register-based RISC machine. Now let’s design a set of instructions for our machine!
Read more » -
A simple interpreter
Now that we have our instruction set, we can execute a list of instructions. The basic process is one of fetching an instruction from the list, decoding it into an instruction name and destination and source registers, and then executing it. Do this in a loop and we’re up and running!
Read more » -
Encoding instructions
So, now we have some notation that defines our instruction set, and we understand how each instruction operates. Last time, in our simple interpreter, we stored our instructions as JS strings. But of course, a real CPU doesn’t have text-based representations of assembly code floating around in it! Instead, machine code is “just a bunch of binary” that the CPU decodes into instructions.
Read more » -
An assembler
Our virtual machine can now fetch, decode, and execute the instructions of a binary program. But how are we supposed to write such a program? Enter the assember – its job will be to convert programs written using the mnemonic instructions we’ve already discussed into binary programs.
Read more » -
Memory mapped peripherals
With an assembler in hand we can write reasonable programs for our virtual machine. Fun! But sadly, our programs are stuck inside of our machine, unable to do much in the way of output (and even less in the way of input). Let’s fix that!
Read more » -
Strings and things
We can finally get more than a single number out of our machine – we can print (short) strings, too. But getting strings into our machine is a pain. Let’s improve our assembler!
Read more » -
Input and asynchrony
With output taken care of, one naturally turns to input. But first, let’s take a closer look at our output peripheral, and our approach to peripherals generally, to understand how well it will support asynchronous behaviour like input.
Read more »