On the Virtues of Assembler
I left the private sector in a large part because I was sick of writing code, it is ironic, although in hindsight, not surprising, that I am still surrounded by it. This situation has turned me mildly retrospective, and I’ve been trying to figure out when it was I finally got, I mean really, natively, understood pointers.
I’m a firm believer that the ability to play with pointers is a talent, not a skill. I don’t think it can be taught. Sure, you can lecture on it, and I can get you to pass any multiple choice, fill in the blank, “knowledge of pointers” test, but I’ve found, and smarter people agree, that less than half of all people are able to juggle pointer abstraction in their head. I did most of my early programming in high level languages, and never really had to deal with pointers. I understood them, but it took a few seconds on every line of code to dissect it and make sure I was using them correctly.
I realized last week that I get it. Totally. And I blame Assembler.
If you were taught Assembler well, alongside a decent CPU structure course, Assembler is all about pointers. You just don’t call them that. You’ll learn about addressing, memory locations, address registers and the Program Counter, and you’ll figure it out, because you have to figure it out, you can’t abstract them away, and at the end of it, without realizing it, you’ll have mastered pointers. Even the literals you use are contained in an instruction in a memory location pointed to by the Program Counter. Everything in Assembler is a pointer.
A lot of my peers don’t understand why I tell them, if they’re only taking a few programming courses, to take the lowest-level languages possible. This is the reason. The closer you are to the silicon, the more real examples you’ll get about why you’re told to do things a certain way. Don’t understand what’s so bad about strings? Parse one in assembler. You’ll never forget it. Why can’t you assume a flat address space? Address more than 256 bytes with an 8-bit processor in assembler, and you’ll be intimately familiar with paging and banking. Very soon you’ll realize the elegance of arrays, that they’re not just native to your language (unless you’re unlucky enough that they’re objects instead), they’re native to your processor, and the inner loop of
while(*s++ = *t++);
is probably a single CPU instruction[1].
I love assembler. I get a rush when I can imagine exactly how the MCU is tossing bits around with every instruction. It’s weird, I know, but if you’re programming in any real capacity, you should love it to.
[1] On the 68k, it (should be) compiled to something like:
strcpy: MOVE.b (A1)+, (A2)+ ; 14D9 CMPI.b #0,(A1) ; 0C11 0000 BNE strcpy ; 66F8
June 7th, 2009 at 1:44 am
I completely agree with you: it wasn’t until I took CS200 (Assembly & Architecture) where I felt I could *actually* speak to a computer. It even made me a better high-level programmer! When you have to manage the stack manually, it’s so true that you’ll never forget it.
But even now that I really understand pointer arithmetic, I still really hate it and think it should be abstracted away
June 8th, 2009 at 8:05 am
I couldn’t agree more, pointers and assembler go hand in hand. Pointers are extremely valuable, especially if you are doing low level hardware or embedded code where you can’t handle the overhead of pushing data structures to the stack.