Machine Code is for Kids!
Dylan Cuthbert on why machine code is perfect for kids to learn programming
GamesIndustry.biz is proud to present the best writing from #AltDevBlogADay, a blog populated by game developers who write about the creation and business of games and related subjects.
Here, Dylan Cuthbert of Q Games discusses the best language to learn programming, his history with BASIC and why he thinks old machine code is a perfect fit for children.
There was some talk on twitter a few weeks back about "I want to teach my 10 year old to programme, what should I start him on?", and a number of people responded with common student-like answers such as "flash script", "java", "lua", "C", no! "C++", no! "C goddammit", etc etc, and I started to have a think about this problem in some detail.
First some history, I learnt to program in BASIC starting from the age of about 10 (1982), by copying in listings from magazines at a friend's house on a ZX Spectrum he had got from an uncle who worked in the Sinclair factory, no less. My friend and I would take turns copying in the text, with one of us reading it out while the other typed, and this is how I learnt to type relatively quickly. What is amusing is that because we were so young we didn't know the proper names for the various symbols in the code, for years afterwards I would still call quotations marks "those things" as a result. But anyway I digress, in many ways the old BASICs with line numbers and older forms of machine code were perfect languages for learning in and this is article is my attempt to explain why.
Abstract Thought is an Adult Skill
It's my view that for a child to be able to learn quickly to code he/she needs a language with the minimum amount of abstraction possible. Have a think about that for a bit. Abstract thought is a skill that gradually grows as you get older, but when you are a kid your brain is wired to take everything at face value; it's a survival instinct that helps you place complete trust in your parents and other adults and as you get older the opposite becomes a survival instinct and abstract thought develops (e.g. the concept that Father Christmas perhaps isn't really visiting you via the chimney every year). Anyone who has or deals with children knows that what you tell them is believed pretty much absolutely.
The old-school BASICS were imperative languages and fairly crap, but one important feature they had was a very low level of abstraction.
As an example, this means that even the relatively simple C concept of '**' meaning "pointer to a pointer" is hard to visualise for young children. They might eventually get to the meaning of it in their own terms but the more abstract concepts there are, the harder they will find it to move forwards, and if guided correctly to avoid these abstraction pitfalls children can move forward at a faster rate and learn much more. I really think the trick is to steer clear of the extraneous abstraction we, as adults, cope with so easily and take for granted.
The old-school BASICS with line numbers were imperative languages and fairly crap when compared to any other language, but one important feature they had was a very low level of abstraction. Any school kid can type 10 PRINT "HELLO MUM!" and then 20 GOTO 10 and understand exactly what it does even my mum can understand! the equivalent in (almost) any other language requires many, many abstract concepts.
To illustrate this, here is what it looks like in C, one of the "simplest" languages:
What's so hard about that you probably ask yourself? That should be a total doddle for a kid to learn! But let's take it step by step (actually, let's just take the first line!) and you'll understand why a child would have trouble, the questions would probably go something like this:
- 1. What's that funny # mark?
- 2. What is "include"
- 3. What is "stdio.h" and what are the funny arrow symbols for?
Just to begin with, those three questions require days of teaching and I leave the rest as an exercise for the reader (and it is an interesting exercise to sometimes remove the blindfolds caused by familiarity) but the list is long. Of course the standard adult answer to these "where do babies come from?" kinds of questions from children is something to divert the question or leave the explanation for a later date. But this is exactly what you don't want if you are trying to teach children. You don't want the child using concepts because they have been told to use them "because that's the way it is", you want them to use the concepts because they understand them.
"Let us praise machine code O'Lord, ooh you are so big, so absolutely huge. Gosh we're all really impressed down here, I can tell you. Forgive us O'machine code for this our dreadful toadying and barefaced flattery, but you are so strong and, well, just so... super." Monty Python on machine code.
...is generally the opinion of people who haven't touched or worked with machine code to any extent. Machine code is seen as an untouchable omnipresent super-being that is better to simply be in awe of than to have to deal with it. For those of us who have made entire games on CPUs with only three registers, typing with our nose and both hands tied behind our backs (on a good day), well... it's as easy as pie (preferably a chocolate one as you will see later).
I'm not saying it is the quickest vehicle to take you where you want to go, but conceptually it is non-abstract pure logic and flow, and surprisingly easy to understand. It also gives you the ultimate flexibility and the age-old adage "computers only do what you tell them to do" actually becomes slightly believable. (Note: If you are a programmer, you owe it to yourself to make machine code your bitch, you are actually the omnipotent super-being and machine code honours you with its humble service!)
So back to BASICs (sorry!), BASIC is pretty much just assembler/machine code that has been extruded slightly, given a couple of boosts for ease of use (primarily auto-allocated variables, string manipulation and math notation), and expanded lexically into something more readable. The line numbers are equivalent to memory locations for example and the flow of the program can be directly visualised by simply stepping through the instructions.
Another key important feature of BASIC is that it is bloody slow (and if it isn't you should force it to be by giving your kid an old ZX Spectrum to learn on). This inherent crap slowness is great for kids because it encourages them to explore faster alternatives, and the alternative that is most equivalent to BASIC is actually machine code. Sounds weird doesn't it? I mean, isn't machine code meant to be for hardcore programmers and their ilk and impossible to learn by anyone other than hackers from northern Europe? Well no! For a child machine code is actually the next easiest thing to learn, as thousands of whizz-kids found out in the 1980s.
If you are a programmer, you owe it to yourself to make machine code your bitch.
Poking Digits Into Memory
The system is simple, you have a limited set of instructions, a limited set of registers, and memory (I remember in old machine code books this used to be illustrated by an open hand with a register per finger, that you would then POKE into memory... I can't remember how the memory was portrayed, maybe it was a giant chocolate cake... mmm poking fingers into chocolate cake, well that already sounds FUN!).
Complexity For The Sake Of Complexity
After having this article proofread by a certain machine code madman who goes by the name of Jaymin Kessler, he initially said, "but will kids really understand register spilling, stack frames, register allocation?". He instantly brought in a ton of abstract terminology that was invented primarily for compilers of higher level abstract languages. These are all pre-conceived notions that aren't needed to learn assembler at all there's no need to even just have one stack in assembler, why not have three? (wait.. C doesn't let you do that so how? oh!) And you might not even use a stack frame at all, it's up to you; there is nothing abstract and pre-decided in machine code apart from the absolutes: memory, registers and instructions. What you do and where you take it from there is for the child's imagination. For example, quite often the stack related instructions in old 8-bit CPUs were used for fast clearing or setting memory, this flexibility is very pure yet easy to understand because it isn't at all abstract.
Twelve Small Steps To Learn Machine Code
To round things up here's a simple list of concepts that a child should find fairly easy to learn (I did):
- 1. Binary show them how binary values can be visualized by using a monochrome bitmap screen and writing values into it. Show how 8 values can form an 8x8 grid and be "seen" as the letter "A". Ask them to calculate the 8 values to display the first letter in their name.
- 2. Hexadecimal 8 bit is fine to begin with and then show them fun things such as calculating the decimal value of B00B.
- 3. Registers visualise them as your fingers, limited in number.
- 4. Memory a neatly sliced cake or the keys on a piano are good visual aids.
- 5. Instructions for simple math combined with loading and storing. LOAD/STORE/ADD equivalents.
- 6. Looping and the concept of counters.
- 7. Binary math show them how "shifting right" divides by two and make sure they understand why. Explain XOR/AND/OR and how they can used visually for inversing, blending and masking.
- 8. Explain calling and the concept of return (GOSUB/RETURN should be a concept they are already familiar with from BASIC), and teach them register preservation (a slightly abstract concept but one that is quickly learnt).
- 9. Teach how a single stack works (perhaps combined with 8.) and the concept of push/pop LIFO for temporary storage (in the old-school 8-bit sense).
- 10. Concepts of data structure (relative access methods) and arrays of repeated structure.
- 11. Above all show them how much faster it all runs compared to BASIC, this is the hook!
- 12. Then simply expand and combine all of the above.
After writing this and extolling the virtues of BASIC and machine code there is an important saddening point I really have to add and that is that we now live in a day and age where machine code has been so far hidden from us it is actually difficult to find a good platform to give a 10 year old to start on. BASIC doesn't exist anymore either, not as far as I'm aware anyway, so my question to the readership is, given the pre-requisite of "little to no abstraction", do you know of a good replacement for the old BASIC -> Assembler path of learning for pre-teens that produced so many amazing programmers during the 80s and very early 90s?
Please Do Note However: Throughout this article when I am talking about machine code, I am talking about real chips, such as Z80, 6502, 68000, MIPS, ARM, etc, and not about the bastard-child we call x86 architecture or any of its variants. Don't let your children anywhere near that pile of stinking bat poo.