V22.0201.002, Machine Organization I, Fall 97
HOW TO USE THE DEBUGGER
TD, TDW and TD32.
(You can find them under the TASM folder.)
TD is for 16-bit DOS applications while
TDW and TD32 are for 16-bit and 32-bit windows applications.
For this course, you only need to use TD. This
is what we assume here. But TD only
works from a DOS environment. That means that you need to
invoke TD from within
an MS-DOS PROMPT window (see FAQs for this).
Here is basic information for using a debugger.
We will be using the Turbo Debugger. Since
this is a fairly complex piece of software,
we will help you with some orientation
Actually, there are 3 versions of the Turbo Debugger:
Note that MS-DOS provides an extremely simple debugger
called DEBUG. You might find it useful to learn
this simple debugger as well (the information on this is in
chapter 5 and Appendix E of your text).
Pre-Debugger: Syntax Errors
Before we even approach the debugger, let us address
a class of errors for which it is an overkill
to use the debugger: that is when you do not
even succeed in assembling your program! No object
file could be produced. These
are basically syntax errors.
The fix here is basically trivial.
First note that if you invoke
``tasm hw1'', it will report the line numbers of
each instruction that has a syntax error.
All you need to do is to address
the problems, one offending line at a time!
To ask tasm to print out the actual offending instructions,
not just their line numbers, do this instead:
Where does the debugger come in? Well, to debug errors
that has to do with the logic of your program.
These are sometimes called semantic errors
as opposed to the ``syntax errors'' in the previous paragraph.
Of course, you can still avoid using a debugger for
small programs. When your programs become complex
the debugger may be essential.
The first thing to realize is that in order to use
the debugger, your assembler and linker needs
to store certain additional information needed by
the debugger. E.g., if you define the variable
then your .obj and .exe files
needs to retain the symbolic information
telling the debugger that data at offset ABCD0123h (or whatever)
is the same as "Greeting". As the human
user, you prefer to see the symbolic name
"Greeting" rather than "ABCD0123h". To do this, such
``symbolic information'' that are normally discarded by TASM needs
to be recorded in the object file it produces.
This can be done by calling TASM
and TLINK with the options /zi and /v (respectively).
Here is a slight revision of the ``First Steps'' instructions
used in the TASM notes:
Greeting db 'Hello, World!'
Note that the resulting .obj and .exe
files with these options are bigger than they otherwise would be.
To see other command options available with tasm or tlink,
you can invoke "tasm" or "tlink" without any arguments.
:> tasm /zi /z hw1
:> tlink /v hw1
:> td hw1
How to Debug
There are 4 basic steps:
The debugger gives you tools to help in all these steps.
E.g., you can run the code in a step-by-step fashion or until
some breakpoint you set in the code. In between these
execution steps, you can examine memory and CPU state
(variables, registers, flags and stack).
- Discovering the Bug. Is there one?
It is not always obvious that you have a bug. (WHY?)
- Isolating the Bug. Where is it?
Locate the part(s) of the
code that is causing the bug.
- Finding the Bug. What exactly is wrong with
the buggy code fragment?
- Fixing the Bug. How should the buggy fragment be
Mechanics of Using TD
NOTE: It is best to print a copy of this and read it
while seated in front of the Turbo Debugger
(say, with your hw1 program loaded, using the
method suggested above).
The Main TD window shows a standard (pull-down) menu bar at the top.
The menu bar lists the following menus:
File, Edit, View, Run, Breakpoints, Data, Options, Windows, Help.
The status bar at the bottom of the
TD window contains helpful information about the
current context. For instance, you often see
a list of all the functions
associated with the function keys F1 to F10.
For instance, F9 is the ``Run'' command.
That means these functions are available in the current context.
Within the Main TD window we can
have a variety of (sub)windows. At any moment,
several of these windows may be active. Each
active windows is numbered (1,2,3, etc.) and this
number is displayed on the upper right hand corner of window.
Below, we will go into some of these windows and discuss how
to manage them. Among the active windows, one of them is
the current top window. The top window has a little green
rectangle at its upper left corner. You can close this
window by clicking on this little green rectangle.
The function key F6
(called ``Next'') steps through your
active windows, allowing each
of them to be ``top window'' in turn.
Try stepping through your windows: how
many windows do you have at this point?
What is the current number of active windows?
How is the ``top window'' indicated?
We already mentioned the Help (pulldown) menu. But
there are more ``immediate'' or context-sensitive
- Status Bar
We noted that status bar usually shows the list of functions associated with
the 10 function keys. But if you hold down the
ALT key, the status bar will show the functions associated
with ALT+Function Keys.
[E.g., ALT+F5 is the ``User'' Function.
Try this! This just gets you back to the MS-DOS Prompt Window.
This is useful if you need to see any output from your
executed code. To get back from the MS-DOS Prompt, type
If you hold down the CTRL key, you will see the CTRL+key
[E.g., CTRL+I allows you to inspect the variable that
the cursor is currently pointed at.]
- Function F1
This key opens a help window containing information
about the current top window, with further subtopics
to choose from.
This can be invoked with the right mouse click at any time.
In most windows, you will get a list of options
suitable for that window.
Some Pulldown Menus
Let us go over some of the pulldown menus:
VIEW pulldown menu
The types of windows available are listed under the VIEW menu.
We describe three of them here:
- Module Window This is usually the first
window you see, and is number 1. It shows
your source code, and so may appear the most
familiar to you (after all, you wrote that code!).
- Watch Window This is usually the second
window you see, and thus is number 2. You can
set up variables and expressions in this window
to ``watch'' (their values change as your program
In fact, exercise 1, you probably saw the Module
and Watch Windows (the watch window
is quite narrow, and you may miss it).
This window is most useful for
assembly language programming (i.e., for this course!)
as it shows the state of your CPU.
At the top bar of this
window, it will tell you the CPU class
(486, Pentium, etc) of the current machine.
This window is partitioned
into 5 smaller display regions called panes:
For more details, see CPU Window
- Code pane:
this pane on the top left is the largest,
showing the machine code and disassembled assembly
instructions of your executable program.
(Source code lines can also be displayed.)
- Registers pane:
this pane is to the right of the
- Flags pane:
this pane is to the right of the
registers pane, showing the 8 CPU flag bits.
- Dump pane:
This is directly below the code pane,
showing the hex dump of any memory
area accessible by your program.
- Stack pane:
this is on the bottom right, showing the
contents of the program stack (in hex)
Write a simple program with these instructions (in addition to
the usual stuff):
Now load the program into TD, and call up the CPU Window
(in addition to the default Module and Watches Windows).
Now step through the execution of the program using F7.
After each step, describe the contents of ax and bx,
and the status flag variables.
WINDOW pulldown menu
This menu helps you manage the various windows.
This menu is divided into two halves (separated
by a horizontal line): the top half contains
commands such as
Next pane (=tab),
The bottom half is
a list of the currently active windows.
RUN pulldown menu
Windows are for watching. But for action, you need
to execute your code. For this, the
RUN menu provides several modes of execution:
- Run (=F9),
i.e., until program terminates
(or until the next breakpoint).
This is the simplest mode.
- Trace into (=F7 or ALT+F7),
i.e., single stepping, instruction by instruction.
What constitutes a single step depends on
which the current ``top window''. If the top
window is the Module window or if you
use F7, then a single
line of source code is executed. If the top window
is the CPU window or if you use ALT+F7,
then a single machine instruction is
executed. If the current source line contains
a function call, TD traces into the function
(assuming it was compiled with debug information).
Some machine instructions, however, cause multiple
instructions to be executed include: CALL, INT,
- Step over (=F8)
This is like ``Trace into'' except that
when the instruction pointer is at a function call,
then the entire function is executed and
you are next placed at the statement following the
(similar to run until terminate, except it
pauses between machine instructions to allow
you to catch what is happening)
(move the instruction pointer
back to the first instruction)
List the functions available as a CTRL+key functions.
List the functions in the SpeedMenu
under the Code Pane of the CPU window.
For each of these functions, briefly describe
what they do (you can either experiment and/or read
up the online help), and describe a debugging
situation in which you might find them useful.
Breakpoints are a device to cause the computer
to take specific actions at specific
points in its execution.
The user can define a breakpoint by specifying
three pieces of information.
The simplest kind of breakpoint is one that
(a) is associated with a specific instruction in the program,
which (b) is always activated (condition is ``always true'')
and (c) pauses the program execution (action is ``break'').
These are called simple breakpoints.
It is the default assumed by TD, and it should suffice
for our purposes. Using this, you run the program
at full speed until specific
instructions, at which points you can examine the
state of the memory and CPU.
- The location
where the breakpoint is set.
- The condition
which allows the breakpoint to activate.
- The action
that takes place when the breakpoint is activated.
As an example of more complex breakpoints,
you could have a global breakpoint which
(a)' is evaluated after each line of source code,
which (b)' is activated when a particular variable is modified
and (c)' logs the value of an expression.
How do you set simple breakpoints?
Well, you only need to specify an instruction in the
program. The simplest is to do this from within
the Module Window, or from the Code Pane in the CPU Window:
Breakpoint addresses must be entered when you
use the keyboard to enter breakpoints. (You can see this
in the Breakpoint option dialog box above.)
Here are the kinds of addresses you can specify:
- First place the cursor at an executable line of code
where a breakpoint is desired.
(How do you tell if a line is executable?)
You then left-click the 2 leftmost columns of line.
Instead of left-click, you can also use
function F2 (see the status line).
NOTE: if the line already has a breakpoint,
then this action removes that breakpoint.
Hence this is also called the toggle action.
- If you use the Breakpoint->At menu option,
you can also place a simple breakpoint at the
current cursor position. However, since this
has a pop-up Breakpoint option dialog box,
also specify more complex types of breakpoint.
How do you see all the current breakpoints?
In the Breakpoints Window, which
can be activated using the View->Breakpoints menu option.
This window has two panes: the left pane lists all the
current breakpoints, the right pane gives details about
the breakpoint that is currently highlighted.
The SpeedMenu from the left pane has options to add or
delete breakpoints, etc.
- #<number> -- for instance, #68 specifies
a breakpoint in line 68 of your source code.
NOTE: If you have several program modules, you need
to preface the line number with the module
name. E.g. #hw1#68 refers to line 68 in
- Symbolic names -- for instance, labels can be
specified. If you have have a label called
``repeat'', you can use this as an address.
Write a simple program using the LOOPE command
to read 20 input characters and to store them
in a variable called INPUTS. Note that LOOPE is discussed in
the exercises of Chapter 6. However, you may break out of
the loop early, when a carriage return (CR) is entered.
After the last input character, store a '$' character
(this is the 21st character if all twenty characters
are read, otherwise, the '$' is stored instead of the CR.
Use TD to examine the status flags in this loop.
Above we briefly introduced
the CPU window. You can activate any pane of the CPU window
by left-clicking the pane. The SpeedMenu the activated
pane is then available. We now describe
two of the panes in more detail.
(1) CODE PANE:
There are three display modes in the code pane.
In the SpeedMenu for the Code Pane, the command ``Mixed''
accepts three options: ``No'', ``Yes'' and ``Both''.
The verbose mode is ``Yes'', and shows for each
source code line:
Note that a source code can generate several machine instructions.
For instance, the usual preliminary lines
in the procedure main
of a program called hw1.asm produces the following
information in the code pane:
- the source code line,
- the machine instruction(s),
- and the disassembled code in the same line
Note that the first mov instruction produces
3 bytes of machine instructions (B8B20A), the second
mov instruction produces only two bytes (8ED8).
The offsets of these two instruction in the code
segment (cs register) are 0000 and 0003, respectively.
#hw1#main: mov ax,@data
cs:0000 B8B20A mov ax,0AB2
#hw1#31: mov ds,ax
cs:0003 8ED8 mov ds,ax
Navigating the code pane.
The SpeedMenu in Code Pane has some useful tools
for navigating your code:
Another useful SpeedMenu command is called Assemble.
It allows you to replace the current line of instruction
with any other (single) instruction that you specify.
- Origin: positions you at the location
of the instruction pointer.
- Follow: goes to the destination address
of current highlighted instruction.
Useful only if the current instruction
is a CALL, INT, JMP, JZ, etc.
- Previous: restores the code pane to the
(2) DUMP PANE:
This is a hex display of an area in memory.
The leftmost path of each line shows the
starting address of the line (e.g., ds:0000).
In the default display format (byte format),
you see 8 bytes per line, and to the right of
these 8 bytes are their representation in the
IBM extended character set (which is
an extension of the ASCII set).
You can use the GOTO command in the SpeedMenu
to examine variables (e.g., GOTO Input, assuming you
have defined the variable "Input").
NOTE: There is also a Dump Window which
can be invoked from the View Menu. This gives
the same information as the Dump Pane, except that
it now can be resized. TRY THIS!
In debugging, we often have to copy hex addresses
or transfer chunks of hex information.
Humans tend to make mistakes with such data.
TD has extensive copy and paste facilities to and
from the Clipboard to help in this process.
Hence it is worth your while to learn some tricks for
using the Clipboard.
E.g., if a dialog box pops up and asks
you for some information (e.g., the address of
a breakpoint), it is sometimes possible to paste
this information from the clipboard.
The first thing to realize is that information
on the clipboard are ``objects'', not just inert
data. For instance, if you copy a chunk of
the memory to the clipboard, the address of
that chunk is remembered. When the contents of
these memory locations change, your clipboard contents
changes! Hence, each item in the clipboard
has an associated type, such as:
Furthermore, when we paste an item from the clipboard, there
are three options: to paste it as a
string (if the item is a string),
as a location (if item has an address)
or as contents (for an address item).
Here is how you perform basic clipboard operations:
address: an address, with no associated data
CPU code: address and byte list of data in memory
from the DUMP window
Expression: from the Watches Window
String: a text string
Copying to Clipboard: position the cursor on the item
(or highlight it with the INSERT and arrow keys),
then press SHIFT+F3.
Pasting from Clipboard: press SHIFT+F4 (or use the Clip button
in some dialog box) to bring up the Clipboard's Pick
Viewing the Clipboard contents: choose View->Clipboard menu option.
Bottom of Page
Go to Top of Page