home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Unsorted BBS Collection
/
thegreatunsorted.tar
/
thegreatunsorted
/
programming
/
asm_programming
/
DEBUGTUT.TXT
< prev
next >
Wrap
Text File
|
1986-02-20
|
40KB
|
1,251 lines
Preface
This unsigned text-file was downloaded from a BBS in Houston Texas on
November 3, 1984. I have added the Title Page, Table of Contents, reorga-
nized the headings, added sections which appeared to have been missed by
the uploader but probably written by the originator, and made some slight
grammatical corrections to the more obvious errors I found.
The program is formatted for Wordstar printing with the Epson MX100 printer
set to compressed (17 CPI) mode. The resulting printout fits on a 5 1/2 by
8 1/2 page with about a 3/4 inch margin which leaves room for looseleaf
binder holes. To print this file with Wordstar, simply load as a Document
file set right margin to 75 and change use your equivalent command for
compressed printing (must put at start and end of header and footer too),
reformat if necessary, and save, and print.
Note that I set the page offset to 32. This sets the image on the center
of the paper and allows a 1-sided to 2-sided copy to overlay nicely with my
Xerox machine.
Robert J. Schniebolk
Gaithersburg, MD
November 4, 1984
DEBUG Tutorial
In the Public Domain
DEBUG Tutorial Page 2
TABLE OF CONTENTS
1. INTRODUCTION........................................................ 3
2. STARTING DEBUG...................................................... 4
3. DISPLAY COMMANDS.................................................... 5
3.1 Register command............................................... 5
3.2 Dump command................................................... 6
3.3 Search command................................................. 8
3.4 Compare........................................................10
3.5 Unassemble command.............................................11
4. DATA ENTRY..........................................................13
4.1 Enter..........................................................13
4.2 Fill...........................................................14
4.3 Move...........................................................15
4.4 Assemble.......................................................16
5. I/O COMMANDS........................................................18
5.1 Name...........................................................18
5.2 Load...........................................................18
5.3 Write..........................................................19
5.4 Input..........................................................20
5.5 Output.........................................................20
5.6 Quit...........................................................20
6. EXECUTION COMMANDS..................................................21
6.1 Go.............................................................21
6.2 Trace..........................................................22
7. ARITHMETIC..........................................................23
8. WRAPUP..............................................................24
DEBUG Tutorial Page 3
1. INTRODUCTION
This tutorial is made to present an overview of the DEBUG.COM program for
the IBM PC. This utility can be extremely useful, when used correctly. It
is almost a must for Assembler Language programmers, and can also provide
an insight into the operation of the machine at the bit level. It has
several nice features, including the ability to display and change any of
the registers in the IBMPC, start and stop program execution at any time,
change the program, and look at diskettes, sector by sector. DEBUG works
at the machine code level, but it does also have the ability to disassemble
machine code, and (at dos 2.0), assemble instructions directly into machine
code.
The procedure for starting DEBUG and command syntax will not be covered
here, as they are well documented in the DOS manual. What we will do is
show some examples of the various commands and the response which is ex-
pected. Note that the segment registers will probably not be exactly what
is shown. This is normal, and should be expected.
For the examples, I will be using the demo program CLOCK.COM in the XA4
database. For those of you with the IBM assembler (MASM), the source can
be down loaded. If you do not have the assembler, or have another assem-
bler, the file CLOCK.HEX has been up loaded. It can be converted to a COM
file using any of the existing HEX conversion programs on the SIG. See the
file CLOCK.DOC for more information.
DEBUG Tutorial Page 4
2. STARTING DEBUG
There are two ways to start DEBUG with a file. Both ways produce the same
results, and either can be used.
In the Command Line: A>DEBUG CLOCK.COM <ENTER>
Separate from the command line: A>DEBUG <ENTER>
-N CLOCK.COM
-L
With either method, you will get the DEBUG prompt of a hyphen (-). DEBUG
has loaded your program and is ready to run. The description of each
instruction will assume this as a starting point, unless otherwise mention-
ed. If at any time you get different results, check your procedure care-
fully. If it is correct, please leave me a message. I have tried to check
everything, but I have been known to make a mistake or two (anyway).
If you do have problems, you can enter the command Q (Quit) any time you
have the DEBUG prompt (-). This should return you to the DOS prompt.
DEBUG Tutorial Page 5
3. DISPLAY COMMANDS
3.1 Register command
The first thing we should look at are the registers, using the R command.
If you type in an R with no parameters, the registers should be displayed
as so:
AX=0000 BX=0000 CX=0446 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=6897 ES=6897 SS=6897 CS=6897 IP=0100 NV UP DI PL NZ NA PE NC
6897:0100 E96B01 JMP 026E
CX contains the length of the file (0446h or 1094d). If the file were
larger than 64K, BX would contain the high order of the size. This is very
important to remember when using the Write command, as this is the size of
the file to be written. Remember, once the file is in memory, DEBUG has no
idea how large the file is, or if you may have added to it. The amount of
data to be written will be taken from the BX and CX registers.
If we want to change one of the registers, we enter R and the register
name. Let's place 1234 (hexadecimal) in the AX register:
-R AX R and AX register
AX 0000 Debug responds with register and contents
: 1234 : is the prompt for entering new contents. We respond 1234
- Debug is waiting for the next command.
Now if we display the registers, we see the following:
AX=1234 BX=0000 CX=0446 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=6897 ES=6897 SS=6897 CS=6897 IP=0100 NV UP DI PL NZ NA PE NC
6897:0100 E96B01 JMP 026E
Note that nothing has changed, with the exception of the AX register. The
new value has been placed in it, as we requested. One note. The Register
command can only be used for 16 bit registers (AX, BX, etc.). It cannot
change the 8 bit registers (AH, AL, BH, etc.). To change just AH, for
instance, you must enter the the data in the AX register, with your new AH
and the old AL values.
DEBUG Tutorial Page 6
3.2 Dump command
One of the other main features of DEBUG is the ability to display areas of
storage. Unless you are real good at reading 8088 machine language, the
Dump command is mostly used to display data (text, flags, etc.). To dis-
play code, the Unassemble command below is a better choice. If we enter
the Dump command at this time, DEBUG will default to the start of the
program. It uses the DS register as it's default, and, since this is a COM
file, begins at DS:0100. It will by default display 80h (128d) bytes of
data, or the length you specify. The next execution of the Dump command
will display the following 80h bytes, and so on. For example, the first
execution of D will display DS:0100 for 80h bytes, the next one DS:0180 for
80h bytes, etc. Of course, absolute segment and segment register overrides
can be used, but only hex numbers can be used for the offset, e D will
display DS:0100 for 80h bytes, the next one DS:0180 for 80h bytes, etc. Of
course, absolute segment and segment register overrides can be used, but
only hex numbers can be used for the offset. That is, D DS:BX is invalid.
With our program loaded, if we enter the Dump command, we will see this:
6897:0100 E9 6B 01 43 4C 4F 43 4B-2E 41 53 4D 43 6F 70 79 ik.CLOCK.ASMCopy
6897:0110 72 69 67 68 74 20 28 43-29 20 31 39 38 33 4A 65 right (C) 1983Je
6897:0120 72 72 79 20 44 2E 20 53-74 75 63 6B 6C 65 50 75 rry D. StucklePu
6897:0130 62 6C 69 63 20 64 6F 6D-61 69 6E 20 73 6F 66 74 blic domain soft
6897:0140 77 61 72 65 00 00 00 00-00 00 00 00 00 00 00 00 ware............
6897:0150 00 00 00 00 00 00 00 00-00 24 00 00 00 00 00 00 .........$......
6897:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
6897:0170 00 00 00 00 00 00 00 00-00 00 00 00 44 4F 53 20 ............DOS
Notice that the output from the Dump command is divided into three parts.
On the left, we have the address of the first byte on the line. This is in
the format Segment:Offset.
Next comes the hex data at that location. Debug will always start the
second line at a 16 byte boundary; that is, if you entered D 109, you would
get 7 bytes of information on the first line (109-10F), and the second line
would start at 110. The last line of data would have the remaining 9 bytes
of data, so 80h bytes are still displayed.
DEBUG Tutorial Page 7
The third area is the ASCII representation of the data. Only the standard
ASCII character set is displayed. Special characters for the IBMPC are not
displayed; rather periods (.) are shown in their place. This makes search-
ing for plain text much easier to do.
Dump can be used to display up to 64K bytes of data, with one restriction:
It cannot cross a segment boundary. That is, D 0100 l f000 is valid
(display DS:0100 to DS:F0FF), but D 9000 l 8000 is not (8000h +9000h =
11000h and crosses a segment boundary).
Since 64K is 10000h and cannot fit into four hex characters, Dump uses 0000
to indicate 64K. To display a complete segment, enter D 0 l 0. This will
display the total 64K segment.
If, at any time you want to suspend the display of data, Cntl-NumLock as
usual. If you want to terminate the display, Cntl-Break will stop itand
return you to the DEBUG prompt.
DEBUG Tutorial Page 8
3.3 Search command
Search is used to find the occurrence of a specific byte or series of bytes
within a segment. The address parameters are the same as for the Dump
command, so we will not duplicate them here. However, we also need the
data to be searched for. This data can be entered as either hexadecimal or
character data. Hexadecimal data is entered as bytes, with a space or a
comma as the separator. Character data is enclosed by single or double
quotes. Hex and character data can be mixed in the same request, i.e. S 01
100 12 34 'abc' 56 is valid, and requests a search from DS:0000 through
DS:00FF for the sequence of 12h 34h a b c 56h, in that order. Upper case
characters are different than lower case characters, and a match will
not be found if the case does not match. For instance, 'ABC' is not
the same as 'abc' or 'Abc' or any other combination of upper and lower
case characters. However, 'ABC' is identical to "ABC", since the single
and double quotes are separators only.
For example when looking for the string 'Sat', the following would occur:
-S 0 l 0 'Sat'
6897:0235
-
The actual segment would be different in your system, but the offset should
be the same. If we then displayed the data, we would find the string
'Saturday' at this location. We could also search on 'turda', or any other
combination of characters in the string. If we wanted to find every place
we did an Int 21h (machine code for Int is CD), we would do the following:
-S 0 l 0 cd 21
6897:0050
6897:0274
6897:027F
6897:028B
6897:02AD
6897:02B4
6897:0332
6897:0345
6897:034C
6897:043A
6897:0467
6897:047A
6897:0513
6897:0526
6897:0537
6897:0544
DEBUG Tutorial Page 9
DEBUG found the hex data CD 21 at the above locations. This does not mean
that all these addresses are INT 21's, only that that data was there. It
could (and most likely is) an instruction, but it could also be an address,
the last part of a JMP instruction, etc. You will have to manually inspect
the code at that area to make sure it is an INT 21. (You don't expect the
machine to do everything, do you?).
DEBUG Tutorial Page 10
3.4 Compare command
Along the same lines of Dump and Search commands, we have the Compare
command. Compare will take two blocks of memory and compare them, byte for
byte. If the two addresses do not contain the same information, both
addresses are displayed, with their respective data bytes. As an example,
we will compare DS:0100 with DS:0200 for a length of 8.
-d 0100 l 8 0200
6897:0100 E9 65 6897:0200
6897:0101 6B 70 6897:0201
6897:0102 01 74 6897:0202
6897:0103 43 65 6897:0203
6897:0104 4C 6D 6897:0204
6897:0105 4F 62 6897:0205
6897:0106 43 65 6897:0206
6897:0107 4B 72 6897:0207
None of the eight bytes compared, so we got output for each byte. If we
had gotten a match on any of the bytes, DEBUG would have skipped that byte.
If all of the locations requested matched, DEBUG would have simply respond-
ed with another prompt. No other message is displayed. This is useful for
comparing two blocks of data from a file, or a program with the BIOS ROM.
Otherwise, I have not found a great amount of use for it.
DEBUG Tutorial Page 11
3.5 Unassemble command
For debugging, one of the main commands you will use is the Unassemble
command. This command will take machine code and convert it to instruc-
tions. Addressing is the same as for previous commands with one exception:
Since we are now working with code (the previous commands are mainly for
data), the default register is the CS register. In a .COM program, this
makes very little difference, unless you reset the DS register yourself.
However, in a .EXE file, it can make a lot of difference, as the CS and DS
registers are set to different values.
Unassemble data can lead to some interesting results. For instance, in our
example, CS:IP is set to 6897:0100. If we look at the program, we see a
JMP as the first instruction, followed by data. If we just enter U, we
will start at CS:IP (6897:0100) and start unassembling data. What we will
get is a good instruction, followed by more or less nonsense. For instance:
-U
6897:0100 E96B01 JMP 026E
6897:0103 43 INC BX
6897:0104 4C DEC SP
6897:0105 4F DEC DI
6897:0106 43 INC BX
6897:0107 4B DEC BX
And so on through 6897:011D. We know the INC BX, DEC SP, etc. are not valid
instructions, but DEBUG doesn't, so we do have to look at the code. After
working with DEBUG a little, you will be able to spot code versus data with
the Unassemble command. For now, suffice to say that the first instruction
will take us to CS:026E and we can start from there.
DEBUG Tutorial Page 12
If we Unassemble CS:026E, we will find something which looks a little more
like what we expect. We get:
-U 26E
6897:026E 8D167802 LEA DX,[0278]
6897:0272 B409 MOV AH,09
6897:0274 CD21 INT 21
6897:0276 EB05 JMP 027D
6897:0278 1B5B32 SBB BX,[BP+DI+32]
6897:027B 4A DEC DX
6897:027C 24B4 AND AL,B4
6897:027E 30CD XOR CH,CL
6897:0280 213C AND [SI],DI
6897:0282 027D0A ADD BH,[DI+0A]
6897:0285 8D167C01 LEA DX,[017C]
6897:0289 B409 MOV AH,09
6897:028B CD21 INT 21
6897:028D CD20 INT 20
The first few instructions look fine. But after the JMP 027D, things start
to look a little funny. Also, note that there is no instruction starting
at 027D. We have instructions at 027C and 027E, but not 027D. This is
again because DEBUG doesn't know data from instructions. At 027C, we
should (and do) have the end of our data. But this also translates into a
valid AND instruction, so DEBUG will treat it as such. If we wanted the
actual instruction at 027D, we could enter U 027D and get it, but from
here, we don't know what it is. What I'm trying to say is, DEBUG will do
what ever you tell it. If you tell it to Unassemble data, it will do so to
the best of its ability. So, you have to make sure you have instructions
where you think you do.
DEBUG Tutorial Page 13
4. DATA ENTRY
4.1 Enter command
The Enter command is used to place bytes of data in memory. It has two
modes: Display/Modify and Replace. The difference is in where the data is
specified - in the Enter command itself, or after the prompt.
If you enter E address alone, you are in display/modify mode. DEBUG will
prompt you one byte at a time, displaying the current byte followed by a
period. At this time, you have the option of entering one or two hexadeci-
mal characters. If you hit the space bar, DEBUG will not modify the
current byte, but go on to the next byte of data. If you go too far, the
hyphen (-) will back up one byte each time it is pressed.
E 103
6897:0103 43.41 4C.42 4F.43 43. 4B.45
6897:0108 2E.46 41.40 53.-
6897:0109 40.47 53.
In this example, we entered E 103. DEBUG responded with the address and
the information at that byte (43). We entered the 41 and DEBUG automatic-
ally showed the next byte of data (4C). Again, we entered 42, debug came
back. The next byte was 4F, we changed it to 43. At 106, 43 was fine with
us, so we just hit the space bar. DEBUG did not change the data, and went
on to the following bytes. After entering 40 at location 109, we found we
had entered a bad value. The hyphen key was pressed, and DEBUG backed up
one byte, displaying the address and current contents. Note that it has
changed from the original value (41) to the value we typed in (40). We
then type in the correct value and terminate by pressing the ENTER key.
As you can see, this can be very awkward, especially where large amounts of
data are concerned. Also, if you need ASCII data, you have to look up each
character and enter its hex value. Not easy, to be sure. That's where the
Replace mod of operation comes in handy. Where the Display/Modify mode is
handy for changing a few bytes at various offsets, the Replace mode is for
changing several bytes of information at one time. Data can be entered in
hexadecimal or character format, and multiple bytes can be entered at one
time without waiting for the prompt. If you wanted to store the characters
'My name' followed by a hexadecimal 00 starting at location 103, enter:
E 103 'My name' 0
As in the Search command, data can be entered in character (in quotes) or
hexadecimal forms and can be mixed in the same command. This is the most
useful way of entering large amounts of data into memory.
DEBUG Tutorial Page 14
4.2 Fill
The Fill command is useful for storing a lot of data of the same data. It
differs from the Enter command in that the list will be repeated until the
requested amount of memory is filled. If the list is longer than the
amount of memory to be filled, the extra items are ignored. Like the Enter
command, it will take hexadecimal or character data. Unlike the Enter
command, though, large amounts of data can be stored without specifying
every character. As an example, to clear 32K (8000h) of memory to 00h, you
only need to enter:
F 0 L 8000 0
Which translates into Fill, starting at DS:0000 for a Length of 32K (8000)
with 00h. If the data were entered as '1234', the memory would be filled
with the repeating string '123412341234', etc. Usually, it is better to
enter small amounts of data with the Enter command, because an error in the
length parameter of the Fill command can destroy a lot of work. The Enter
command, however, will only change the number of bytes actually entered,
minimizing the effects of a parameter error.
DEBUG Tutorial Page 15
4.3 Move
The Move command does just what it says - it moves data around inside the
machine. It takes bytes from with the starting address and moves it to the
ending address. If you need to add an instruction into a program, it can
be used to make room for the instruction. Beware, though. Any data or
labels referenced after the move will not be in the same place. Move can
be used to save a part of the program in free memory while you play with
the program, and restore it at any time. It can also be used to copy ROM
BIOS into memory, where it can be written to a file or played with to your
heart's content. You can then change things around in BIOS without having
to worry about programming a ROM.
M 100 L 200 ES:100
This will move the data from DS:0100 to DS:02FF (Length 200) to the address
pointed to by ES:0100. Later, if we want to restore the data, we can say:
M ES:100 L 200 100
which will move the data back to its starting point. Unless the data has
been changed while at the temporary location (ES:0100), we will restore the
data to its original state.
DEBUG Tutorial Page 16
4.4 Assemble
I purposely left the Assemble command to the end, as it is the most complex
of the data entry commands. It will take the instructions in the assembler
language and convert them to machine code directly. Some of the things it
can't do, however, are: reference labels, set equates, use macros, or
anything else which cannot be translated to a value. Data locations have
to be referenced by the physical memory address, segment registers, if
different from the defaults, must be specified, and RET instructions must
specify the type (NEAR or FAR) of return to be used. Also, if an instruc-
tion references data but not registers (i.e. Mov [278],5), the Byte ptr or
Word ptr overrides must be specified. One other restriction: To tell
DEBUG the difference between moving 1234h into AX and moving the data from
location 1234 into AX, the latter is coded as Mov AX,[1234], where the
brackets indicate the reference is an addressed location. The differences
between MASM and DEBUG are as follows:
MASM DEBUG Comments
Mov AX,1234 Mov AX,1234 Place 1234 into AX
Mov AX,L1234 Mov AX,[1234] Contents of add. 1234 to AX
Mov AX,CS:1234 CS:Mov AX,[1234] Move from offset of CS.
Movs Byte ptr ... Movesb Move byte string
Movs Word ptr ... Movsw Move word string
Ret Ret Near return
Ret Retf Far return
Also, Jmp instructions will be assembled automatically to Short, Near, or
Far Jmps. However, the Near and Far operands can be used to override the
displacement if you do need them. Let's try a very simple routine to clear
the screen.
-A 100
6897:0100 MOV AX,600
6897:0103 MOV CX,0
6897:0106 MOV DX,184f
6897:0109 MOV BH,07
6897:010B INT 10
6897:010D INT 20
6897:010F
-
DEBUG Tutorial Page 17
We are using BIOS interrupt 10h, which is the video interrupt. (If you
would like more information on the interrupt, there is a very good descrip-
tion in the Technical Reference Manual.) We need to call BIOS with AX=600,
BH=7, CX=0, and DX=184Fh. First we had to load the registers, which we did
at in the first four instructions. The statement at offset 6897:010B
actually called BIOS. The INT 20 at offset 010D is for safety only. We
really don't need it, but with it in, the program will stop automatically.
Without the INT 20, and if we did not stop, DEBUG would try and execute
whatever occurs at 010F. If this happens to be a valid program (unlikely),
we would just execute the program. Usually, though, we will find it to be
invalid, and will probably hang the system, requiring a Ctrl-Alt-Del (may-
be) or a power-off and on again (usually). So, be careful and double check
your work!
Now, we need to execute the program which will probably hang the system,
requiring a Ctrl-Alt-Del (maybe) or a power-off and on again (usually).
So, be careful and double check your work! To proceed, enter the G com-
mand, a G followed by the enter key. If you have entered the program
correctly, the screen will clear and you will get a message "Program ter-
minated normally". (More on the Go command later).
Again, I cannot stress the importance of checking your work when using the
Assemble command. The commands may assemble correctly, but cause a lot of
problems. This is especially important for the Jmp and Call commands;
since they cause an interruption in the flow of the program, they can cause
the program to jump into the middle of an instruction, causing VERY unpre-
dictable results.
DEBUG Tutorial Page 18
5. I/O COMMANDS
5.1 Name
The Name command has just one purpose - specifying the name of a file which
DEBUG is going to Load or Write. It does nothing to change memory or
execute a program, but does prepare a file control block for DEBUG to work
with. If you are going to load a program, you can specify any parameters
on the same line, just like in DOS. One difference is, the extension MUST
be specified. The default is no extension. DEBUG will load or write any
file, but the full file name must be entered.
-N CHKDSK.COM /F
This statement prepares DEBUG for loading the program CHKDSK.COM passing
the /F switch to the program. When the Load (see below) command is execut-
ed, DEBUG will load CHKDSK.COM and set up the parameter list (/F) in the
program's input area.
5.2 Load
The Load command has two formats. The first one will load a program which
has been specified by the Name command into storage, set the various regis-
ters, and prepare for execution. Any program parameters in the Name com-
mand will be set into the Program Segment Prefix, and the program will be
ready to run. If the file is a .HEX file, it is assumed to have valid
hexadecimal characters representing memory values, two hexadecimal charac-
ters per byte. Files are loaded starting at CS:0100 or at the address
specified in the command. For .COM. .HEX and .EXE files, the program will
be loaded, the registers set, and CS:IP set to the first instruction in the
program. For other files, the registers are undetermined, but basically,
the segment registers are set to the segment of the PSP (100h bytes before
the code is actually loaded), and BX and CX are set to the file length.
Other registers are undetermined
-N CLOCK.COM
-L
This sequence will load CLOCK.COM into memory, set IP to the entry point of
0100, and CX will contain 0446, the hexadecimal size of the file. The
program is now ready to run.
The second form of the Load command does not use the Name command. It is
used to load absolute sectors from the disk (hard or soft) into memory.
DEBUG Tutorial Page 19
The sector count starts with the first sector of track 0 and continuing to
the end of the track. The next sector is track 0, second side (if double
sided), and continues to the end of that sector. Then, back to the first
side, track 1, and so on, until the end of the disk. Up to 80h (128d)
sectors can be loaded at one time. To use, you must specify starting
address, drive (0=A, 1=B, etc.), starting sector, and number of sectors to
load.
-L 100 0 10 20
This instruction tells DEBUG to load, starting at DS:0100, from drive A,
sector 10h for 20h sectors. DEBUG can sometimes be used this way to
recover part of the information on a damaged sector. If you get an error,
check the memory location for that data. Often times, part of the data has
been transferred before the error occurs and the remainder (especially for
text files) can be manually entered. Also, repetitive retrys will some-
times get the information into memory. This can then be rewritten on the
same diskette (see the Write command below), or copied to the same sector
on another diskette. In this way, the data on a damaged disk can sometimes
be recovered.
5.3 Write
The write command is very similar to the Load command. Both have two modes
of operation, and both will operate on files or absolute sectors. As you
have probably guessed, the Write command is the opposite of the Load com-
mand. Since all the parameters are the same, we will not cover the syntax
in detail. However, one thing worth mentioning: When using the file mode
of the Write command, the amount of data to be written is specified in BX
and CX, with BX containing the high-order file size. The start address can
be specified or is defaulted to CS:0100. Also, files with an extension of
EXE or HEX cannot be written out, and error message to that effect will be
displayed. If you do need to change a .EXE or .HEX file, simply rename and
load it, make your changes, save it and name it back to its original
filename.
DEBUG Tutorial Page 20
5.4 Input
The Input command is used to access data from the machine's input ports.
The Input command must specify the desired port. Invocation of the command
will provide a one byte response from the selected port. For example:
-I 3F8
7D
-
This is the Line input port for the first Asynchronous adapter. Your data
may be different, as it depends on the current status of the port. It
indicates the data in the register at the time it was read was 7Dh. Depen-
ding on the port, this data may change, as the ports are not controlled by
the PC.
5.5. Output
As you can probably guess, the Output command is the reverse of the Input
command. You can use the Output command to send a single byte of data to a
port. Note that certain ports can cause the system to hang (especially
those dealing with system interrupts and the keyboard), so be careful with
what you send where!
-O 3FC 1
-
Port 3FCh is the modem control register for the first asynchronous port.
Sending a 01h to this port turns on the DTR (Data Terminal Ready) bit. A
00h will turn all the bits off. If you have a modem which indicates this
bit, you can watch the light flash as you turn the bit on and off.
5.6 Quit
This command needs no explanation, however, you must remember to write all
data to the desired file prior to exercising this command as the result is
an immediate exit from the program.
-Q
A>
(Although not really an I/O comand for debugging a program, this command is
certainly an out from Debug.)
DEBUG Tutorial Page 21
6. EXECUTION COMMANDS
6.1 Go
The Go command is used to start program execution. A very versatile com-
mand, it can be used to start the execution at any point in the program,
and optionally stop at any of ten points (breakpoints) in the program. If
no breakpoints are set (or the breakpoints are not executed), program
execution continues until termination, in which case the message "Program
terminated normally" is sent. If a breakpoint is executed, program execu-
tion stops, the current registers are displayed, and the DEBUG prompt is
displayed. Any of the DEBUG commands can be executed, including the Go
command to continue execution. Note that the Go command CANNOT be termin-
ated by Ctrl-break. This is one of the few commands which cannot be
interrupted while executing.
-G = 100
The Go command without breakpoints starts program execution at the address
(in this case CS:0100) in the command. The equal sign before the address
is required. (Without the equal sign, the address is taken as a break-
point.) If no starting address is specified, program execution starts at
CS:IP. In this case, since no breakpoints are specified, CLOCK.COM will
continue execution until the cntl-break key is pressed and the program
terminates. At this time, you will get the message "Program terminated
normally". Note that, after the termination message, the program should be
reloaded before being executed. Also, any memory alterations (storing
data, etc.) will not be restored unless the program is reloaded.
-G 276 47C 528 347
This version of the control command will start the program and set break-
points at CS:276, CS:47C, CS:528 and CS:347. These correspond to locations
in CLOCK.COM after the screen is cleared, and the day, date and time are
displayed, respectively. The program will stop at whichever breakpoint it
hits first. Note that the second and third breakpoints will only be dis-
played at two times - when the program is started and at midnight. If you
care to stay up (or just change the time in the computer), and set a
breakpoint at 47C, this will stop when the program is started, and again at
midnight.
Some notes about breakpoints. The execution stops just before the instruc-
tion is executed. Setting a breakpoint at the current instruction address
will not execute any instructions. DEBUG will set the breakpoint first,
then try to execute the instruction, causing another breakpoint. Also, the
DEBUG Tutorial Page 22
breakpoints use Interrupt 3 to stop execution. DEBUG intercepts interrupt
3 to stop the program execution and display the registers. Finally, break-
points are not saved between Go commands. Any breakpoints you want will be
have to be set with each Go command.
6.2 Trace
Along the same lines as Go is the Trace command. The difference is that,
while Go executes a whole block of code at one time, the Trace command
executes instructions one at a time, displaying the registers after each
instruction. Like the Go instruction, execution can be started at any
address. The start address again must be preceeded by an equal sign.
However, the Trace command also has a parameter to indicate how many in-
structions are to be executed.
-T =100 5
This Trace command will start at CS:100 and execute five instructions.
Without the address, execution will start at the current CS:IP value and
continue for five instructions. T alone will execute one instruction.
When using Trace to follow a program, it is best to go around calls to DOS
and interrupts, as some of the routines involved can be lengthy. Also, DOS
cannot be Traced, and doing so has a tendency to hang the system. There-
fore, Trace to the call or interrupt and Go to the next address after the
call or interrupt.
DEBUG Tutorial Page 23
7. ARITHMETIC COMMANDS
7.1 Hexarithmetic
The Hexarithmetic command is handy for adding and subtracting hexadecimal
numbers. It has just two parameters - the two numbers to be added and
subtracted. DEBUG's response is the sum and difference of the numbers.
The numbers can be one to four hexadecimal digits long. The addition and
subtraction are unsigned, and no carry or borrow is shown beyond the fourth
(high order) digit.
-H 5 6
000B FFFF
-H 5678 1234
68AC 4444
-
In the first example, we are adding 0005 and 0006. The sum is 000B, the
difference is -1. However, since there is no carry, we get FFFF. In the
second example, the sum of 5678 and 1234 is 68AC, and the difference is
4444.
DEBUG Tutorial Page 24
8. WRAPUP
If you give it a chance, DEBUG can be a very useful tool for the IBMPC. It
is almost a requirement for debugging assembler language programs, as no
nice error messages are produced at run time. DEBUG does work at the base
machine level, so you need some experience to use it effectively, but with
practice, it will be your most useful assembler language debugging tool.