Welcome to cpu.dusttoash.org

This website is a blog/resource for writing apps in machine code in a bare-metal (meaning there's no operating system, just your code) environment. Anyone can do it (pretty easily), and this site will show you how and will walk you through increasingly complex x86 machine code programs.

Though I try to keep everything fairly to the point and informative, this site is more like a blog that has code and explanations which you can follow along. I write them as I go and the site is not designed to be a structured, reference-like resource. A good reference is a lot easier to follow and interpret code from. (The plan is to make one of those later, when I have more information available myself.)

The main content on each page is short and to the point for getting code to run, but throughout each page are sectioned content (the colored boxes with a gray background; I call them "asides") that provide background, details, and more thorough information on each topic being covered. You can skip all of these asides if you want to get something running as fast as possible or want to learn by just tweaking code (guidebook mode), or you can peruse through them at your leisure and get all the history, side-details... everything (textbook mode). It's structured to let you choose.

Everything is split up into easy-to-follow pages, each covering a specific project or program. You can see a list of these below in the index down below.

Index

This is an index of all the available pages. If you're wondering where to start, here's the recommended path:

BackgroundToolchainPrint Test→ Other Simple Programs

After that, you should know all the basics and be able to write your own programs easily and jump around. The Toolchain page is not strictly necessary, but if you plan on writing machine code frequently, you might want to set up an efficient pipeline.

Reading Order (Hardware & Software Quirks)

If you're planning on writing your own code while using this site, you may want to read the pages in order. It's not necessary, but later pages assume you're aware of the stuff mentioned in previous pages. If you're interested in writing your own programs (instead of just reading for fun), you may want to at least look at some of the previous pages when something doesn't work, but you don't have to solve every issue before it even occurs, so read what you want to.

Different pages will have asides which contain auxiliary information of different kinds. For example, whenever a page mentions some kind of hardware-specific or software-specific behavior, you'll see something like this:

The asides will always be in a colorful box like this, so if you're debugging some weird issue on your system and jumping back to previous pages, it'll be easy to skim through to find and read only about the system quirks, or to skim out any of the additional details asides about how things work in more detail, etc.

What language do I use?

Because everything here is for the CPU (and I do stuff on my own i9-14900K), most of the code on this site is x86 machine code. That means each code snippet is a sequence of bytes. Most pages will also include assembly or hexadecimal code, but the primary format you'll see code in here is ASCII.

By ASCII, I mean this:

\b4Sho\b0H\cdDle\b0i\cdDle\eb\fe
Prints Hi using BIOS interrupts.

This corresponds to the following hex bytes:

b4 0a b0 48 cd 10 b0 69 cd 10 eb fe

The reason it looks like this is because that's how I write it. And the reason for that is that, when I started out, I realized quickly that writing a C/C++ program that contains the bytes of my x86 CPU machine code in an array (I tried a string too) which the C++ program then writes to a file, was not at all conducive to coding—if I wanted to modify my program, I'd have to modify my C++ array, recompile the C++ program, then run it, and if I wanted to read the program, I'd have to break apart the array (or string, which was better but still not ideal). This worked initially—for my very first CPU program: When I made the character A appear on the screen, I wrote the bytes needed to do that to a flash drive with C++—but if I was going to start writing x86 machine code frequently, then I'd need something better than using a C++ array as my editor/source file. I found out that I can type almost any unicode character on whatever Linux distro I'm on, using CTRL + SHIFT + U, and then typing the unicode character's hexadecimal value, then hitting enter. This works in the terminal and a lot of other text boxes, but works with everything except for the null character, Nul (0x00). I tried out different text editors looking for one that let me do this easily and comfortably but to no avail.

Eventually I figured out that my terminal, in raw mode, lets me enter the null character in a few different ways (namely, by pressing CTRL + SPACE or CTRL + 2 and I'm used to the former now), and also has some extremely intuitive ways to write lots of other ASCII control characters—holding CTRL while pressing many different keys just subtracts 96 from whatever byte would have been sent to the terminal otherwise; try pressing CTRL and typing i which has ASCII value 106 and is the 9th letter in the alphabet, instead of pressing TAB, which has the ASCII value 9. You should see the same effect you would have if you hit TAB!—so I ended up writing a (very simple) C++ text editor that runs in my terminal and lets me write any byte to a file. That's what I use, and it looks extremely similar to the code on this site (I tried to match the colors).

I wrote the pages here based off of the way I do things but you can follow along however you like and use the info/code however you want. If you want to match my pipeline, I go over it on the Toolchain page. If you don't, it doesn't matter at all. They're just bytes; write them however's best for you.


I do plan on adding something to this site to easily view the same code block in different formats (hexadecimal, ASCII, or even ASM), but for now, if you want to follow along, I usually use an ASCII table which you can see here.