Learn Assembly Programming Fun Way

Here I am compiling a little list of resources about games, toy microprocessors and concepts that help you learn assembly programming.

Just to clarify, this is not intended as a way of learning real world Assembly programming such as how to program an Intel x86 or ARM microprocessor.

No, this is more about learning the basic concepts which applies to almost all assembly programming. It is also great way of learning the basic operations of a Microprocessor.

Isn’t Assembly Coding Outdated?

Yes. So why learn it?

Even if you programming a high-level programming language, the code you write has to be translated into assembly code (or more specifically machine code). If you have absolutely no idea of how the computer runs code, then you have not good conceptual idea of how your high level code will perform either.

It is also a question of the satisfaction of having a sense of how computers work a high level language all the way down to assembly code and down to the microprocessor executing machine code.

My interest in this really began with teaching my kids programming. I am teaching them some Julia programming, Scratch and MakeCode. However this is very math like and abstract. It doesn’t give my kids a good sense of how computers actually work.

Specifically I wanted to teach them what a microprocessor does. How it works with memory etc. Assembly code is really good for that. You don’t learn Assembly without learning about microprocessors.

So here is a list of things I explored and my experience with it.

The Little Man Computer

Turns out there is this strong simplification of a microprocessor that has been around for a long time called “The Little Man Computer”.

The reason for the funny name is that, instead of explaining a microprocessor in terms of electronic components connected with electric wires it instead imagines the microprocessor as a sort of box with a little guy inside.

This guy runs around and carries out instructions, the way a CPU would carry out the instructions of program in memory.

It is a simple enough concept that a whole bunch of simulators for this CPU has been made and people have made games around this idea. Let us look at the games first.

Human Resource Machine

This game is suitable for kids as they find it quite funny with the characters. However it is not an easy game. I have to sit with the kids and help them out.

Image for post

Basically the idea is that your main character is a hapless office drone which has to carry out menial office work to the letter.

You provide a set of instructions which look like assembly code for you guy to carry out the tasks he is given by your boss.

As you succeed you move up to higher floors in this giant office building and get more advance tasks, which really just means you get more trick problems to solve, which require more sophisticated programs.

TIS-100

Zachtronics make a whole bunch of puzzle like educational games. TIS-100 is one of their first programming games.

It is quite similar to the Little Man Computer concept with some twists:

  • You don’t have one CPU to program but multiple which communicate with each other.
  • You don’t have storage memory. You have a few CPU registers you have to use in smart fashion.

The whole TIS-100 concept is that you are in the future and TIS-100 is this massively parallel supercomputer thing. You got it from your uncle which passed away and you to fix it to figure out what it was meant to do.

Image for post

Fixing in this case means programming various CPUs inside the TIS-100 so they run their test program or diagnostic programs correctly. Basically you get a bunch of inputs and have to make sure your program produce a particular kind of output from this input.

From the screenshot you can see that each CPU (or node) is connected to a bunch of other nodes. You can write small assembly code programs inside them. The assembly code is very similar to Little Man Computer (LMC).

Here is an example:

MOV 8, ACC   # Put number 8 in accumulator
MOV LEFT # Add number from left node to ACC
MOV ACC, RIGHT # Move number in ACC to right node

It is pretty quick to learn the assembly code. There are not a lot of instructions. You only have to registers ACC and BAK.

You only got these categories of instructions:

  • Simple add and subtract. There is no multiple, divide or logical operations.
  • A bunch of different jump instructions. They don’t depend on any flags, only value of accumulator (ACC)
  • Move instruction moving data between nodes, from input, or to output.

Shenzhen I/O

Shenzhen I/Oexpands on the ideas developed in TIS-100 but makes it into something that looks a bit more like a game.

The back story here is that you are hired to make crappy little electronic devices in Shenzhen, China.

It cold be stuff like a fake surveillance camera, or a billboard which has to animate some lights.

Image for post

So unlike TIS-100 where you just take in numbers and produce some other numbers as output, here you feel a bit more like you are actually controlling some hardware in a useful manner.

