DEBUGGER NOTES: V22.0201.002 (Fall 97)

### V22.0201.002, Machine Organization I, Fall 97

## HOW TO USE THE DEBUGGER

CONTENTS

- Introduction
- Pre-Debugger: Syntax Errors
- The Debugger
- How to Debug
- Mechanics of Using TD
- Some Pulldown Menus
- Breakpoints
- CPU Window
- Clipboard Facilities
- Bottom of page

### Introduction

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 information below. Actually, there are 3 versions of the Turbo 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).

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! HINT: To ask tasm to print out the actual offending instructions, not just their line numbers, do this instead:

    :> tasm /z hw1

### The Debugger

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

    Greeting db 'Hello, World!'

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:

    :> tasm /zi /z hw1
    :> tlink /v hw1
    :> td hw1

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.

### How to Debug

There are 4 basic steps:

1. Discovering the Bug. Is there one? It is not always obvious that you have a bug. (WHY?)
2. Isolating the Bug. Where is it? Locate the part(s) of the code that is causing the bug.
3. Finding the Bug. What exactly is wrong with the buggy code fragment?
4. Fixing the Bug. How should the buggy fragment be rewritten?

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).

### 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).

Overview 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.

TD Windows 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.

Exercise 1 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?

Online Help We already mentioned the Help (pulldown) menu. But there are more ``immediate'' or context-sensitive help available:

1. 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 any key. ]
   If you hold down the CTRL key, you will see the CTRL+key functions.
   [E.g., CTRL+I allows you to inspect the variable that the cursor is currently pointed at.]
2. Function F1 This key opens a help window containing information about the current top window, with further subtopics to choose from.
3. SpeedMenu 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:

1. 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!).
2. 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 is executed). In fact, exercise 1, you probably saw the Module and Watch Windows (the watch window is quite narrow, and you may miss it).
3. CPU Window 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:
   - 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 code pane.
   - 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)
   For more details, see CPU Window below.

Exercise 2 Write a simple program with these instructions (in addition to the usual stuff):

    mov ax,0ffffh
    mov bx,8000h
    neg bx
    add ax,bx

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 Zoom (=F5), Next (=F6), Next pane (=tab), etc. 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:

1. Run (=F9), i.e., until program terminates (or until the next breakpoint). This is the simplest mode.
2. 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, LOOP, etc.
3. 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 function call.
4. Animate (similar to run until terminate, except it pauses between machine instructions to allow you to catch what is happening)
5. Restart (move the instruction pointer back to the first instruction)

Exercise 3 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

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.

1. The location where the breakpoint is set.
2. The condition which allows the breakpoint to activate.
3. The action that takes place when the breakpoint is activated.

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.

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:

- 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, you could also specify more complex types of breakpoint.

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:

- #<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 hw1.asm module.
- Symbolic names -- for instance, labels can be specified. If you have have a label called ``repeat'', you can use this as an address.

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.

Exercise 4 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.

### CPU Window

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:

- the source code line,
- the machine instruction(s),
- and the disassembled code in the same line

Note that a source code can generate several machine instructions. For instance, the usual preliminary lines

    mov ax,@data
    mov ds,ax

in the procedure main of a program called hw1.asm produces the following information in the code pane:

    ...
    #hw1#main: mov ax,@data
      cs:0000 B8B20A	 mov   ax,0AB2
    #hw1#31: mov ds,ax
      cs:0003 8ED8		 mov   ds,ax
    ...

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.

Navigating the code pane. The SpeedMenu in Code Pane has some useful tools for navigating your code:

- 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 previous position.

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.

(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!

### Clipboard Facilities

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:

- 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

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:

- 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 dialog box.
- Viewing the Clipboard contents: choose View->Clipboard menu option.

### Bottom of Page

Go to Top of Page