This week I read the third edition of “Assembly Language Step-by-Step: Programming With Linux” by Jeff Duntemann. It is my favorite book on the subject of x86 assembly language and simply one of the most enjoyable programming books I have ever read. For years I have happily owned and read through my copy of the second edition, and so I was excited to see what was new in this most recent edition.
Best Quote Ever
Let’s be honest with each other: few of us will ever need to write software in x86 assembly language. I have rarely required x86 assembly for matters of performance; high-level languages have been sufficient almost all of the time. I stress x86 assembly here as there have been more situations where I’ve found myself writing assembly language for other processors, particularly the MOS 6502 where assembly language programming is much easier (in my opinion) and there are fewer high-level languages available. But when it comes to x86 assembly my experience is restricted to rare performance demands and simply to learn.
The author discusses this second reason in the opening of the book, and it is one of my favorite quotes:
Note well: When somebody asks you, “Why would you want to do that?” what it really means is this: “You’ve asked me how to do something that is either impossible using tools that I favor or completely outside of my experience, but I don’t want to lose face by admitting it. So… how ‘bout those Blackhawks?”
The answer to the Infamous Question is always the same, and if the weasels ever ask it of your, snap back as quickly as possible, “Because I want to know how it works.”
This humorously sums up what I believe is the best reason to learn x86 assembly language these days: to better understand how those computers work. Knowledge of the lowest-levels of assembly language will make you a better programmer in any language. Believe me.
Two-Hundred Page Introduction
A lot of books on assembly language jump right into the instruction set. The author rejects this approach on the grounds that knowing the x86 instruction set in-and-out is pointless if you do not understand the fundamental behavior of the CPU, memory addressing, and all related low-level hardware behavior.
Thus Jeff Duntemann spends two-hundred pages, almost one-third of the entire book, explaining every important detail of the hardware that runs your x86 assembly programs. I appreciate this approach because it provides in-depth context for the assembly language, but it also teaches important hardware concepts that will benefit you no matter what you do. For example, I don’t care if you are writing web applications or PC games or a desktop spreadsheet application: you need to understand how x86 PCs use and access memory, because you cannot truly optimize memory usage if you do not know how it all works under the hood.
Some readers will be eager to start writing assembly language programs and thus will be put off by the two-hundred pages of information about the grand scheme of the hardware. But I believe the lengthy lessons of x86-based hardware is not only vital to becoming a proficient x86 assembly language programmer, it is valuable information for every computer programmer. Duntemann’s funny anecdotes and analogies do wonders to make the first six chapters as entertaining as they are educational.
NASM on Linux
The second edition of the book closes with lessons about writing x86 assembly on Linux. The majority of the book focused on MS-DOS. The most significant change of the third edition is how it uses Linux as the operating system for teaching its concepts, specifically using NASM as the assembler.
Note: If you want to play around with MS-DOS then I suggest you check out DOSBox. It is a fantastic emulator and is great not only for MS-DOS programming but also for running classic MS-DOS games like the Elder Scrolls: Daggerfall (freely available).
Linux is my operating system of choice and so I cannot help but enjoy the third edition’s preferential treatment towards it. But on top of that I believe it is easier to learn x86 assembly programming on Linux. Writing such programs requires less boilerplate than their modern Windows equivalents, and in my opinion there are simply better relevant tools and libraries available on Linux. The author mentions this at the start of chapter twelve:
There’s a lot of value in learning assembly language, most of it stemming from the requirement that you must know in detail how everything works, or you won’t get very far. This has always been true, from the very dawn of digital electronic computing, but from it follows a fair question: Do I really have to know all that?
The fair answer is no. It’s possible to write extremely effective programs without having an assembly-level grip on the machine and the operating system. […]
That includes Linux. There are some small portions of Linux written in assembly, but overall the bulk of the operating system is written in C. The Linux universe revolves around the C language, and if you expect to make significant use of assembly language under Linux, you had better be prepared to learn C and use it when necessary.
There is almost immediate payoff: being able to access libraries of procedures written in C. There are thousands of such libraries, and those associated with the Linux operating system are mostly free, and come with C source code.
Any Linux programmer will attest to the truth of these statements. C is ubiquitous on Linux. The author does a great job explaining how to use C libraries within assembly language programs, and that makes it possible to put what you learn to use by writing non-trivial assembly language software that makes use of those thousands of C libraries to take care of things like creating terminal-friendly user-interfaces.
The author provides a useful appendix of commonly used x86 instructions. But it is far from complete, and understandably so; years of development have caused the x86 instruction set to grow and grow and grow…. You will never learn and remember all of the instructions unless you are a savant. So here are some resources you will find useful once you complete the book and have experience writing x86 assembly language:
That final link is the most comprehensive, authoritative reference out there. The full manual of every x86 instruction comes close to 1,500 pages, more than twice the size of Assembly Language Step-by-Step. And that is why no one learns every instruction, so bookmark that for future reference.
“Programming From the Ground Up” is also a good (free) book to read if you want to learn more about assembly language programming on Linux.