Programming in this case is quite similar but with a few twists separating it from TIS-100:

  • Instead of uniform nodes with the same abilities. You have little micro controllers with different output sizes and memory for assembly code.
  • Unlike TIS-100 you explicitly connect these microcontrollers to each other.
  • Because we deal with real time systems, timing is now an issue. Hence the a sleep instruction slp is introduced.

Some of the behavior of the assembly code in Shenzhen I/O reminds of what is called conditional execution on the ARM microprocessors. Here is an example from the ARM manual:

ADD     r0, r1, r2    ; r0 = r1 + r2, don't update flags
ADDS r0, r1, r2 ; r0 = r1 + r2, and update flags
ADDSCS r0, r1, r2 ; If C flag set then r0 = r1 + r2,
; and update flags
CMP r0, r1 ; update flags based on r0-r1.

Basically you can a suffix to ARM instructions to make them conditionally execute. E.g. an ADD instruction will add two number every time. While an ADDEQ will only add if the previous two numbers tested where equal (EQ). If you want it executed if they are not equal (NE) you would write ADDNE.

Shenzhen I/O assembly code has a twist to this.

teq acc 0
+ teq p0 100
+ mov 1 x1
- mov 0 x1
mov p0 acc
slp 1

In the small program above you can notice there are (+) and (-) labels in front of some instructions. These are for conditional execution. teq acc 0 tests if the acc register is equal to 0.

The + teq p0 100 instruction is only carried out if the previous test was true.

The - mov 0 x1 on the other hand, is only carried out if the previous test was false.

If you are an old school assembly programmer like me who learned Motorola 68000 and Intel x86, this looks odd. But modern RISC processors which try to avoid stalling their pipelines can benefit from this.

Although even more modern RISC processor such as RISC-V does not have such instructions.

I just mention this because while interesting that it is included, I am not sure I want to teach my kids these kinds of concepts. I like to keep stuff simple with Jump instructions. Although the conditional execution does make a lot of code easier to write. But it forces you to learn yet another concept. Hence not a big fan.

Little Man Simulators

Because LMC is so simple, I implemented my own LMC simulator, assembler and disassembler in Julia. You can check it out here. It is just 200 lines of code.

To quickly try it out you can also you one of these two web based simulators:

Cardiac CPU

This was a simple CPU made to work using cardboard back in the 1960s. Since then they have made a simulator for it.

Image for post

This also as a very simply design as you can see, with very few registers. It only has 9 different instructions.

Read more about Cardiac here.

Notch’s DCPU-16 CPU

The creator of MineCraft came up with a simple CPU for a future game, that later got abandoned. It was a CPU designed for being able to easily play with. So it has a fairly small instruction set.

One of the interesting things is that his specification contained the idea of a memory area for graphics, which meant that using DCPU-16 emulators or simulators you could make simple bitmap graphics. The internet is full of various DCPU-16 emulators that different people have made. Here is one example of a DCPU-16 emulator on a webpage.

The full specification of DCPU-16 can be found here. To get some taste samples here are some of the opcodes supported on this CPU:

  • SET b, a sets b to a.
  • ADD b, a sets b to a + b
  • IFE b, a perform next instruction if b == a
  • IFG b, a perform next instruction if b > a

Final Thoughts

This is an interesting topic and the next article I want to write about this will be about how a simple computer/CPU is implemented in electronics.

I will try to base this article off simplecpudesign.com which implements a really minimum complexity CPU.

But I will use the opportunity to talk a bit more about how you actually put together the AND, OR and NAND gates to make stuff like adders, decoders etc that a CPU is made up of.

I want to get into more details on e.g. stuff like how does a CPU decode an instruction and toggle on different functions in the ALU (Arithmetic Logic Unit). Don’t worry if none of this jargon makes any sense to you now. That will be the point of the next article. To explain a lot of the CPU internals.

Written by

Geek dad, living in Oslo, Norway with passion for UX, Julia programming, science, teaching, reading and writing.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store