Est. 1980 Advanced

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

Paradigm Assembly, Interactive command language
Typing Untyped — every value is a hexadecimal byte or word; there are no labels, symbols or variables
First Appeared 1980
Latest Version No further Microsoft releases after MS-DOS 6.22 (1994); NT-family 32-bit Windows carried the MS-DOS 5.0 binary. Free successor Debug/X 2.51 (June 2025)

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:

Command1980 meaning
DDump memory in hex and ASCII
EEnter bytes, either as a list or interactively
FFill a range with a byte list
GGo, with up to ten breakpoints
HHex arithmetic (sum and difference of two numbers)
I / OInput from and output to an I/O port
L / WLoad and write a named file, or raw disk sectors
MMove a block, handling overlaps correctly
NName the file for L and W
QQuit
RDisplay or change registers and flags
SSearch a range for bytes or a string
TTrace 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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
; DEBUG-86 8086 debugger runs under 86-DOS       version 2.30
;
; Modified 5/4/82 by AaronR to do all I/O direct to devices
; Runs on MS-DOS 1.28 and above
; REV 1.20
;       Tab expansion
;       New device interface (1.29 and above)
; REV 2.0
;       line by line assembler added by C. Peters
; REV 2.1
;       Uses EXEC system call

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 H command 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 ^ Error under the first bad character and executed none of the command. For E with 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:offset or as an offset in the default segment. Ranges can be start end or start 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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
assemble     A [address]
compare      C range address
dump         D [range]
enter        E address [list]
fill         F range list
go           G [=address] [addresses]
hex          H value1 value2
input        I port
load         L [address] [drive] [firstsector] [number]
move         M range address
name         N [pathname] [arglist]
output       O port byte
proceed      P [=address] [number]
quit         Q
register     R [register]
search       S range list
trace        T [=address] [value]
unassemble   U [range]
write        W [address] [drive] [firstsector] [number]
allocate expanded memory        XA [#pages]
deallocate expanded memory      XD [handle]
map expanded memory pages       XM [Lpage] [Ppage] [handle]
display expanded memory status  XS

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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
a 100
mov ah,9
mov dx,109
int 21
int 20
db 'Hello, World!$'

n hello.com
r cx
17
w
q

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:

FlagSetClear
OverflowOVNV
DirectionDN (down)UP
InterruptEIDI
SignNG (negative)PL (plus)
ZeroZRNZ
Auxiliary carryACNA
ParityPE (even)PO (odd)
CarryCYNC

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

ReleaseChange 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

1980
Tim Paterson finishes version 1.5 of the Seattle Computer Products 8086 Monitor, dated 24 April 1980 and marked "This software is not copyrighted." Its ROM command set (Dump, Enter, Fill, Go, Input, Move, Output, Register, Search, Trace, plus Boot) and its two-letter flag mnemonics are the direct ancestors of DEBUG
1980
The 86-DOS 0.3 User's Manual (copyright 1980; 86-DOS 0.3 is generally dated 15 November 1980) documents "DEBUG — The Resident Debugger" with the commands D, E, F, G, H, I, L, M, N, O, Q, R, S, T and W. There is no assembler and no disassembler yet
1981
DEBUG.COM ships as a standard external command in IBM PC DOS 1.0, released alongside the IBM PC announced on 12 August 1981. Paterson had by then added 8086 disassembly, exposed as the U (Unassemble) command
1982
A Microsoft source comment records that DEBUG was "Modified 5/4/82 by AaronR to do all I/O direct to devices", and the program now requires MS-DOS 1.28 or later
1983
DOS 2.0 adds the A (Assemble) command; the source credits the "line by line assembler" to C. Peters. DEBUG also starts loading programs through the new EXEC system call, so it can load .EXE files
1984
DOS 3.0 adds the P (Proceed) command, which runs a CALL, loop or INT to completion instead of single-stepping into it
1988
MS-DOS/PC DOS 4.00 adds the expanded-memory commands XA, XD, XM and XS (the source dates their implementation to June 1987 and carries a 1988 copyright), along with double-byte character set handling
1991
MS-DOS 5.0 adds a ? command that lists DEBUG's own commands, part of the DOS 5 change that gave every command on-screen help
2006
Andreas "Japheth" Grech takes over Paul Vojta's free DEBUG clone (copyright 1995-2003, MIT-style licence) with version 0.99 on 27 September 2006, and adds DebugX, a DPMI-aware version, in 1.00 on 25 November 2006
2014
The Computer History Museum publishes the source code of MS-DOS 1.25 and 2.0 on 25 March 2014. The 2.0 release includes DEBUG.ASM and its companion modules, and Microsoft republishes the code on GitHub under the MIT License in September 2018
2024
Microsoft publishes the source of MS-DOS 4.00 on 25 April 2024, including the later DEBUG with its EMS commands and a revision history in the file header
2025
Debug/X 2.51 is released on 17 June 2025, still keeping MS-DOS DEBUG's one-letter command syntax while supporting assembly and disassembly up to the Pentium Pro

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.

Language Influence

Influenced By

SCP 8086 Monitor Assembler (Intel 8086)

Influenced

FreeDOS DEBUG Debug/X

Running Today

Run examples using the official Docker image:

docker pull
Last updated: