My computer has ROM, RAM, I/O options (serial port, LCD screen and 6522 VIA) and some primitive address decoding. Now feels like a good time to write a simple test OS for it. If I can type things in and get things out, then it’ll feel like a computer – albeit a rather simple one.
Early 8-bit computers often came with a minimal program on them called a “monitor”. This might be considered a very minimal OS – with simple keyboard input (sometimes: just a hexidecimal keypad) the user could read bytes from memory, write bytes to memory, and start execution from a given address.
This was just enough for a computer to be considered “programmable” – you could write the machine code directly into RAM, execute it, and then hopefully see the results. There was no concept of an assembler (let alone BASIC) so writing programs consisted of a lot of flicking through CPU reference manuals and composing your programs by hand … but it was a start.
This is quite an interesting read (if you’re into that kind of thing – which, if you’re reading this blog probably means you are) all about Steve Wozniak’s monitor (known as WOZMON) for the Apple 1 computer. He managed to fit a monitor into just 254 bytes of ROM!
So I reckon that implementing one for my computer (which I’ve already decided I’m naming ODDMON – geddit?) is a good next step.
Text will be entered into the monitor via the serial port, and any output will go back the same way. This means that I need a PC to use my computer – but that’s fine for now. It means that I can start to write test programs and transfer them easily with a comms package.
The monitor needsto allow the user to do three things:
- write bytes to RAM
- read bytes from RAM
- start execution from a certain point in RAM.
The command syntax for my monitor will be pretty simple:
R <hex address> - reads a byte from RAM
W <hex address> <hex byte> [hex byte] [hex byte] [etc] - writes bytes to RAM
X <hex address> - start executing at this point in RAM.
There’s not much to talk about actual implementation – so I’ll give you the summary: it seems to work. Instead, I’ll talk about the simulator I discovered.
I’m still learning 6502, so my development process is very much trial and error. “Debugging” is rather limited when you’re not using a proper OS with a proper development kit. If I was trying to discover why my code wasn’t working, I’d either be single-stepping my computer with an address monitor (which gets tiresome really quickly) or selectively disabling code until things start working again, and then selectively re-enable chunks until it breaks.
As you can imagine: if every iteration of that process requires moving an EEPROM between computer and a PC and rewriting it before moving it back again, that gets laborious. It’s not a good long-term strategy.
One alternative to this is to write an emulator; but that’s a lot of work, and the specification of this computer is in perpetually changing.
Instead, I’ve found this: Michal Kowalski’s 6502 simulator. This is an app that emulates a 6502 processor and a very minimal amount of peripherals around it (keyboard input, and text output). You can single-step through instructions, see the CPU registers change, watch loops iterate, see memory being populated, and so on.
This removes a massive amount of my lazy guesswork; allowing me to see (and learn) exactly what each instruction does.
It’s a little clunky, but when you understand some of its faults it is still a huge time saver. Obviously the keyboard input and text output mapping of the simulator doesn’t match my computer, but that’s fine: I just write little routines for input and output, and make sure all my code uses them. Then I only have two small routines to swap out depending on whether I’m running my code in the simulator, or on my computer.
Here’s the simulator in use:
And if you’d like to have a look at the first draft of my monitor, the source file can be downloaded here (11K, but it’s mostly comments).