Appendix B Errata of the first edition
This appendix lists the content errors of the first edition (the PDF
built in June 2020) that were corrected in the second edition, so that
readers of the old PDF can check their copy, and contributors can see
which reported issues were closed. Typo-only reports are not listed
individually. Numbers in parentheses are GitHub issue or pull-request
numbers in the tuhdo/os01 repository.
B.1 Preface and chapter 1
- The “What you will learn” list promised “bare metal x86_64”; everything in the book is 32-bit. The second edition says so and explains 64-bit mode in chapter 15.
- Chapter 1 claimed that the book’s website hosts copies of the Intel manuals and the System V ABI documents; it never did. The text now says where to search for them (#37).
- A citation of Kovitz was placed after the sentence’s full stop (#97).
B.2 Chapter 2
- The example machine code said that
10100000means “add” and000000101(nine bits) means “halt”. The second edition uses two real one-byte x86 opcodes,00000000(add) and11110100(hlt). - Example 2.5 said “domain-agnostic language” where the paragraph describes a domain-specific one.
- Figure 2.3.4, the four-chip OR gate layout, labeled pin 1B of the
first 74HC00 as
A2; it isA1like on the other three chips (#115, PR #158). - The three links to the 74HC00 datasheet were dead; they now point to the manufacturer’s current page (#113).
- A margin note recommending Ben Eater’s video on how semiconductors work had been lost from the text (#155).
- Grammar in several sentences (#183, #184, PR #185, PR #174, PR #159).
B.3 Chapter 3
- The photo captioned “Raspberry Pi B+ Rev 1.2” is a Raspberry Pi 2 Model B.
- “Field Gate Programmable Array” for FPGA.
- The Q35 chipset was described as “relatively modern”; the second edition dates it (2007) and explains what changed since.
- “mount” for “amount” (#129).
B.4 Chapter 4
- Example 4.5.7 used
jmp [eax*4 + eax + esi], which nasm rejects (invalid effective address): a scaled index needs a base and one index, so the example is nowjmp [eax*4 + esi](#108, #148). - Exercise 4.3.1 referred to a section number of the Intel manual that no longer exists; it now names the section by title (#177).
- Exercise 4.9.1 referred to the wrong manual; it is the Optimization Reference Manual (#112).
- The listing for
add(1,1)did not match the source code shown (#114, #139). - Figure 4.9.1, the
shl/salillustration: the row labeled “after 10-bit shift” showed an 11-bit shift (#156). - Figure 4.9.6, the stack frame: the return address was drawn below
the saved
ebp; it sits above it, at a higher address (#152). - In the conditional example, the registers holding
iandjwere swapped in the explanation (iis inedx,jineax) (#179). - The byte table of the
jmpencoding example had a spurious tenth byte. - The far-jump text described the in-memory order of an
m16:32pointer wrongly; it is the 32-bit offset first (34 12 00 00), then the 16-bit segment (78 56). - The SIB table’s third column was labeled
R/M; it isIndex. - “Produce Calls” for “Procedure Calls”;
ESP/SP/AHMM4andMM/XMM1garbled register names; a margin note oncat /proc/cpuinfowas clipped out of the page (#109); other wording issues (#110, #111, #121, #166). - The stack offsets in “Examine compiled code” were inconsistent (two variables at the same offset). gcc 14 allocates locals in declaration order, and the listings and prose now agree.
B.5 Chapter 5
- The ELF entry point was said to be
main; it is_start, which calls the C runtime that callsmain. - The ELF header’s
Flagsfield was described as the EFLAGS register; it is a processor-specific flags word, and no flags are defined for x86. - “Size of program headers” is 56 bytes in a 64-bit file, not 64.
- Exercises 5.3 and 5.4 had the
LinkandInfofields of.rel.textswapped. - Example 5.18 placed both arrays in
.preinit_arraywhile the text discusses.init_array; the source now uses.init_arrayforinit_arr. - A
readelf -x 25command dumped a section that was not.datain the listing shown. - “HIREVERSE” for “HIPROC”/“HIUSER” range names; a
hello2.cfile compiled ashello.
B.6 Chapter 6
- The “Single stepping” section did not explain the mechanism; it now describes the trap flag and the debug exception (#145).
- The
upcommand’s explanation said frame 1 was in functionbat line 3; the session shows it incat line 2. - The
untilexample’s line numbers did not match its own listing, andadd1000was called with arguments it does not take. - The breakpoint figure labeled the patched bytes as
sub esp,0x4; the instruction issub esp,0xc. - Examples were numbered out of order (6.9 before 6.8, 6.11 before 6.10, 6.25 before 6.24).
- The DWARF section and the DIE tree figure showed DWARF 4 output; the second edition shows DWARF 5, which current compilers emit by default.
B.7 Chapter 7
- A bootloader that prints a string would print nothing (#33): the
flat binary is assembled at offset 0 and never sets
DS, somov si, msgpoints into the interrupt vector table once the BIOS has loaded the code at 0x7C00. The second edition adds the section “Two traps when writing a bootloader” (org 0x7c00,DS/ES/SSsetup, and theleave-without-prologue trap reported in #154). - The first flat Makefile
(
bootdisk: bootloader.o kernel.o) never worked; its targets are directories. - The text said the bootloader reads 30 sectors; the code reads 2.
- The Makefile’s
DISK_IMGpath was wrong (#151),-T os.ldslacked a space (#163), the Make summary had$PATHfor$(PATH), the wrong result for+=, a wrong$$example,DISK_IMG=disk.img.o, “starts with.asm” for “ends with”, and the claim that Make starts with thealltarget rather than the first target (#176, #168, #167). - The sample
.gdbinitof chapter 7 contained two lines (symbol-file,b main) that belong to chapter 8 and made gdb abort the script.
B.8 Chapter 8
- The final linker script of the first edition is rejected by current
versions of
ld(PHDR segment not covered by LOAD segment). The section “A segment for the program header table” shows the error and the fix. - Example 8.10 showed an implausible
LOADlayout; it was replaced by a reproducibleAT()demonstration. - Figures
no_FILEHDRandwith_FILEHDRlabeled the loaded segment.text .eh_framewith sizes of the 2016 toolchain. - With gcc 14, uninitialized globals are no longer
COMMONsymbols unless-fcommonis given; the relocation example says so.
B.9 Code and tooling
- The committed sample code included build outputs and a stale
debug.elf; all build products are now generated. - Modern compilers default to position-independent executables; every listing in chapters 4 to 8 was regenerated with the flags of chapter 0, and the differences are explained where they matter (chapter 0, chapter 4 and chapter 5).
set architecture i8086in gdb no longer changes the disassembly when attached to QEMU’s gdb stub; chapters 7 and 9 explain how to read 16-bit code anyway.