DEBUG
Tim Paterson's one-letter-command debugger for 86-DOS, MS-DOS and PC DOS — a hex dump, patcher, disassembler and, from DOS 2.0, a line-by-line 8086 assembler that shipped on nearly every DOS disk for more than a decade.
Created by Tim Paterson (Seattle Computer Products); later maintained by Microsoft and IBM
DEBUG is the line-oriented debugger that shipped with 86-DOS, PC DOS and MS-DOS, and for most of the 1980s it was probably the most widely installed piece of programming software on IBM-compatible PCs, simply because it came with the operating system. It is not a programming language in the usual sense. It has no variables, no labels, no control flow and no decimal numbers. But its prompt is a small command language of single-letter verbs followed by hexadecimal addresses, ranges and byte lists, and from DOS 2.0 onward it contains an 8086 assembler. People wrote programs in it: they typed instructions at the - prompt, saved them as .COM files, and passed around text files of DEBUG commands that rebuilt binaries on any DOS machine.
History and Origins
A ROM monitor for an S-100 card
DEBUG started on a circuit board. In 1979 Tim Paterson designed an 8086 CPU card for the S-100 bus at Seattle Computer Products (SCP). To bring it up he wrote a monitor program that lived in ROM. Version 1.5 of the SCP 8086 Monitor is dated 24 April 1980 in its listing, which credits “Tim Paterson” and states plainly: “This software is not copyrighted.”
The monitor manual describes a tool that any later DEBUG user would recognise at once. Commands were “the first letter of its name (upper case only) followed by any parameters”, and they covered Boot, Dump, Enter, Fill, Go, Input, Move, Output, Register, Search and Trace. A range could be written as two addresses or as an address, L and a length. Strings in byte lists went in single or double quotes. The register display already used the two-letter flag codes NV UP EI PL NZ NA PO NC that DEBUG would print for the rest of its life. The manual’s case for its Trace command, which used the 8086’s hardware single-step mode, was that “every instruction is traced correctly (unlike 8080 or Z80 debuggers).”
“The Resident Debugger”
Paterson began writing an operating system for the card in 1980: QDOS, later renamed 86-DOS. He turned the monitor into a program that ran under it. The 86-DOS User’s Manual, Version 0.3, marked “Preliminary” and copyright 1980 by Seattle Computer Products, has a chapter titled “DEBUG — The Resident Debugger.” Its introduction reuses the monitor manual almost word for word. The monitor’s Boot command is gone, and new commands for the disk and the program being debugged have taken its place:
| Command | 1980 meaning |
|---|---|
D | Dump memory in hex and ASCII |
E | Enter bytes, either as a list or interactively |
F | Fill a range with a byte list |
G | Go, with up to ten breakpoints |
H | Hex arithmetic (sum and difference of two numbers) |
I / O | Input from and output to an I/O port |
L / W | Load and write a named file, or raw disk sectors |
M | Move a block, handling overlaps correctly |
N | Name the file for L and W |
Q | Quit |
R | Display or change registers and flags |
S | Search a range for bytes or a string |
T | Trace one or more instructions |
The 1980 version could not read .HEX files (“these must have been already converted by HEX2BIN”), and it had neither an assembler nor a disassembler. Daniel B. Sedory’s history of DEBUG, which Paterson reviewed, says Paterson then “added the ability to disassemble 8086 machine code” while it was still a QDOS program.
Into PC DOS and MS-DOS
Microsoft licensed 86-DOS from SCP, hired Paterson in 1981, and adapted the system for IBM’s Personal Computer. When IBM PC DOS 1.0 shipped with the PC in August 1981, DEBUG.COM came with it. That is the 1981 date usually given for DEBUG. The program itself is about a year older.
Microsoft’s released source for DOS 2.0 starts with a short revision history:
| |
Those two DOS 2.0 changes made DEBUG what most people remember. The A command gave it an assembler, and the EXEC call let it load .EXE programs as well as .COM files. The size of the binary shows how big the change was. DEBUG.COM in Microsoft’s MS-DOS 1.25 release is 5,999 bytes, and the DOS 2.0 build is 11,764 bytes.
Design Philosophy
DEBUG was built to be resident and always available. It did not depend on a compiler, a symbol table or a source file. It assumes you have the machine in front of you and want to look at it. Several design choices follow from that:
- Hexadecimal only. Every number is hex. DEBUG has no decimal input, and the
Hcommand exists because you will often need to add or subtract two hex values by hand. - One letter per verb. Commands are a single letter (later a few two-letter forms such as
XA), followed by addresses, ranges and lists. The grammar is small enough to describe on one page. - Nothing happens on a bad line. Since the monitor, a syntax error printed
^ Errorunder the first bad character and executed none of the command. ForEwith a list, the 1980 manual promises that “NO locations are changed” if there is an error. - Segment:offset addressing, made easy. Addresses can be written as
segment:offsetor as an offset in the default segment. Ranges can bestart endorstart L length, a convention carried over unchanged from the 1980 ROM. - Scriptable by accident. DEBUG reads standard input, so you can redirect a file of commands into it. That was never a designed feature, but it turned DEBUG into a batch-file tool for building binaries.
Key Features
The command set as most users knew it
By MS-DOS 6.22 the ? command listed this command set, essentially unchanged since DOS 4.0:
| |
Writing a program in DEBUG
The A command assembles one instruction per line at the current address and stops at a blank line. There are no labels, so jumps and data references use literal offsets that the programmer works out by hand. A complete “Hello, World!” .COM program can be built from a script like this:
| |
The blank line ends assembly. N sets the file name, R CX sets the number of bytes to write (17 hex = 23 bytes: two for MOV AH,9, three for MOV DX,109, two each for the INT instructions, then 14 bytes of text ending in $), and W writes the file. Running debug < hello.txt produces HELLO.COM, which prints the string through DOS function 9. The address 109 is the first byte after the code, and you have to count to get it. That is the price of an assembler with no symbols.
Examining a running program
R shows the registers in the layout Paterson used in 1980, followed by the next instruction disassembled. T executes one instruction, and P (from DOS 3.0) runs a whole CALL, LOOP or INT as one step. G runs to a breakpoint. D and U let you look at the result as hex and ASCII or as 8086 mnemonics. The flag codes come straight from the 86-DOS manual’s table:
| Flag | Set | Clear |
|---|---|---|
| Overflow | OV | NV |
| Direction | DN (down) | UP |
| Interrupt | EI | DI |
| Sign | NG (negative) | PL (plus) |
| Zero | ZR | NZ |
| Auxiliary carry | AC | NA |
| Parity | PE (even) | PO (odd) |
| Carry | CY | NC |
Talking to hardware
I and O read and write I/O ports directly. L and W with a drive and sector number read and write raw disk sectors, bypassing the file system. G can jump to any address, including a routine in an expansion-card ROM. Together these made DEBUG a general hardware tool on PCs that had nothing else installed.
Evolution
| Release | Change to DEBUG |
|---|---|
| SCP 8086 Monitor 1.5 (April 1980) | ROM ancestor: D E F G I M O R S T, plus Boot |
| 86-DOS 0.3 (1980) | Runs as a DOS program; adds H, L, N, Q, W and file loading |
| PC DOS 1.0 (1981) | DEBUG.COM ships with the IBM PC; U disassembles 8086 code |
| DOS 2.0 (1983) | A (line-by-line assembler); .EXE loading through EXEC |
| DOS 3.0 (1984) | P (Proceed); T can step into interrupts |
| DOS 4.00 (1988) | XA, XD, XM, XS for EMS; DBCS support |
| MS-DOS 5.0 (1991) | ? help listing; DEBUG.EXE by this release at the latest (see below) |
Sources disagree on when the program changed from DEBUG.COM to DEBUG.EXE. Wikipedia says MS-DOS 3.2, while Sedory’s guide associates the change with DOS 5.0. The MS-DOS 4.00 source notes “Change to EXE file” under revision 2.3 without giving a DOS version. Sedory also notes that every version since DOS 3.0 carries the internal string “Vers 2.40”.
The date for P is a little untidy too. Sedory gives DOS 3.0, and the DEBUG.COM binary in Microsoft’s DOS 2.0 release (which identifies itself as “Vers 2.10”) still sends P to the error routine. But the DOS 2.0 source in the same release is a later revision (its header says 2.30), and it already wires P to a “ZTRACE” routine that steps over INT and CALL, enabled by a switch commented “true if P traces over interrupts”. The header credits this to “Ztrace mode by zibo” in revision 2.2. So the command existed in Microsoft’s tree before DOS 3.0 shipped it.
What Microsoft never added is just as telling. DEBUG’s assembler and disassembler stayed limited to the 8086/8088 instruction set (plus the 8087), and it only knows the 16-bit registers. Microsoft sold SYMDEB and later CodeView as its serious debuggers, and Borland had Turbo Debugger. DEBUG stayed the free tool that came in the box.
Windows
DEBUG stayed in Windows as long as Windows could run 16-bit DOS programs. Sedory reports that the DEBUG.EXE shipped with Windows NT, 2000 and XP is byte-for-byte the MS-DOS 5.0 program. Under the NT family it cannot read or write hard-disk sectors, and its port I/O commands do not reach the real hardware. Sixty-four-bit editions of Windows have no MS-DOS subsystem, so DEBUG is not available on them, along with the other 16-bit DOS commands.
Clones and successors
DR-DOS took a different route. According to Wikipedia, Novell DOS 7 and later DR-DOS versions shipped a DEBUG that reimplements Digital Research’s SID86 debugger. It accepts the MS-DOS command syntax and adds many extensions of its own.
The free line started with Paul Vojta, whose clone is copyright 1995-2003 under MIT-style terms and became the FreeDOS DEBUG. Andreas “Japheth” Grech continued it from version 0.99 in September 2006, adding 32-bit register display, FAT32 support for L and W, and the DPMI-capable DebugX. Under the name Debug/X it was still being released in the 2020s: 2.00 in December 2022, 2.50 in June 2024 and 2.51 on 17 June 2025. Its assembler and disassembler cover documented Intel instructions through the Pentium Pro, and it keeps the original one-letter command language.
Current Relevance
DEBUG is a historical tool, not a living one. Microsoft has not shipped a new version since the MS-DOS era, and modern 64-bit Windows does not include it at all. It still has users in three places:
- Retrocomputing and emulation. DEBUG runs wherever DOS runs, including emulators and FreeDOS installations, and it is still the fastest way to look at memory, patch a byte or read a boot sector on a vintage PC.
- Software archaeology. With the MS-DOS 1.25 and 2.0 sources released in 2014 (and on GitHub under the MIT License since 2018), plus the MS-DOS 4.00 sources released on 25 April 2024, DEBUG’s own assembly source can now be read in full.
- Debug/X, which is still maintained and keeps the command language in use on FreeDOS and other DOS systems.
Why It Matters
DEBUG was the place where a generation of PC users first saw machine code. Because it was free, on every DOS disk, and needed nothing else, it was the first assembler and debugger many programmers ever used. Its - prompt, the segment:offset hex dump with a dash in the middle of each line, and the NV UP EI PL NZ NA PO NC flag line are among the most recognisable bits of 1980s PC computing.
Its command language also shows how much a few one-letter verbs can do. The SCP 8086 Monitor of April 1980 already had the dump, enter, fill, go, move, search and trace commands, the L-length range syntax and the two-letter flags. Every later version, from 86-DOS through MS-DOS 6.22 to Debug/X in 2025, added to that grammar without replacing any of it. A tool written to check one S-100 CPU card ended up being used for more than forty years.
Timeline
Notable Uses & Legacy
Standard utility in 86-DOS, PC DOS and MS-DOS (1980-1994)
DEBUG was on the system disk of 86-DOS and then of every PC DOS and MS-DOS release, so for many PC owners it was the only debugger, hex editor and assembler they had without buying anything. Microsoft also carried it into the MS-DOS subsystem of 32-bit Windows.
Low-level formatting of hard disks through controller ROMs
Microsoft Knowledge Base article Q60089 tells users to start DEBUG and type G=C800:5 (or CA00:5, CC00:5, CE00:5) to jump into the low-level format routine stored in the ROM of Western Digital 8-bit hard disk controllers. DEBUG's Go command was the usual way to reach these ROM utilities, which otherwise had no way to be started.
DEBUG scripts for building and patching binaries
Because DEBUG reads commands from standard input (DEBUG < file), a plain text file of A, E, N, R CX and W commands can rebuild a small binary on any DOS machine. Batch programmers used this to create tiny .COM utilities and to read or repair disk sectors from scripts.
Teaching 8086 assembly language
DEBUG let students assemble, run and single-step instructions with nothing installed beyond DOS. Kip Irvine's widely used textbook Assembly Language for Intel-Based Computers had a companion "Using Debug" tutorial for exactly this purpose.