Randall Hyde’s The Art of Assembly Language is one of the works often recommended to new x86 assembly language programmers. It comes in three flavours: two 32-bit versions, one for Windows, one for GNU/Linux and a 16-bit version for DOS. The 32-bit versions use a custom language that adds high-level constructs to assembly language, but the 16-bit version has to deal with DOS. The high-level assembly language in the 32-bit versions put me off, but I was quite happy to read the 16-bit version, being a fan of that crusty old “operating system”.
The exhaustive listing of the x86 instruction set (at least, up to the 486) isn’t until chapter 6 (mov is introduced in an earlier chapter and the string instructions are postponed until chapter 15). Large chunks of the book are dedicated to the old Microsoft Macro Assembler, MASM. While not very useful as written, mentally translating the examples to nasm is a useful exercise. The final chapters of the book briefly cover how to program various PC hardware: the keyboard, text display, game adapter and serial and parallel ports. There’s also a fairly thorough discussion on parameter passing, covering the implementation of several call-by-foo styles of passing arguments.
I would recommend it to anyone who wants to start learning DOS arcana (the BIOS and hardware progragramming chapters might be interesting to hobby-OS developers). The 32-bit versions’ “High-Level Assembler” puts me off, so I can’t recommend it as a general-purpose assembley language tutorial (for that, I think that one of the other titles recommended on StackOverflow would be more appropriate).