Thursday, July 23, 2009

Bucket List 1: Write Code Down at the Bare Metal.

I think every developer should experience the joy, frustration, and shear thrill of programming in assembly (machine) language. While maybe not a critical day-to-day skill for many software developers, Assembly Language programming still educates the software developer in many ways.


I first started programming 6502 Assembly back in 1985. I had an 8-bit Atari computer, and I was doing a lot of programming BASIC. The problem with this platform is that the computer only had a clock speed of 1.44 Mhz, and BASIC was interpreted. This wasn't exactly the speediest platform. :-)


I soon learned that the Atari platform had some very simple hooks to allow your BASIC program to jump to a user machine language program loaded into "page 6". Each "page" on the Atari computer had 256-bytes of memory. Page 0 started at memory location 0, Page 1 started at memory location 256. Page 6 started at memory address 1536.


I remember hand-translating the assembly opcodes to machine language, and then using BASIC's DATA statements to load them into memory, starting at location 1536. If my assembly language program when awry, the computer would lock up and I'd reboot. I was in heaven a year later when I found an Assembler written in BASIC that would do the translating for me. :-)


I used 6502 Assembler to quickly redefine character sets, wipe out memory, animate graphics, mix colors, break the 4-Player limit in Player-Missile-Graphics (there were some gnarly things you could do when the screen was redrawing itself mid-screen).


6502 Assembly was a great assembly language to learn. There were only three registers (A, X, and Y). The instruction set was small. I learned a lot about the computer - everything from interfacing with external devices to programming the graphics and sound chips.



My later experience was in college. I picked up 80x86 assembly language to do some hi-performance 3D graphics. The 80x86 had more sophisticated memory management and more registers to work with, but the experience was just as invaluable. I learned the art of really fast integer math (both fixed point math and all of the neat tricks with rotates/adds that could be done to speed up calculations). I counted clock cycles. I precalculated values to make math even faster. I unrolled loops to prevent the penalty of having to branch/jump.


I haven't done any assembler since college (well over 15 years now!). But I still look back at those times very fondly. They gave me a great appreciation for how computers really work, how memory is managed, and how devices really work. You get great insights into code optimization. Finally, there was always a huge pay check at the end of the day - A HUGE performance pay off in speed.


I remember learning C and remembering how simple it was. Everyone in myu college class was having a hard time understanding pointers and memory allocation. But after programming in assembly, it was really easy to understand the abstractions that C was providing the programmer and what the programmer needed to do in order to clean up after himself.


With today's multi-core, multi-language, multi-system architectures, it's easy to see how Assembly language programming is becoming a lost art. With C/C++ compilers that produce super optimized machine code and JVM's that perform run-time analysis before compiling to machine code, I cannot see myself ever dipping back into assembly language again. But the time spent their was a fascinating part of my experience as a software developer. And I still wish every developer gets a chance to talk to the machine using its own native language.

1 comment:

MarkRebuck said...

My history with assembler is identical to yours. I still remember weird crap like 0xA9 is "LDA immediate" and 0xEA is NOP.

When I started doing some PIC Microcontoller programming at the end of 2005, I had to dust off my assember skills. It was quite a shock, but there is a certain sense of satisfaction in knowing that every thing that happens... EVERYTHING... is because you explicitly declared it. No wonky garbage collecting. No unsupported device drivers. No weird pixelation issues. Nothing but exactly what you declared, bit by painstaking bit.

My inner controlfreak still loves programming on the metal.