A Guide to DEBUG
( The Microsoft® DEBUG.EXE Program
)
Copyright©2004,2007,2009 by Daniel B.
Sedory
This page
may be freely copied for PERSONAL use ONLY !
( It may NOT be used for ANY other purpose unless you have
first contacted and received permission
from the author ! )
In
1980, Tim Paterson began working on a 16-bit OS for the 8086 S-100 Bus card
he had designed for SCP (Seattle Computer Products) the
previous year. To help in getting QDOS
(later called 86-DOS) to work correctly, Tim created a debugger in a ROM chip;
the code for that ROM version was released into the Public Domain. Later, Tim
adapted the code to run as a .COM program under QDOS, and also added the ability
to disassemble 8086 machine code. In the meantime, Microsoft® had
been busy purchasing the rights to sell Tim's QDOS to IBM®
for their 'secret' PC project. Tim was then hired by Microsoft
as the primary author of their first OS. When he completed his work on IBM's
Personal Computer DOS 1.00 in 1981, his DEBUG.COM utility
was included with it. All the functionality that Tim put into DEBUG is still
there and little has been added to it (the major exception being the Assemble
command; added under DOS 2.0).
[ Thanks go to Tim Paterson himself for reviewing
this perspective on DEBUG's beginnings. ]
With the release of DOS 2.0, DEBUG gained the ability to assemble instructions directly into machine code (the A command). This is one of the most important commands for many of its users. Though lacking much of the functionality of a stand-alone Assembler, e.g., all Jumps must be to hexadecimal addresses (no labels can be used), many useful .COM programs have been assembled with this command. Under DOS 3.0, the P (Proceed) command was added, so DEBUG could quickly execute subroutines; at the same time, it became possible to attempt stepping through Interrupts with the T (Trace) command. When DOS made EMS (Expanded Memory) functions available under DOS 4.0, the four commands xa, xd, xm and xs were also added to DEBUG. It appears they were rarely, if ever used though, even by programmers. For most of us, the only noticeable change in DEBUG was the addition of the help command (type a '?' while inside DEBUG) under DOS 5.0; when all DOS commands finally got the /? command-line switch.
DEBUG's code went through a number of changes (and 'bug fixes' too) over the years! Some of these internal changes were related to DOS system calls and screen output, then there was the change in file type from a .COM to an .EXE program under DOS 5.0. But in spite of all those changes and others which followed, DEBUG has never had an official revision since 2.40 (those digits have been embedded inside all versions of DEBUG since DOS 3.0). We can only guess about the real reasons that Microsoft® never updated DEBUG to handle instructions beyond those of the Intel® 8086/8087/8088 processors. Microsoft® did create their own Assembler (MASM), 'C' compiler and Debugger (CodeView ); which you could use too, if you were willing to pay extra, so that could have been one of their reasons. Rather than using MASM and CodeView, many opted for the less expensive Borland® assembler (TASM) and Turbo Debugger when they appeared, or some other commercial product. However, users and students alike can still learn a great deal about Assembly language by using DEBUG.
The internal structure of these Windows® versions of DEBUG appear much different than any previous DOS forms; at least at first glance. Though it seems a great deal has changed, you'll still find the phrase "Vers 2.40" but in a different location. Windows® itself went through a lot of changes during this period, such as being able to handle a new file system, FAT32, and larger drives. But without access to its source code, we can't be sure if there were any major differences in DEBUG. The changes might be due to something as simple as just reorganizing the error messages in the source code and/or using a new Assembler/Linker.
DEBUG had always been an effective tool in the hands of any Batch programmer, but some time after the introduction of Windows 95 and especially with Windows 98, that effectiveness was diminished when its I/O commands became unreliable! Whether due to a 'bug' in DEBUG itself or in Windows®, the fact is that I/O commands under Windows 9x/Me cannot be relied upon for direct access to a hard drive! If you run our ATA drive ID script under Win9x/Me, the data you get back is as interesting as it is disturbing: It appears that every other byte is still correct! So, one has to wonder what the cause of this problem might be.
The DEBUG program included
with Windows® NT/2000/XP/2003 appears to operate the
same as it did under DOS 5.0, but with two major exceptions:
1)
DEBUG is no longer allowed to load from or write
to any logical HDD sectors; only named files can still
be read from or written to under an NT-type OS. It can, however, still access
diskette sectors in the A:\ or B:\ drives
with the L and W commands, but only if those diskettes
contain a file system the OS can recognize! (See the L command in the
Tutorial section for more information.)
[ Note: DEBUG has never been able to directly access areas of an HDD outside of its drive volumes; such as an Extended partition table or even the MBR sector! However, DEBUG can be used to access such data by programming it to run INT13 commands or using a script file under DOS (e.g., our old CopyMBR script). ]
2) The I and O commands are essentially useless, since the program's interface with the rest of the system is only being emulated under these versions of Windows® rather than having any direct access to the hardware. This was already true to varying degrees under previous versions of Windows®.
This may surprise you: We
purposely mentioned the DOS 5.0 version of DEBUG here, since the DEBUG.EXE
file included with Windows® XP (and every other version
of the NT OS series) is exactly the same program file created
for MS-DOS 5.0 (md5sum = c17afa0aad78c621f818dd6729572c48).
DEBUG was only one of a small handful of DOS 5.0 programs that didn't
require any changes to run under an NT operating system. It's almost
ironic that another of those few programs is EDLIN, a line editor disliked by
most DOS users. Though EDLIN was also created by Tim Paterson, he did so in
just two weeks and was shocked when he heard IBM had actually included
it in their PC-DOS 1.00 release! No doubt he wished it had been replaced by
something better way back in 1981. It wasn't until the release of DOS 5.0,
that EDLIN was effectively replaced by Microsoft's EDIT.COM
program (v 1.0, 1991;
QBASIC must be present, or it's useless); EDLIN was, however, still retained,
to be 'backwards compatible' with various 3rd-party Batch files. Though NOTEPAD
or more advanced editors are available under Windows, you can still use
the 1995 standalone version of EDIT (v
2.0.026) at Command Line prompts in Windows XP; its menus will
even respond to mouse clicks.
Though created at the beginning of the 16-bit processor era (before the 80286 existed), more recent versions of DEBUG (such as those found inside a Windows Me or 98SE Emergency Boot Diskette's EBD.CAB file) are still useful to PC techs for direct access to certain memory locations on present-day systems (an Intel® Pentium IV, for example). DEBUG can also be quite useful for educational purposes. And even for debugging the Assembly code that is required during the boot process: The software that checks the Partition Table on hard disks and loads OS Boot Sectors into Memory. Unfortunately, many Boot Managers and recent MBR sectors now use instructions requiring a 386 (or even 486) class CPU to function, making it difficult to use DEBUG for such a purpose. Because of the backward compatibility of most Intel® processors, and the fact that it was included with Microsoft® Windows XP and 2003, DEBUG has had a much longer life span than ever expected. Though the ITANIUM CPU was not x86-compatible, the AMD64 was. In 2005, Intel® made the so-called "x64-based" CPUs that were once again x86-compatible. So, DEBUG still continues to find some use on 64-bit computers, even my new Intel® Core 2 Quad (4 processors in one) machine.
DEBUG was originally designed to work with .COM programs having a maximum size of only 65,280 bytes [ (64 x 1024) - 256 ] or less; how much less, depended upon the maximum number of bytes the program had to place on the Stack at the same time. The subtraction of 256 bytes is necessary since DEBUG often uses the area from offset 00 through FF hex for some internal data such as the name of the file that was loaded. Remember, true .COM programs by definition are supposed to fit inside a single Segment of memory (only 64 KiB).
Even when running MS-DEBUG under the latest Windows® OS, since it's still an old 16-bit DOS application, you can only open files whose names have been saved in the 8.3 DOS convention; i.e., up to 11 characters total, using no more than 8 DOS characters for the name and 3 for the extension.
As early as DOS 1.10, DEBUG was able to load files larger than 64 KiB. Basically, how large a file that DEBUG can safely use without error depends on the amount of available memory and the way the OS handles memory management. We'll say more about this below.
|
Remember: The Segment assigned to DEBUG, depends on the amount of memory in use, not the total memory available. So, the same DOS machine, whether it has 16 or even 4096 MiB of memory, will generally load DEBUG into the same Segment; unless a "terminate and stay resident" program is using that memory, or memory was not properly deallocated prior to running DEBUG.
Any version of DEBUG from DOS 2.0 or higher, makes use of the operating system's EXEC function which means that it's possible for you to perform a limited amount of debugging on an .EXE program. However, DEBUG can never be used to save either an .EXE or a .HEX file to disk, since both of these file types contain extra data that DEBUG has no idea how to create nor modify! It's quite possible though, to simply change the extension of an .EXE file to something else, such as .BIN, so DEBUG can be used to edit such a file and then change it back to an .EXE extension afterwards. Though it would be much better to use a Hex editor than DEBUG, don't forget that DEBUG can be used with Batch files and scripts to carry out such changes automatically; a sort of poor man's Patch program.
One of the simplest .EXE programs you can run under DEBUG is the so-called DOS "Stub" found inside many Windows® executables. You can follow along as we examine one of these here!
There will always be some code and data placed within the first 256 bytes of the Segment for DEBUG's own use. And although DEBUG often functions as expected if you zero-out this area, there may be some cases where you wouldn't want to alter its contents. The code bytes are simple and always found in the same locations: The first two bytes of this area ("CD 20") are machine code for the DOS interrupt: INT 20. The bytes at offsets 50h and 51h ("CD 21") form an INT 21, and the byte "CB" at offset 52h is a RETF instruction.
|
When running DEBUG in a Windows® DOS-box (under CMD.exe), dumping its first 256 bytes will almost always show the same fragmented string. The characters are the remains of the Ntvdm program (which starts as soon as any 16-bit command is run) quickly reading one line at a time from the file, C:\WINDOWS\system32\AUTOEXEC.NT, into the same area of memory where command line parameters are stored. The longest line in that file, including its trailing 0Dh (carriage return) byte, is successively overwritten by shorter lines in the file until the process results in what's copied to offsets 82h through CEh of DEBUG's Segment:
|
Note: If you rename or delete AUTOEXEC.NT, you will not be allowed to run DEBUG (nor any of the other 16-bit programs that normally run in Ntvdm). You can, however, save a copy, then edit AUTOEXEC.NT to see how any of your changes affect what's copied into DEBUG. You may reduce its contents to just a single byte of any value. But in order to see anything other than zero bytes in offsets 82h and following, at least one space byte (20h) must be placed between a non-space byte at the beginning of a line and whatever you'd like to have displayed. If the file contains only the 3 bytes: "T", space and "S", then offsets 82h and 83h would be an "S" followed by 0Dh.
This section is presently a "Work in Progress", but if you happen to see this before it's finished, can you guess what it's about?
Before using any of the
debugging (Trace, Procedure) or Register commands, you
should familiarize yourself with the abbreviations for the CPU Registers
that are referenced in DEBUG (See the Appendix, The
8086 CPU Registers for all the details.)
You should also know about the SEGMENT:OFFSET Addressing method used by DEBUG (and other programming utilities).
A note about where and how DEBUG is used in a computer's Memory: Using DEBUG in a Windows® DOS-box (or CMD prompt) for the first time could easily confuse you! If you open two instances of DEBUG (one per DOS-window) and examine all the memory they can access, you might notice completely different data in many of the same memory locations! The reason is that each application under a Windows OS is (theoretically) given its own 4-Gigabyte "Virtual computer" sandbox to play in, and a copy of the critical data within the machine's first Megabyte of Memory is made for each running instance of DEBUG. Only under 16-bit DOS, does DEBUG actually have access to the real Memory locations in which the operating system itself is running; making it much easier to crash the whole system if an error is made. Under Windows®, the theory is that such errors should crash only the open CMD window or application that caused a problem, but not the whole computer! At least that's how Windows® is supposed to operate. From experience, it seems that Windows 2000/XP do a much better job at keeping control of their systems under the same circumstances that often ended in Blue Screens on the displays of earlier versions! |
We recommend reading through the entire Tutorial on DEBUG before using these quick command links.
For a reminder of all the commands available while inside of DEBUG, simply enter a question mark (?) at the DEBUG prompt; when using DOS 5.0 or later.
Click on a command here for all its details:
-? 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] [number] unassemble U [range] write W [address] [drive] [firstsector] [number]