Not all that long ago, every PC programmer was familiar with at least the rudiments of the internals of the 8086, the BIOS and assembly language programming. To do any kind of graphical work, you needed to change video modes, and Terminate-And-Stay-Resident programs powered by Interrupt 27H were a playground for utility programmers.
Two of the better books on assembly language programming have recently been updated and make it an excellent time to learn (or refresh your familiarity with) the low-level truth of computing. Both Jeff Duntemann’s “Assembly Language Step-by-Step” (Wiley) and Randall Hyde’s “The Art of Assembly Language” (No Starch Press) are thick books that cover the 8086 instruction set from AAA to XOR. More importantly, though, both are excellent tutorials that require very little prior knowledge of memory models, addressing or bit-twiddling.
The books are very different in style, and determining which one is better largely depends on whether you appreciate the breezy style of Duntemann or Hyde’s dryer approach. Duntemann’s tone has the “Hey, kids! Let’s build an oscilloscope!” confidence of a ham radio enthusiast, with lots of authorial presence. Hyde’s book has a far more bread-and-butter approach that allows more topics to be treated deeply. (He has a whole section on floating point arithmetic, for instance.)
Duntemann’s style is very easy to read but can invite contradiction. For instance: “Assembly language programming is about memory addressing.” One could also say that it’s about “register allocation” or “the universality of binary representation.” But if you trust Jeff (and you should), you’ll find him a very able guide.
Despite the dry tone, Hyde takes a radical approach to teaching assembly language, which is that he doesn’t actually teach it. His book is really about programming in “High-Level Assembly” (HLA), a programming language with a somewhat Pascal-like syntax, control structures and a standard library. The concept is that HLA is a scaffolding that allows one to quickly, for instance, get “Hello, World!” onto the screen but that, over time, one learns to do without HLA’s help. If you want to do crazy jumps that bypass normal control structures and calling conventions (which, after all, is half the fun of assembly language), you can do them, but if you like the explicitness of a while loop, you can use that, too.
In truth, HLA is probably one of the smarter ways to work with assembly language. Assembly language is most practical in specific subroutines. With HLA, one could mock out the data and calling structures and then concentrate on the specialized behavior. HLA is certainly easier to read and write than inline assembly in a C program. Regrettably, Hyde doesn’t really discuss integration with other languages, while Duntemann justifiably devotes an entire chapter to interfacing with C.
Both books start by introducing basic binary representation and memory layout before descending into the weeds. Duntemann does a better job describing the variety of memory modes available to descendants of the 8086, which is perhaps not surprising given his position on memory addressing. Both books also have extensive discussion of integer representations and strings.
Hyde’s book goes deeper into arithmetic and higher-level programming concerns such as functions and modules, while Duntemann’s provides clearer guidance on an example-by-example basis.