The Enbugger
So how minimal is this tooling?
Some history
A long time ago in a school far, far away I came face to face with my very first computer. It was a Sinclair ZX81 and it was by far the most wondrous thing I’d ever seen. Yes, I am that old.
The ZX81 came with a BASIC interpreter chip on board, which is a good thing because the parent who donated it hadn’t included any programs. This is a problem if you don’t know how to program BASIC and, because it’s the dawn of time, there is no internet or even a teacher who can help.
Fortunately there were computing magazines around and they came with what Wikipedia chooses to call type-in programs. Essentially there would be pages and pages of the magazine filled with a program listing that you would sit and type in yourself. That’s how I got to play a Space Invaders clone and also, after a minute of playing, cheated at Space Invaders by giving myself 99 lives. If you want to see what I’m talking about then the Internet Archive has some of those early magazines like Sinclair Programming.
On the ZX81 those were BASIC programs. A couple of years later the same parent donated a ZX Spectrum which was a much more complex machine. The type-in programs also got more complicated and started using the magical POKE and PEEK commands. The code itself was a complete mystery, remember there was no internet to try and find answers. So I’d type in code and sometimes, if I typed it in right, after a few hours I’d wind up with a game to play at the other end. Games like these (I think I may have actually made that Moon Buggy one).
This is where things get relevant. POKE and PEEK were used to directly manipulate memory and they were being used to enter machine code programs. Other listings used a lot of DATA instructions to do the same thing. If there were assemblers for these computers then I certainly never saw one.
How low to go?
I think you can probably see my goal here. I want to start out by putting bytes directly into memory and see what I can achieve. It’s a deliberate handicap the sole purpose of which is my amusement. Otherwise I’d just use GRUB and C and have something running in a day or so. The target goal of an OS is a direction, but it’s the journey that is really important for this project.
Strictly speaking the absolute minimum instruction set would be the POKE command on its own. We don’t need to look at the contents of memory, because we code perfectly, and jumping to code can be done by modifying the existing code.
I’m not that much of a masochist.
Our minimal instruction set will be this:
- PEEK <address> — print to screen the hexadecimal value of the byte at the address.
- POKE <address> <value> — overwrite the byte at the address with the value.
- CALL <address> — perform a far call to the address.
I think the CALL instruction needs a little more explanation. The reason it’s a far call and not a jump is so that whatever code we execute can, if it doesn’t screw up the stack, do a far return and get back to our original routine.
Not a debugger
The dictionary has this to say about debuggers:
A computer program that assists in the detection and correction of errors in other computer programs.
— Oxford Dictionary
That’s not what we’ll be doing. There is no program to correct so there is no debugging taking place. This is why I’ve decided to call this the Enbugger instead. We’re taking a perfectly happy, albeit inactive system, and deliberately poking at its memory to add code. We are in fact going to be adding bugs, not taking them away.
Here’s one I made earlier
I actually started writing the Enbugger a few days ago and it has been a useful exercise. I haven’t programmed using assembly language for a long time and there are so many pitfalls it requires a different style of thinking. Popping things off the stack in the wrong order? Yeah, did that. Trashing the top of the stack and wondering why everything breaks on return? Yeah, did that and numerous other screw ups. Needless to say it has been fun.
What I came up with is a boot sector which loads a couple of disk sectors that contain the Enbugger program. Since it’s just a means to an end I’m not going to go into any detail on the code in the Enbugger but, for the curious, it was made using GAS and LD and I think before long I’m going to miss those tools.
In terms of hardware I’m using an emulated 64 bit x86 via the QEMU emulator which boots a floppy image. I don’t have anything lying around that can boot from a floppy, or any floppies for that matter, so it’s going to be a hell of a lot easier using QEMU for now. If I get to the point where I’ve got disk functionality then I may move to my little netbook, but that would mean working out how to boot from USB. I’ll have to resist the urge to use QEMU’s monitor tools.
So without further ado I present the Enbugger:

In case you’re curious 0xCB translates to the RETF instruction which, when accessed via the CALL command, returns straight back to the Enbugger.
Draw the rest of the dwarf
Should be easy going now right? I mean we’ve got a way to alter memory so we’re all good to go.
Unfortunately not!
I, like the vast majority of humans that have ever lived, have absolutely no understanding of how to translate assembly instructions into hexadecimal. Obviously that’s going to have to change and this is where things get kind of dull. Think of it as the section in a computer game where you have to grind to get the good gear you need to do really fun stuff.
Here’s what you need to read to learn how to talk to an x86 processor:
Intel® 64 and IA-32 Architectures Software Developer’s Manual
So it’s time to grab a coffee, put up my feet and do some studying…maybe more than one coffee.
— Curufir