When my son was about 8 or 9 I introduced him to non-decimal base numbers — we were playing aliens with 2 or 3 or 8 or 16 total fingers. Now he is 12. We’ve been studying 8080 asm for about two weeks now, every evening. To my surprise, it’s going extremely well.
Why did I choose assembly language?
Both ”enterprise” languages (Java or C#) and “open” languages (Ruby, Javascript etc.) are overcomplicated. Most of modern languages are multiparadigm ones. This means, if you start with a “real” language, on his first day he’d bump into elements of OOP, functions, closures and God knows what else. Then there are libraries. Then there are IDEs. Believe me, you don’t want your kid to get overwhelmed on his first day.
Most modern languages — except pure functional ones like Haskell and the like — have their syntaxis highly influenced by C. Why not learn C then? IMHO, that’s a great idea. It does not have OOP, and is overall pretty simple. However, when learning C you will inevitably bump into things that are IMPOSSIBLE TO EXPLAIN without talking about RAM, stack, and registers. Unless of course you want to wave your arms and say that it’s all computer magic.
In light of the above, learning ASM as the first language makes a lot of sense. ASM is not hard at all. I would even say it’s simpler than any high-level programming language because of its narrow scope and small number of moving parts. You really only have a handful of registers, a few arithmetical commands
Now, what you DON’T want to teach your child is the memory conventions, segments, and the process of compiling and linking an asm source file. Leave that for until after he knows C. That’s why for our programming environment I chose SID — this is a ”debugger-monitor” running on a legacy OS called CP/M (running on an in-browser 8080 emulator: http://www.tramm.li/i8080). All you get is a blank screen, with few simple commands (L100 to see a disasemmbly of instructions at address 100, A100 to start entering new instructions line by line, G100 to run the program etc.). I can’t tell you how much it helps the focus to narrow the scope to a blank screen with one command line.
Here’s what we have covered so far:
- Hex / Binary / Decimal conversion and arithmetic.
- Basics of von-Neumann architecture: CPU, registers, RAM
- Basic assembly mnemonics (Intel-style) – MOV, ADD, SUB
- CP/M debugger-monitor (DDT/SID) workflow and basic commands: A, L, T, X
- i8080-specific mnemonics – MVI, ADI. Entering and running a simple program.
- The notion of loop. The FLAGS register. The Zero flag. New command JNZ. Implementing multiplication of two numbers via addition.
- More 8080 mnemonics – LXI, PCHL. Implementing a subprogram via jumps (don’t know what stack is yet)
- More debugger commands: S, H. More 8080 mnemonics: INR. Reading from RAM.
- Implementing a program that sums elements of an array given a pointer to its head and a number of elements.
- The notion of carryover. The Carry flag. Implementing a two-byte addition by counting the carryovers. Enhanced the Sum Of Array program accordingly.
- More 8080 mnemonics: INX. Array of structures. Writing to RAM. Using flowcharts to visualize complex programs.
- Implemented a program that takes an array of triples, then for each element multiples first two bytes and stores the result into the third byte.
- Comparing numbers with CMP. A program to find maximum value in array.
- A program to reverse an array in-place.
Next, I’m planning to introduce a concept of stack, and then, after a bunch of exercises we will move on to C. I’m excited.
As Joel Spolsky once said:
Trying to be a programmer without understanding how a CPU works is like trying to practice medicine without learning anatomy. Sure, you can have limited success curing patients with medical advice gleaned from Google, but on the whole you’re going to be a pretty bad doctor.
