I started learning assembly a few weeks ago. Assembly?? Yeah. Assembly.
But I always find myself drawn to assembly.
After reading Paul Graham’s Beating the Averages, I took up his unwritten challenge to learn and use Lisp. Lisp is a beautifully simple language, and its elegance affords the programmer ultimate flexibility, with a little work. Compared to Lisp, assembly is a constrained, weak language, confined to the few operations the machine understands. Put a bunch of bits here. Put some more bits over there. Check this bit, set that bit. Bits, bits, bits, bits. There are no lists, strings, or objects. Math is confined to the arbitrary size limits of the processor.
And yet a Lisp interpreter is ultimately expressed in terms of these primitives. Assembly is the base. Everything else is just an abstraction.
I didn’t set out to learn assembly for the usual reason of performance. What caused me to take the plunge and dive into assembly was language design.
For a personal project, I began writing a domain-specific embedded scripting language. Let’s call it Q. Under the hood, Q expressions are implemented as binary parse trees, like most other languages. The parser builds up these trees in memory, and the run-time walks the tree and executes actions for each op-code.
Q functions are expressed as self-contained parse trees that are evaluated for every function call. Named functions are just parse trees linked to one or more symbol tables. Scope is implemented by keeping a stack of symbol tables, one per scope.
What started out as a niche language with specific requirements morphed into a general purpose language. I blame Lisp for this. With a little bit of work and a couple dozen more parentheses here and there, Q could become a Lisp dialect.
Yawn. Boring. How many Lisp-y languages are out there? Ten? Twenty? More? Don’t get me wrong, Lisp is awesome. But like other high-level languages (I’m looking at you, Perl/Ruby/Python), it requires an interpreter. Someone wrote some kick-ass program in Erlang? Gotta install the interpreter and standard libraries. Python? Get the interpreter. Ruby? You guessed it, you need an interpreter.
I figure if I know assembly well enough, translating Q parse trees and symbol tables into machine code should be fairly trivial. Patterns tend to bubble up from the most foundational levels of computer science. Q’s design follows the Von Neumann architecture, which maps cleanly to real hardware architectures, and by extension, assembly.
Underlying all of this is my personal drive to learn. Learn anything. Learn everything. It’s why I got involved in computers in the first place. And although my logical reason for wanting to learn assembly are shaky at best (do we really need another Lisp? Probably not) the illogical reason is good enough for me.
Why do you pursue your passion?