Debug Tutorial
Debug Tutorial
INTRODUCING DEBUG
As you begin to learn assembly language programming, the importance of using a
program called a debugger cannot be stressed too much. A debugger displays the
contents of memory and lets you view registers and variables as they change. You can
step through a program one line at a time (called tracing), making it easier to find logic
errors. In this appendix, we offer a tutorial on using the debug.exe program that is
supplied with both DOS and Windows (located in the \Windows\Command directory).
From now on, we will just call this program Debug. Later, you will probably want to
sample.exe
debug.exe
DOS
B.2
To trace or execute a machine language program with Debug, type the name of the
program as a command line parameter. For example, to debug the program sample.exe,
you would type the following command line at the DOS prompt:
debug sample.exe
If we could picture DOS memory after typing this command, we would see DOS loaded in
the lowest area, debug.exe loaded above DOS, and the program sample.exe loaded above
Debug. In this way, several programs are resident in memory at the same time. DOS
retains control over the execution of Debug, and Debug controls the execution of
sample.exe.
Printing a Debugging Session (local printer only). If you have a printer attached directly
to your computer, you can get a printed copy of everything you're doing during a debugging session by pressing the Ctrl-PrtScrn keys. This command is a toggle, so it can be
typed a second time to turn the printer output off.
Printing a Debugging Session (network printer). If your computer is attached to a
network and there is a printer on the network, printing a debugging session is a bit
challenging. The best way we've found is to prepare a script file containing all the debug
commands you plan to type. Run Debug, telling it to read its input from the script file, and
have Debug send the output to another file. Then, print the output file in the same way
you usually print on the network. In Windows, for example, the output file can be loaded
into Notepad and printed from there. See the section later in this appendix entitled Using
Script Files with Debug.
Using the Mark and Copy Operations in a DOS Window. Under Windows, when you run
Debug in a window, a toolbar has commands that you can use to mark a section of the
window, copy it to the clipboard, and paste it into some other application (such as
Notepad or Word):
Memory Manipulation
C
Miscellaneous
H
Input-Output
I
B.3
INDIVIDUAL COMMANDS
Default Values. When Debug is first loaded, the following defaults are in effect:
1. All segment registers are set to the bottom of free memory, just above the debug.exe
program.
2. IP is set to 0100h.
3. Debug reserves 256 bytes of stack space at the end of the current segment.
4. All of available memory is allocated (reserved).
5. BX:CX are set to the length of the current program or file.
6. The flags are set to the following values: NV (Overflow flag clear), UP (Direction flag
= up), EI (interrupts enabled), PL (Sign flag = positive), NZ (Zero flag clear), NA (Auxiliary Carry flag clear), PO (odd parity), NC (Carry flag clear).
2.1
Command Parameters
Debug's command prompt is a hyphen (). Commands may be typed in either uppercase
or lowercase letters, in any column. A command may be followed by one or more parameters. A comma or space may be used to separate any two parameters. The standard
command parameters are explained here.
Address. A complete segment-offset address may be given, or just an offset. The segment
portion may be a hexadecimal number or register name. For example:
F000:100
DS:200
0AF5
Segment, offset
Segment register, offset
Offset
Range. A range refers to a span of memory, identified by addresses in one of two formats.
In Format 1, if the second address is omitted, it defaults to a standard value. In Format 2,
the value following the letter L is the number of bytes to be processed by the command. A
range cannot be greater than 10000h (65,536):
Syntax
Examples
100.)
Sector. A sector consists of a starting sector number and the number of sectors to be
loaded or written. You can access logical disk sectors Using the L (load) and W (write)
commands.
String. A string is a sequence of characters enclosed in single or double quotes. For
example:
'COMMAND'
"File cannot be opened."
INDIVIDUAL COMMANDS
This section describes the most common Debug commands. A good way to learn them is
to sit at the computer while reading this tutorial and experiment with each command.
3.1
? (Help)
Press ? at the Debug prompt to see a list of all commands. For example:
Figure 1. Debug's List of Commands.
assemble
compare
dump
enter
fill
go
hex
input
load
move
name
output
proceed
quit
register
A
C
D
E
F
G
H
I
L
M
N
[address]
range address
[range]
address [list]
range list
[=address] [addresses]
value1 value2
port
[address] [drive] [firstsector] [number]
range address
[pathname] [arglist]
O port byte
P [=address] [number]
Q
R [register]
B.3
INDIVIDUAL COMMANDS
search
trace
unassemble
write
3.2
S range list
T [=address] [value]
U [range]
W [address] [drive] [firstsector] [number]
A (Assemble)
Assemble a program into machine language. Command formats:
A
A address
If only the offset portion of address is supplied, it is assumed to be an offset from CS.
Here are examples:
Example
Description
A 100
Assemble at CS:100h.
A DS:2000
Assemble at DS:2000h.
When you press Enter at the end of each line, Debug prompts you for the next line of
input. Each input line starts with a segment-offset address. To terminate input, press the
Enter key on a blank line. For example:
a 100
5514:0100 mov ah,2
5514:0102 mov dl,41
5514:0104 int 21
5514:0106
3.3
C (Compare)
The C command compares bytes between a specified range with the same number of
bytes at a target address. Command format:
C range address
For example, the bytes between DS:0100 and DS:0105 are compared to the bytes at
DS:0200:
3.4
74
15
F6
C7
20
75
00
C3
0E
1F
E8
D2
1F6E:0200
1F6E:0201
1F6E:0202
1F6E:0203
1F6E:0204
1F6E:0205
D (Dump)
The D command displays memory on the screen as single bytes in both hexadecimal and
ASCII. Command formats:
D
D address
D range
If no address or range is given, the location begins where the last D command left
off, or at location DS:0 if the command is being typed for the first time. If address is
specified, it consists of either a segment-offset address or just a 16-bit offset. Range
consists of the beginning and ending addresses to dump.
Example
Description
D F000:0
Segment-offset
D ES:100
Segment register-offset
D 100
Sffset
The default segment is DS, so the segment value may be left out unless you want to
dump an offset from another segment location. A range may be given, telling Debug to
dump all bytes within the range:
D 150 15A
Other segment registers or absolute addresses may be used, as the following examples
show:
B.3
INDIVIDUAL COMMANDS
Example
Description
D SS:0 5
D 915:0
D 0 200
D 100 L 20
Memory Dump Example. The following figure shows an example of a memory dump. The
numbers at the left are the segment and offset address of the first byte in each line. The
next 16 pairs of digits are the hexadecimal contents of each byte. The characters to the
right are the ASCII representation of each byte. This dump appears to be machine language instructions, rather than displayable characters.
Dump of offsets 0100h through 017Fh in COMMAND.COM:
-D 100
1CC0:0100
1CC0:0110
1CC0:0120
1CC0:0130
1CC0:0140
1CC0:0150
1CC0:0160
83
A5
8B
7A
7E
A5
40
7A
3D
80
8B
43
F8
3B
.~$.rdGFx...vx.z
% sI.z%.u.FB%.k=
.vx.z%.t..z%.t..
z%.u(.Fz.vz...v.
~x:C%u..6(t.D..C
%k.!.v2d;FzwX.Fx
@.FxH;F$u!!.v2d;
1CC0:0170
46 FC B9 00 00 75 01 41-A1 A8 F4 03 46 FC 8B 16
F|9..u.A!(t.F|..
7E
20
76
A5
F8
EB
89
A4
73
F8
0F
3A
0A
46
01
49
80
75
43
A1
F8
72
80
7A
28
A5
06
48
64
7A
A5
FF
75
F6
3B
C7
A5
08
46
0C
32
46
46-F8
0E-75
74-0C
FA-8B
03-36
E4-3B
A4-75
01
06
80
76
A8
46
A1
00
C6
7A
FA
F4
FA
A1
8B
42
A5
8B
8B
77
06
76
A5
07
84
44
D8
F6
F8
0A
74
06
FF
8B
32
80
EB
06
F6
88
46
E4
The following dump shows a different part of COMMAND.COM. Because memory at this
point contains a list of command names, the ASCII dump is more interesting:
-D 3AC0
1CD6:3AC0
05 45 58 49 53 54 EA 15-00 04 44 49 52 01 FA 09
.EXISTj...DIR.z.
1CD6:3AD0 07 52
1CD6:3AE0 0C 06
1CD6:3AF0 0C 05
1CD6:3B00 05 43
1CD6:3B10 13 05
B2
3D
01
1F
CE
.RENAME.2..REN.2
..ERASE.=..DEL.=
..TYPE.o..REM...
.COPY.L..PAUSE..
..DATE.8..TIME.N
1CD6:3B20
18 04 56 45 52 00 57 0E-04 56 4F 4C 01 C8 0D 03
..VER.W..VOL.H..
1CD6:3B30
1CD6:3B40
1CD6:3B50
1CD6:3B60
1CD6:3B70
1CD6:3B80
1CD6:3B90
1CD6:3BA0
43
44
01
41
53
05
05
05
CD.&..CHDIR.&..M
D.Y..MKDIR.Y..RD
....RMDIR....BRE
AK....VERIFY.G..
SET....PROMPT.z.
.PATH. ..EXIT.I.
.CTTY.w..ECHO.Y.
.GOTO....SHIFT.V
44
01
0E
4B
45
50
43
47
45
45
54
4F
44
01
D9
13
00
54
41
54
4F
4E
52
59
50
41
A6
12
06
92
00
54
54
54
41
41
50
59
54
12
06
52
17
0F
48
59
4F
4D
53
45
01
45
06
4D
4D
07
10
00
01
00
45
45
01
CC
00
43
4B
44
56
07
A0
F7
96
01-B2
01-3D
EF-0C
1A-06
38-18
48-44
44-49
49-52
45-52
50-52
0F-05
11-05
16-06
0C
0C
04
50
05
49
52
01
49
4F
45
45
53
04
04
52
41
54
52
01
0E
46
4D
58
43
48
52
44
45
55
49
01
D9
13
59
50
49
48
49
45
45
4D
53
4D
A6
12
06
00
54
54
4F
46
4E
4C
00
45
45
12
03
42
C7
00
00
00
54
01
01
04
00
00
03
52
52
17
FA
C9
59
00
4D
44
45
04
0F
11
17
56
10
3.5
1CD6:3BB0
16 03 49 46 00 50 15 04-46 4F 52 00 68 14 04 43
..IF.P..FOR.h..C
1CD6:3BC0
4C 53 00 53 12 00 00 00-00 00 00 00 00 00 00 00
LS.S............
E (Enter)
The E command places individual bytes in memory. You must supply a starting memory
location where the values will be stored. If only an offset value is entered, the offset is
assumed to be from DS. Otherwise, a 32-bit address may be entered or another segment
register may be used. Command formats are:
E address
E address list
Press the space bar to advance to the next byte, and press the Enter key to stop. To enter a
string into memory starting at location CS:100, type:
E CS:100 "This is a string."
3.6
F (Fill)
The F command fills a range of memory with a single value or list of values. The range
must be specified as two offset addresses or segment-offset addresses. Command format:
F range list
3.7
Example
Description
F CS:300 CS:1000,FF
F 100 L 20 'A'
Fill 20h bytes with the letter 'A', starting at location 100.
G (Go)
Execute the program in memory. You can also specify a breakpoint, causing the program
to stop at a given address. Command formats:
G
G breakpoint
B.3
INDIVIDUAL COMMANDS
11
G = startAddr breakpoint
G = startAddr breakpoint1 breakpoint2 ...
Breakpoint is a 16- or 32-bit address at which the processor should stop, and startAddr is
an optional starting address for the processor. If no breakpoints are specified, the program runs until it stops by itself and returns to Debug. Up to 10 breakpoints may be
specified on the same command line. Examples:
Example
Description
G 50
Execute from the current location and stop before the instruction at
offset CS:50.
G=10 50
CS:50.
3.8
H (Hexarithmetic)
The H command performs addition and subtraction on two hexadecimal numbers. The
command format is:
H value1 value2
For example, the hexadecimal values 1A and 10 are added and subtracted:
H 1A 10
2A 0A
3.9
(displayed by Debug)
I (Input)
The I command inputs a byte from a specified input/output port and displays the value in
hexadecimal. The command format is:
I port
Where port is a port number between 0 and FFFF. For example, we input a byte from port
3F8 (one of the COM1 ports), and Debug returns a value of 00:
-I 3F8
00
3.10
L (Load)
The L command loads a file (or logical disk sectors) into memory at a given address. To
read a file, you must first initialize its name with the N (Name) command. If address is
12
E x a m p le
D es cr ip tio n
L o a d n am e d file in to m em o ry a t C S :0 1 0 0
L D S :0 2 0 0
L o a d n am e d file in to m em o ry a t D S :0 2 0 0
L 100 2 A 5
L 100 0 0 2
L o a d tw o s ec to rs in to m e m o ry a t C S :1 0 0 , fro m th e
d is k in d rive A , sta rtin g a t lo g ic al sec to r n u m b er 0 .
omitted, the file is loaded at CS:100. Debug sets BX and CX to the number of bytes read.
Command format:
L
L address
L address drive firstsector number
The first format, with no parameters, implies that you want to read from a file into
memory at CS:0100. (Use the N command to name the file.) The second format also reads
from a named file, but lets you specify the target address. The third format loads sectors
from a disk drive, where you specify the drive number (0 = A, 1 = B, etc.), the first logical
sector number, and the number of sectors to read. Examples are shown in Table 1.
Each sector is 512 bytes, so a sector loaded at offset 100 would fill memory through
offset 2FF. Logical sectors are numbered from 0 to the highest sector number on the
drive. These numbers are different from physical sector numbers, which are hardwaredependent. To calculate the number of logical sectors, take the drive size and divide by
512. For example, a 1.44 MB diskette has 2,880 sectors, calculated as 1,474,560 / 512.
Here is a disassembly of sector 0 read from a floppy disk, using Debug. This is
commonly called the boot record. The boot record contains information about the disk,
along with a short program that is responsible for loading the rest of the operating system
when the computer starts up:
1F6E:0100
...
1F6E:0136
1F6E:0137
1F6E:0139
1F6E:013B
EB34
JMP
0136
FA
33C0
8ED0
BC007C
CLI
XOR
MOV
MOV
AX,AX
SS,AX
SP,7C00
B.3
3.11
INDIVIDUAL COMMANDS
13
M (Move)
The M command copies a block of data from one memory location to another. The
command format is:
M range address
Range consists of the starting and ending locations of the bytes to be copied. Address is
the target location to which the data will be copied. All offsets are assumed to be from DS
unless specified otherwise. Examples:
Example
Description
Sample String Move. The following example uses the M command to copy the string
'ABCDEF' from offset 100h to 106h. First, the string is stored at location 100h; then
memory is dumped, showing the string. Next, we move (copy) the string to offset 106h
and dump offsets 100h-10Bh:
-E 100 "ABCDEF"
-D 100 105
19EB:0100 41 42 43 44 45 46
-M 100 105 106
-D 100 10B
19EB:0100 41 42 43 44 45 46 41 42-43 44 45 46
3.12
ABCDEF
ABCDEFABCDEF
N (Name)
The N command initializes a filename (and file control block) in memory before using the
Load or Write commands. Comand format:
N
[d:][filename][.ext]
Example:
N b:myfile.dta
3.13
P (Proceed)
The P command executes one or more instructions or subroutines. Whereas the T (trace)
command traces into subroutine calls, the P command simply executes subroutines. Also,
14
LOOP instruction and string primitive instructions (SCAS, LODS, etc.) are executed
completely up to the instruction that follows them. Command format:
P
P =address
P =address number
Examples are:
Example
P =200
P =150 6
P5
Description
Execute a single instruction at CS:0200.
Execute 6 instructions starting at CS:0150.
Execute the next 5 instructions.
Example: Debugging a Loop. Let's look at an example where the P command steps
through MOV and ADD instructions one at a time. When the P command reaches the
LOOP instruction, however, the complete loop is executed five times:
-A 100
4A66:0100
4A66:0103
4A66:0106
4A66:0108
mov cx,5
mov ax,0
add ax,cx
loop 106
-R
AX=000F BX=0000
DS=4A66 ES=4A66
4A66:0100 B90500
-P
AX=000F BX=0000
DS=4A66 ES=4A66
4A66:0103 B80000
-P
AX=0000 BX=0000
DS=4A66 ES=4A66
4A66:0106 01C8
-P
AX=0005 BX=0000
DS=4A66 ES=4A66
4A66:0108 E2FC
-P
AX=000F BX=0000
DS=4A66
ES=4A66
; loop counter = 5
CX=0000
DX=0000
SP=FFEE
BP=0000
SS=4A66
CS=4A66
IP=010A
SI=0000
DI=0000
NV UP EI PL NZ NA PE NC
B.3
INDIVIDUAL COMMANDS
3.14
15
Q (Quit)
The Q command quits Debug and returns to DOS.
3.15
R (Register)
The R command may be used to do any of the following: display the contents of one
register, allowing it to be changed; display registers, flags, and the next instruction about
to be executed; display all eight flag settings, allowing any or all of them to be changed.
There are two command formats:
R
R register
Description
Display the contents of all registers.
Display the contents of IP and prompt for a new value.
Same (for the CX register).
Display all flags and prompt for a new flag value.
Once the R F command has displayed the flags, you can change any single flag by typing
its new state. For example, we set the Zero flag by typing the following two commands:
Data registers
Stack pointer
R F
Destination index
The following is a sample register display (all values
are in hexadecimal):
AX = 0000
BX = 0000
CX = 0000
DX = 0000
SP = FFEE
BP = 0000
DS = 1CC0
ES = 1CC0
SS = 1CC0
CS = 1CC0
IP = 0100
NV
UP
SI = 0000
DI
PL
NZ
Flags
Instruction pointer
Code segment
Stack segment
Extra segment
Data segment
DI = 0000
NA
PO
NC
16
The complete set of possible flag mnemonics in Debug (ordered from left to right) are as
follows:
Set
OV = Overflow
DN = Direction Down
EI = Interrupts Enabled
NG = Sign Flag negative
ZR = Zero
AC = Auxiliary Carry
PO = Odd Parity
CY = Carry
Clear
NV = No Overflow
UP = Direction Up
DI = Interrupts Disabled
PL = Sign Flag positive
NZ = Not Zero
NA = No Auxiliary Carry
PE = Even Parity
NC = No Carry
3.16
7E04
JLE
0106
S (Search)
The S command searches a range of addresses for a sequence of one or more bytes. The
command format is:
S range list
Comment
S 100 1000 0D
B.4
3.17
SEGMENT DEFAULTS
17
T (Trace)
The T command executes one or more instructions starting at either the current CS:IP
location or at an optional address. The contents of the registers are shown after each
instruction is executed. The command formats are:
T
T count
T =address count
Where count is the number of instructions to trace, and address is the starting address for
the trace. Examples:
Example
Description
T 5
T =105 10
This command traces individual loop iterations, so you may want to use it to debug
statements within a loop. The T command traces into procedure calls, whereas the P
(proceed) command executes a called procedure in its entirety.
3.18
U (Unassemble)
The U command translates memory into assembly language mnemonics. This is also
called disassembling memory. If you don't supply an address, Debug disassembles from
the location where the last U command left off. If the command is used for the first time
after loading Debug, memory is unassembled from location CS:100. Command formats
are:
U
U startaddr
U startaddr endaddr
Where startaddr is the starting point and endaddr is the ending address. Examples are:
18
3.19
Example
Description
U 0
U 100 108
W (Write)
The W command writes a block of memory to a file or to individual disk sectors. To write
to a file, its name must first be initialized with the N command. (If the file was just loaded
either on the DOS command line or with the Load command, you do not need to repeat
the Name command.) The command format is identical to the L (load) command:
W
W address
W address drive firstsector number
Place the number of bytes to be written in BX:CX. If a file is 12345h bytes long, for
example, BX and CX will contain the following values:
BX = 0001
CX = 2345
Description
Initialize the filename EXAMPLE.COM on the default drive.
Set the BX and CX registers to 00000020h, the length of the
file.
Write 20h bytes to the file, starting at CS:100.
Write from location CS:0 to the file.
Write named file from location CS:0100.
Write named file from location DS:0200.
The following commands are extremely dangerous to the data on your disk drive,
because writing sectors can wipe out the disk's existing file system. Use them with
extreme caution!
W 100 2 A 5
W 100 0 0 2
B.5
19
Description
Default Segment
Assemble
CS
Dump
DS
Enter
DS
Fill
DS
Go (execute)
CS
Load
CS
Move
DS
Procedure trace
CS
Search
DS
Trace
CS
Unassemble
CS
Write
CS
SEGMENT DEFAULTS
Debug recognizes the CS and DS registers as default segment registers when processing
commands. Therefore, the value in CS or DS acts as a base location to which an offset
value is added. Table 2 lists the default segment register for selected Debug commands.
The Assemble command, for example, assumes that CS is the default segment. If CS
contains 1B00h, Debug begins assembling instructions at location 1B00:0100h when the
following command is typed:
-A 100
The Dump command, on the other hand, assumes that DS is the default segment. If
DS contains 1C20h, the following command dumps memory starting at 1C20:0300h:
-D 300
B.5
read input from the script file instead of the console. For example, assume that a script
file called input.txt contains the following lines:
a 100
mov ax,5
mov bx,10
add ax,bx
int 20
(blank line)
Q
(Always remember to put a Q on a line by itself at the end of your script file. The Q
command returns to the DOS prompt.)
Debug can be executed, using the script file as input:
debug < input.txt
If you are running in a task-switching environment such as Windows, you can edit
and save the script file with the Notepad editor or DOS Edit (in a separate window). Then
switch back to a window in which you are running Debug. In this way, a program may be
modified, saved, assembled, and traced within a few seconds. If you would like the output
to be sent to a disk file or the printer, use redirection operators on the DOS command line:
debug < input.txt > prn
debug < input.txt > output.txt
(printer)
(disk file)