0% found this document useful (0 votes)
39 views302 pages

Turbo Debugger 3.0 For Windows Users Guide 1991

Uploaded by

josejose45008
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views302 pages

Turbo Debugger 3.0 For Windows Users Guide 1991

Uploaded by

josejose45008
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 302

TURBO

DEBUGGER®3.0
FOR WINDOWS

USER'S GUIDE

BORLAND
...

Turbo Debugger for


Window~

Version 3.0

User's Guide

. BORLAND INTERNATIONAL INC. 1800 GREEN HILLS ROAD


P.O. BOX 660001, SCOTTS VALLEY, CA 95067-0001
Copyright© 1988, 1991 by Borland International. All rights
reserved. All Borland products are trademarks or registered
trademarks of Borland International. Inc. Other brand and
product names are trademarks or registered trademarks of their
respective holders. Windows, as used in this manual, shall refer to
Microsoft's implementation of a windows system.

PRINTED IN THE USA.


Rl 10 9 8 7 6 5 4 3 2 1
c 0 N T E N T s

, !\.1cr..us and dialog bcxe~ ____


Introduction l 1q
New features and changes for version 3.0 . 1 Using the menus . . . . . . . . . . . . . . . . . 19
Hardware and software requirements ... 2 Dialog boxes . . . . . . . . . . . . . . . . . . . . 20
A note on terminology . . . . . . . . . . . . . . . . . 3 Knowing where you are . . . . . . . . . . . . 21
What's in the manual . . . . . . . . . . . . . . . . . . 3 Local menus . . . . . . . . . . . . . . . . . . . . 22
How to contact Borland . . . . . . . . . . . . . . . . 5 History lessons . . . . . . . . . . . . . . . . . . . . 24
Resources in your package . . . . . . . . . . . 5 Automatic name completion . . . . . . . 25
Borland resources . . . . . . . . . . . . . . . . . . . 5 Incremental matching . . . . . . . . . . . . . . 25
Recommended reading . . . . . . . . . . . . . . . . 6 Making macros . . . . . . . . . . . . . . . . . . . . 26
Window shopping . . . . . . . . . . . . . . . . . 26
Chapter 1 Getting started 9 Windows from the View menu . . . . 26
The distribution disks . . . . . . . . . . . . . . . . . 9 Breakpoints window . . . . . . . . . . . 26
Online text files . . . . . . . . . . . . . . . . . . . . . . . 9 Stack window . . . . . . . . . . . . . . . . . 27
The README file . . . . . . . . . . . . . . . . . . 10 Log window . . . . . . . . . . . . . . . . . . 27
The MANUAL.TOW file ............ 10 Watches window .............. 27
The HELPME!.TDW file . . . . . . . . . . . . 10 Variables window . . . . . . . . . . . . . . 27
The ASMDEBUG.TDW file . . . . . . . . . 10 Module window . . . . . . . . . . . . . . . 28
The UTILS. TOW file . . . . . . . . . . . . . . . . 11 File window . . . . . . . . . . . . . . . . . . . 28
Installing TOW . . . . . . . . . . . . . . . . . . . . . . 12 CPU window . . . . . . . . . . . . . . . . . . 28
Installing TDDEBUG.386 . . . . . . . . . . . . 12 Dump window . . . . . . . . . . . . . . . . 28
Hardware debugging ................. 13 Registers window . . . . . . . . . . . . . . 29
Where to now? . . . . . . . . . . . . . . . . . . . . . . 13 Numeric Processor window . . . . . 29
Programmers learning Turbo C++ .... 13 Execution History window . . . . . . 29
Turbo C++ pros, but Turbo Debugger Hierarchy window . . . . . . . . . . . . . 29
novices ........................... 13 Windows Messages window . . . . 30
Programmers experienced with Turbo Clipboard window . . . . . . . . . . . . . 30
Debugger . . . . . . . . . . . . . . . . . . . . . . . . . 14 Duplicate windows . . . . . . . . . . . . 30
Chapter 2 TOW basics 15 User screen . . . . . . . . . . . . . . . . . . . . . 30
Is there a bug? . . . . . . . . . . . . . . . . . . . 15 Inspector windows . . . . . . . . . . . . . . . 31
Where is it? ..................... 16 The active window . . . . . . . . . . . . . . . 31
What is it? . . . . . . . . . . . . . . . . . . . . . . 16 What's in a window . . . . . . . . . . . . . . 32
Fixing it . . . . . . . . . . . . . . . . . . . . . . . . 16 Working with windows . . . . . . . . . . . 33
What TOW can do for you . . . . . . . . . . . . 16 Window hopping . . . . . . . . . . . . . . 33
What TOW won't do . . . . . . . . . . . . . . . 18 Moving and resizing windows . . . 35
How TOW does it . . . . . . . . . . . . . . . . . . 18 Closing and recovering windows . 36
The TOW advantage . . . . . . . . . . . . . . . . . 18 Saving your window layout . . . . . 36
Copying and pasting . . . . . . . . . . . . . . . 36 Starting directory (-t) ............... 63
The Pick dialog box . . . . . . . . . . . . . . 37 Configuration files . . . . . . . . . . . . . . . . . . . 63
The Clipboard window . . . . . . . . . . . 38 The Options menu . . . . . . . . . . . . . . . . . . . 64
Clipboard item types . . . . . . . . . . . 38 The Language command . . . . . . . . . . . . 64
The Clipboard window local The Macros menu.. . . . . . . . . . . . . . . . . . 64
menu ......................... 39 Create .......................... 64
Dynamic updating . . . . . . . . . . . . . 39 Stop Recording . . . . . . . . . . . . . . . . . . 64
Tips for using the Clipboard . . . . . . . 40 Remove ........................ 65
Getting help . . . . . . . . . . . . . . . . . . . . . . . 40 Delete All . . . . . . . . . . . . . . . . . . . . . . . 65
Online help . . . . . . . . . . . . . . . . . . . . . 41 Display Options command . . . . . . . . . . 65
The status line . , . . . . . . . . . . . . . . . . . 42 Display Swapping . . . . . . . . . . . . . . . 65
In a window . . . . . . . . . . . . . . . . . . . 42 Integer Format . . . . . . . . . . . . . . . . . . 66
In a menu or dialog box . . . . . . . . . 42 Screen Lines . . . . . . . . . . . . . . . . . . . . . 66
Tab Size ........................ 66
Chapter 3 A quick example 43 Path for Source command . . . . . . . . . . . 66
The demo program . . . . . . . . . . . . . . . . . . . 43 Save Options command . . . . . . . . . . . . . 66
Using TOW . . . . . . . . . . . . . . . . . . . . . . . . . 45 Restore Options command . . . . . . . . . . 67
The menus . . . . . . . . . . . . . . . . . . . . . . . . 45 Returning to Windows . . . . . . . . . . . . . . . 67
The status line . . . . . . . . . . . . . . . . . . . . . 46
The windows . . . . . . . . . . . . . . . . . . . . . . 46 Chapter 5 Controlling program
Using the C demo program . . . . . . . . . . . . 48 execution 69
Setting breakpoints . . . . . . . . . . . . . . . . . 49 Examining the current program state 70
Using watches . . . . . . . . . . . . . . . . . . . . . 50 The Variables window . . . . . . . . . . . . . . 70
Examining simple C data objects . . . . . 51 The Global pane local menu . . . . . . . 71
Examining compound C data objects . 53 Inspect ....................... 71
Changing C data values . . . . . . . . . . . . . 53 Change ....................... 72
Watch ........................ 72
Chapter 4 Starting TOW 57 The Static pane local menu ....... . 72
Preparing programs for debugging . . . . . 57 Inspect ...................... . 72
Starting TDW . . . . . . . . . . . . . . . . . . . . . . . 58 Change ...................... . 72
Entering command-line options ...... 59 Watch ....................... . 73
Directly entering command-line Show ........................ . 73
options ............... , ......... 59 The Stack window ................ . 73
Entering command-line options from The Stack window local menu ..... 74
TCW ........................... 59 Inspect ...................... . 74
Things to remember . . . . . . . . . . . . . . 60 Locals ...................... .. 74
Running TOW . . . . . . . . . . . . . . . . . . . . . . . 60 The Origin local menu command ... . 75
Command-line options . . . . . . . . . . . . . . . 60 The Get Info command ............ . 75
Loading the configuration file (-c) .... 61 Global memory information ...... . 75
Display updating (-d) . . . . . . . . . . . . . . . 61 Status line messages ............. . 76
Getting help (-hand-?) . . . . . . . . . . . . . 61 The Run menu ...................... . 78
Assembler-mode startup (-1) . . . . . . . . . 62 Run ............................. . 78
Mouse support (-p) ................. 62 Go to Cursor ..................... . 78
Source code handling (-s) ........... 62 Trace Into ........................ . 78
Step Over . . . . . . . . . . . . . . . . . . . . . . . . . 79 Pointers . . . . . . . . . . . . . . . . . . . . . . . . 98
Execute To . . . . . . . . . . . . . . . . . . . . . . . . 79 Arrays .......................... 99
Until Return ....................... 79 Structures and unions . . . . . . . . . . . 100
Animate .......................... 80 The Inspector window local menu . . . . . 100
Back Trace ........................ 80 Range ........................... 101
Instruction Trace ................... 80 Change .......................... 101
Arguments ...... , . . . . . . . . . . . . . . . . 81 Inspect . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Program Reset ..................... 81 Descend ................ ; ........ 101
The Execution History window . . . . . . . . 81 New Expression .................. 102
The local menu . . . . . . . . . . . . . . . . . . . . 82 Type Cast . . . . . . . . . . . . . . . . . . . . . . . . 102
Inspect ....................... 82
Reverse Execute ............... 82 Chapter 7 Breakpoints 103
Full History . . . . . . . . . . . . . . . . . . . 83 The Breakpoints menu . . . . . . . . . . . . . . . 104
Interrupting program execution . . . . . . . . 83 Toggle ......................... 105
Program termination . . . . . . . . . . . . . . . . . 84 At ............................ 105
Restarting a debugging session . . . . . . . . 85 Changed memory global . . . . . . . . . 105
Opening a new program to debug . . . . . . 85 Expression true global . . . . . . . . . . . 105
Changing the program arguments . . . . . . 86 Hardware breakpoint . . . . . . . . . . . . 105
Delete all . . . . . . . . . . . . . . . . . . . . . . 105
Chapter 6 Examining and modifying The Breakpoints window . . . . . . . . . . . . 105
data 87 The Breakpoints window local menu . 106
The Data menu . . . . . . . . . . . . . . . . . . . . . . 88 Set Options . . . . . . . . . . . . . . . . . . . . 106
Inspect .......................... . 88 Add ........................... 106
Evaluate/Modify ................. . 88 Remove ....................... 107
Add Watch ....................... . 91 Delete all . . . . . . . . . . . . . . . . . . . . . . 107
Function Return .................. . 91 Inspect . . . . . . . . . . . . . . . . . . . . . . . . 107
Pointing at data objects in source files .. . 91 Group ......................... 107
The Watches window ................ . 92 Groups ...................... 108
The Watches window local menu ... . 93 Add ......................... 108
Watch ......................... . 93 Delete ....................... 109
Edit ........................... . 93 Enable ....................... 109
Remove ....................... . 93 Disable ...................... 109
Delete All ...................... . 93 The Breakpoint Options dialog box . . 109
Inspect ............. , .......... . 93 Address . . . . . . . . . . . . . . . . . . . . . . . 110
Change ........................ . 94 Group ID .. .. . .. . .. .. .. . .. .. . .. 110
Inspector windows .................. . 94 Global ......................... 110
C data Inspector windows .......... . 95 Disabled ....................... 110
Scalars ......................... . 95 Conditions and Actions . . . . . . . . . . 111
Pointers ....................... . 95 Change ........................ 111
Structures and unions ........... . 96 Add ........................... 111
Arrays ......................... . 97 Delete ......................... 111
Functions ...................... . 97 The Conditions and Actions dialog
Assembler data Inspector windows .. . 98 box ............................. 111
Scalars ......................... . 98 The condition radio buttons . . . . . . 112

iii
Always ...................... 112 Previous . . . . . . . . . . . . . . . . . . . . . . . 126
Changed memory . . . . . . . . . . . . . 112 Line ........................... 126
Expression true . . . . . . . . . . . . . . . 112 Search ......................... 126
Hardware . . . . . . . . . . . . . . . . . . . . 112 Next .......................... 127
The action radio buttons . . . . . . . . . 113 Origin ......................... 127
Break ........................ 113 Goto .......................... 127
Execute . . . . . . . . . . . . . . . . . . . . . . 113 Examining other disk files ............ 127
Log ......................... 113 The File window . . . . . . . . . . . . . . . . . . 127
Enable group . . . . . . . . . . . . . . . . . 113 The File window local menu . . . . . . . . 128
Disable group . . . . . . . . . . . . . . . . 113 Goto .......................... 129
Setting conditions and actions . . . . 114 Search ......................... 129
Condition Expression . . . . . . . . . . . . 114 Next .......................... 130
Action Expression ............... 115 Display As . . . . . . . . . . . . . . . . . . . . . 130
Pass count . . . . . . . . . . . . . . . . . . . . . 115 File ........................... 130
Customizing breakpoints ............ 116
Simple breakpoints ................ 116 Chapter 9 Expressions 131
Global breakpoints . . . . . . . . . . . . . . . . 116 Choosing the language for expression
Changed memory breakpoints . . . . . . 117 evaluation . . . . . . . . . . . . . . . . . . . . . . . . . 132
Conditional expressions . . . . . . . . . . . 118 Code addresses, data addresses, and line
Scope of breakpoint expressions . . 118 numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Hardware breakpoints . . . . . . . . . . . . . 118 Accessing symbols outside the current
Logging variable values . . . . . . . . . . . . 119 scope .............................. 133
Breakpoints and templates . . . . . . . . . 119 Scope override syntax ............. 134
Breakpoints on class templates . . . . 119 Overriding scope in C, C++, and
Breakpoints on function templates . 120 assembler programs . . . . . . . . . . . . . 134
Breakpoints on template class Scope override tips . . . . . . . . . . . . 136
instances and objects . . . . . . . . . . . . 120 Overriding scope in Pascal
The Log window . . . . . . . . . . . . . . . . . . . . 120 programs . . . . . . . . . . . . . . . . . . . . . . 137
The Log window local menu . . . . . . . 121 Scope override tips . . . . . . . . . . . . 138
Open Log File . . . . . . . . . . . . . . . . . . 121 Scope and DLLs . . . . . . . . . . . . . . . . 138
Close Log File . . . . . . . . . . . . . . . . . . 122 Implied scope for expression
Logging ....................... 122 evaluation . . . . . . . . . . . . . . . . . . . . . . . 139
Add Comment . . . . . . . . . . . . . . . . . 122 Byte lists . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Erase Log . . . . . . . . . . . . . . . . . . . . . . 122 C expressions . . . . . . . . . . . . . . . . . . . . . . 140
Display Windows Info . . . . . . . . . . . 122 C symbols . . . . . . . . . . . . . . . . . . . . . . . 140
C register pseudovariables . . . . . . . . . 140
Chapter 8 Examining files 123 C constants and number formats .... 142
Examining program source files . . . . . . . 123 Escape sequences ................. 142
The Module window . . . . . . . . . . . . . . 124 C operator precedence . . . . . . . . . . . . . 143
The Module window local menu . . . . 125 Executing C functions in your pro-
Inspect . . . . . . . . . . . . . . . . . . . . . . . . 125 gram ............................ 144
Watch ......................... 125 C expressions with side effects ...... 144
Module ........................ 126 C reserved words and type
File ........................... 126 conversion . . . . . . . . . . . . . . . . . . . . . . . 145

iv
Assembler expressions .............. . 146 Chapter 11 Using Windows debugging
Assembler symbols ............... . 146 features 157
Assembler constants 146 Windows features . . . . . . . . . . . . . . . . . . . 157
Assembler operators . : : : : : : : : : : : : : : 147 Logging window messages . . . . . . . . . 158
Format control ..................... . 147 Selecting a window for a standard
Chapter 1O Object-oriented Windows application . . . . . . . . . . . . 158
Adding a window selection for a
debugging 149
standard Windows aoolication 159
The Hierarchy window . . . . . . . . . . . . . . i 49
Selecting a window for ·a~ .
The Class List pane . . . . . . . . . . . . . . . . 150
ObjectWindows application . . . . . . 159
The Class List pane local menu . . . 150
Obtaining a window handle . . . . 159
Inspect ...................... 150
Specifying a window with
Tree ......................... 151
ObjectWindows support
The Hierarchy Tree pane . . . . . . . . . . . 151
enabled . . . . . . . . . . . . . . . . . . . . . . 160
The Hierarchy Tree pane local
Adding a window with
menu(s) . . . . . . . . . . . . . . . . . . . . . . . 151
ObjectWindows support
The Parent Tree pane . . . . . . . . . . . . . . 151
enabled ...................... 161
The Parent Tree pane local menu . . 152
Deleting a window selection . . . . . . 162
Class Inspector windows . . . . . . . . . . . . . 152
Specifying a message class and
The class Inspector window local
action ......................... 162
menus ........................... 153
Adding a message class . . . . . . . . 162
The Data Member (top) pane 153
Deleting a message class . . . . . . . 164
Inspect ...................... 153
Window message tips . . . . . . . . . 165
Hierarchy .................... 153
Viewing messages . . . . . . . . . . . . . . 165
Show Inherited . . . . . . . . . . . . . . . 153
Obtaining memory and module lists. 166
The Member Function (bottom)
Listing the contents of the global
pane .......................... 154
heap .......................... 166
Inspect ...................... 154
Listing the contents of the local
Hierarchy . . . . . . . . . . . . . . . . . . . . 154
heap .......................... 168
Show Inherited . . . . . . . . . . . . . . . 154
Obtaining a list of modules ....... 168
Object Inspector windows . . . . . . . . . . . . 154
Debugging dynamic link libraries
The object Inspector window local
(DLLs) .......................... 169
menus ........................... 155
Using the Load Modules or DLLs
Range ......................... 155
dialog box ..................... 170
Change ........................ 155
Changing source modules . . . . . . 170
Methods . . . . . . . . . . . . . . . . . . . . . . . 155
Working with DLLs and
Show Inherited . . . . . . . . . . . . . . . . . 156
programs .................... 171
Inspect . . . . . . . . . . . . . . . . . . . . . . . . 156
Adding a DLL to the DLLs &
Descend . . . . . . . . . . . . . . . . . . . . . . . 156
Programs list . . . . . . . . . . . . . . . . . . . 172
New Expression ................ 156
Setting debug options in a DLL ... 173
Type Cast . . . . . . . . . . . . . . . . . . . . . . 156
Controlling TDW's loading of DLL
Hierarchy . . . . . . . . . . . . . . . . . . . . . . 156
symbol tables ................... 173
The middle and bottom panes . . . . . . 156
Debugging DLL startup code ..... 173

v
Converting memory handles to Instructions pane . . . . . . . . . . . . . . . 194
addresses . . . . . . . . . . . . . . . . . . . . . . . . 175 File window . . . . . . . .. . . . . . . .. . . . . . 194
Log window menu . . . . . . . . . . . . . . . . 194
Chapter 12 Assembler-level Module window . . . . . . . . . . . . . . . . . . 195
debugging 177 Windows Messages window . . . . . . . 195
When source debugging isn't enough . . 177 Window Selection pane . . . . . . . . . . 195
The CPU window . . . . . . . . . . . . . . . . . . . 178 Message Class pane . . . . . . . . . . . . . 196
The Code pane . . . . . . . . . . . . . . . . . . . . . 180 Messages pane . . . . . . . . . . . . . . . . . 196
The disassembler . . . . . . . . . . . . . . . . . 180 Clipboard window . . . . . . . . . . . . . . . . 196
The Register and Flags panes . . . . . . . . . 181 Numeric Processor window . . . . . . . . 197
The Selector pane . . . . . . . . . . . . . . . . . . . 181 Register pane . . . . . . . . . . . . . . . . . . . 197
The Selector pane local menu ....... 182 Status pane . . . . . . . . . . . .. . . . . . . . 197
Selector . . . . . . . . . . . . . . . . . . . . . . . . 182 Control pane . . . . . . . . . . . . . . . . . . . 197
Examine . . . . . . . . . . . . . . . . . . . . . . . 182 Hierarchy window . . . . . . . . . . . . . . . . 197
The Data pane . . . . . . . . . . . . . . . . . . . . . . 183 Class pane . . . . . . . . . . . . . . . . . . . . . 197
The Stack pane . . . . . . . . . . . . . . . . . . . . . 183 Hierarchy Tree pane ............. 198
The Dump window . . . . . . . . . . . . . . . . . 184 Parent Tree pane . . . . . . . . . . . . . . . . 198
The Registers window . . . . . . . . . . . . . . . 184 Registers window menu . . . . . . . . . . . 198
Chapter 13 Command reference 185 Stack window . . . . . .. . . . . . . . . . . . . . 198
Hot keys . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Variables window .. . . . . . . . . . . . . . . . 198
Commands from the menu bar . . . . . . . 187 Global Symbol pane . . . . . . . . . . . . . 198
The = (System) menu . . . . . . . . . . . . . . 187 Local Symbol pane . ; . . . . . . . . . . . . 199
The File menu . . . . . . . . . . . . . . . . . . . . 187 Watches window ................. 199
The Edit menu . . . . . . . . . . . . . . . . . . . . 188 Inspector window . . . . . . . . . . . . . . . . . 200
The View menu . . . . . . . . . . . . . . . . . . . 188 Class Inspector window . . . . . . . . . . . 200
The Run menu . . . . . . . . . . . . . . . . . . . . 189 Object Inspector window . . . . . . . . . . 200
The Breakpoints menu . . . . . . . . . . . . . 189 Text panes ......................... 201
The Data menu . . . . . . . . . . . . . . . . . . . 189 List panes . . . . . . . . . . . . . . . . . . . . . . . . . . 202
The Options menu . . . . . . . . . . . . . . . . 189 Commands in input and history list
The Window menu . . . . . . . . . . . . . . . . 190 boxes .............................. 202
The Help Menu . . .. . .. . . . . . . . . . . . . 190 Window movement commands . . . . . . . 203
The local menu commands . . . . . . . . . . . 190 Wildcard search templates . . . . . . . . . . . 204
Breakpoints window . . . . . . . . . . . . . . 191 Complete menu tree . . . . . . . . . . . . . . . . . 204
The CPU window menus . . . . . . . . . . 191 Chapter 14 Debugging a standard C
Code pane . . . . . . . . . . . . . . . . . . . . . 191 application 207
Selector pane . . . . .. . .. . . .. . . . .. . 192 When things don't work ... ~ . . . . . . . . . 207
Data pane . . . . . . . . . . . . . . . . . . . . . . 192 Debugging style . . . . . . . . . . . .. . . . . . . . 208
Flags pane . . . . . . . . . . . . . . . . . . . . . 193 Run the whole thing . . . . . . . . . . . . . . . 209
Register pane . . . . . . . . . . . . . . . . . . . 193 Incremental testing . . . . . . . . . . . . . . . . 209
Stack pane . . .. .. . .. . . . . . . . . .. . . 193 Types of bugs . . . . . . . . . . . . . . . . . . . . . . 209
Dump window ................... 194 General bugs . . . . . . . . . . . . . . . . . . . . . 210
The Execution History window Hidden effects . . . . . . . . . . . . . . . . . . 210
menus ........................... 194 Assuming initialized data ........ 210

vi
Not cleaning up . . . . . . . . . . . . . . . . 210 WMRButtonDown . . . . . . . . . . . . . . 226
Fencepost errors . . . . . . . . . . . . . . . . 211 WMMouseMove . . . . . . . . . . . . . . . . 226
C-specific bugs . . . . . . . . . . . . . . . . . . . 211 The pen-color routines . . . . . . . . . . . 226
Using uninitialized automatic Creating the application . . . . . . . . . . . 226
variables . . . . . . . . . . . . . . . . . . . . . . . 211 Debugging the program . . . . . . . . . . . . . 227
Confusing= and== ............. 212 Finding the first bug . . . . . . . . . . . . . . . 227
Confusing operator precedence ... 212 Finding the function that called
Bad pointer arithmetic . . . . . . . . . . . 212 Windows . . . . . . . . . . . . . . . . . . . . . . 227
Unexpected sign extension ....... 213 Debugging wMLButtonDown . . . . 228
Unexpected truncation . . . . . . . . . . . 213 Debugging MoveTo . . . . . . . . . . . . . 228
Misplaced semicolons . . . . . . . . . . . 213 Fixing the bug . . . .. . . . . . . . . . . . . . 229
Macros with side effects . . . . . . . . . 214 Testing the fix .................. 229
Repeated autovariable names ..... 214 Finding the pen color bug . . . . . . . . . . 230
Misuse ofautovariables .......... 214 Setting a window message
Undefined function return value .. 214 breakpoint . . . . . . . . . . . . . . . . . . . . . 230
Misuse of break keyword . . . . . . . . 215 Setting a window message
Code has no effect . . . . . . . . . . . . . . . 215 breakpoint with a handle ...... 231
Accuracy testing .................... 215 Setting a window message
Testing boundary conditions . . . . . . . 216 breakpoint with a window
Invalid data input . . . . . . . . . . . . . . . . . 216 object ........................ 232
Empty data input .. . . . . . .. . . . . . .. . 216 Inspecting wParam . . . . . . . . . . . . . . 233
Debugging as part of program design . . 216 Testing the fix . . . . . . . . . . . . . . . . . . 234
The sample debugging session ........ 217 Finding the off-screen drawing bug 234
Looking for errors . . . . . . . . . . . . . . . . . 217 Logging the window messages . . . 234
Deciding your plan of attack . . . . . . . . 218 Discovering the bug . . . . . . . . . . . . . 234
Starting Turbo Debugger . . . . . . . . . . . 218 Fixing the bug . . .. . . . . . . . . . . . . . . 235
Inspecting . . . . . . . . . . . . . . . . . . . . . . . 219 Testing the fix .................. 236
Breakpoints . . . . . . . . . . . . . . . . . . . . . . 219 Finding the erase-screen bug . . . . . . . 236
The Watches window . . . . . . . . . . . . . . 220 Analyzing the cause of the bug . . . 237
The Evaluate/Modify dialog box . . . . 220 Fixing the bug . . .. . . . . . . . . . . . . . . 238
Eureka! . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Testing the fix . . . . . . . . . . . . . . . . . . 238
Chapter 15 Debugging an Appendix A Summary of command-line
ObjectWindows options 239
application 223
Appendix B Error and information
About the program . . . . . . . . . . . . . . . . . . 223
messages 241
The Color Scribble window type
Dialog box messages . . . . . . . . . . . . . . . . 241
definition . . . . . . . . . . . . . . . . . . . . . . . . 224
Error messages . . . . . . . . . . . . . . . . . . . . . 248
ScribbleWindow ................ 225
Fatal errors . . . . . . . . . . . . . . . . . . . . . . . 248
GetWindowClass . . . . . . . . . . . . . . . 225
Other error messages . . . . . . . . . . . . . . 249
WMLButtonDown . . . . . . . . . . . . . . 226
WMLButtonUp . . . . . . . . . . . . . . . . . 226 Index 263

vii
T A B L E s

2.1: What goes in a dialog box ........... 21 13.1: The function key and hot key
2.2: Clipboard item types ............... 38 commands ...................... 186
2.3: Clipboard local menu commands .... 39 13.2: Text pane key commands ......... 201
11.l: Windows message classes ........ 163 13.3: List pane key commands ......... 202
11.2: Fonnat of a global heap list ....... 167 13.4: Dialog box key commands ........ 203
11.3: Format of a local heap list ........ 168 13.5: Window movement key
11.4: Format of a Windows module list .. 169 commands ..................... 203
11.5: DLLs & Programs list dialog box A.1: TOW command-line options ....... 239
controls ........................ 171

viii
F G u R E s

2.1: Glabal and local menus __ - .. 23 6.4: A C pointer Inspector window ...... 96
2.2: A history list in an input box ........ 24 6.5: A C structure or union Inspector
2.3: The active window has a double window .......................... 97
outline ........................... 32 6.6: A C array Inspector window ........ 97
2.4: A typical window ................. 32 6.7: A C function Inspector window ..... 98
2.5: The Pick dialog box ................ 37 6.8: An assembler scalar Inspector
2.6: The Clipboard window ............. 38 window .......................... 98
2.7: The normal status line .............. 42 6.9: An assembler pointer Inspector
2.8: The status line with Alt pressed ...... 42 window .......................... 99
2.9: The status line with Ctr/ pressed ..... .42 6.10: An assembler array Inspector
3.1: The startup screen showing window ........................ 100
TDDEMO ........................ 44 6.11: An assembler structure Inspector
3.2: The menu bar ..................... 45 window ........................ 100
3.3: The status line ................... .46 7.1: The Breakpoints window .......... 106
3.4: The Module and Watches windows, 7.2: The Edit Breakpoint Groups dialog
tiled ............................. 47 box ............................. 108
3.5: Program stops on return from 7.3: The Add Group dialog box ........ 108
function showargs ................. 49 7.4: The Breakpoint Options dialog box . 110
3.6: A breakpoint at line 44 ............. 50 7.5: The Conditions and Actions dialog
3.7: AC variable in the Watches window .51 box ............................. 111
3.8: An Inspector window .............. 52 7.6: The Log window ................. 120
3.9: Inspecting a structure .............. 53 8.1: The Module window .............. 124
3.10: The Change dialog box ............ 54 8.2: The File window ................. 128
3.11: The Evaluate/Modify dialog box ... 55 8.3: The File window showing hex data . 128
4.1: The Display Options dialog box ..... 65 10.1: The Hierarchy window ........... 149
4.2: The Save Options dialog box ........ 67 10.2: A class Inspector window ........ 152
5.1: The Variables window ............. 70 10.3: An object Inspector window ...... 155
5.2: The Local Display dialog box ........ 73 11.1: The Windows Messages window for
5.3: The Stack window ................. 74 a standard Windows application ... 158
5.4: The Get Info text box ............... 75 11.2: The Add Window dialog box for a
5.5: The Execution History window ...... 82 standard Windows application .... 159
5.6: The Enter Program Name to Load 11.3: The Windows Messages window with
dialog box ........................ 85 ObjectWindows support enabled .. 161
6.1: The Evaluate/Modify dialog box .... 89 11.4: The Add Window dialog box with
6.2: The Watches window .............. 92 ObjectWindows support enabled .. 162
6.3: A C scalar Inspector window ........ 95 11.5: The Set Message Filter dialog box .. 163

ix
11.6: The Windows Information dialog 12.1: The CPU window ............... 178
box ............................ 166 12.2: The Dump window .............. 184
11.7: The Load Modules or DLLs dialog 12.3: The Registers window ........... 184
box ............................ 170 13.1: The Turbo Debugger menu tree ... 205

x
N T R 0 D u c T 0 N

Turbo Debugger for Windows (TOW) is a state-of-the-art, source-


level debugger designed to work with Turbo C++ for Windows.
Multiple, overlapping windows, a combination of pull-down and
pop-up menus, and mouse support provide a fast, interactive
environment. An online context-sensitive help system provides
you with help during all phases of operation.
Here are just some of TDW's features:
• debugging of Microsoft Windows applications
•full C, C++, and assembler expression evaluation
•reconfigurable screen layout
•assembler /CPU access when needed
• powerful breakpoint and logging facility
•back tracing
•full support for object-oriented programming in Turbo C++ for
Windows
•operates in character mode

New features and changes for version 3.0


For version 3.0, TOW has the following enhancement:
• The Clipboard lets you copy from windows and paste either
into text entry boxes on dialog boxes or into other windows.
This feature is described on page 36.
•There are new breakpoint features (see Chapter 7) that let you
• set multiple conditions and actions on a breakpoint
•set and remove breakpoints in groups

Introduction
•set and remove breakpoints on all functions or procedures in
a module
• set and remove breakpoints on all methods in an object type
or all member functions in a class
• C++ templates and nested classes are supported (see page 119).
•International sort orders are supported through the Windows
Language setting. You turn this feature on by using the configu-
ration program TDWINST.EXE (see the file TDWINST.DOC).
• The CPU window has a new pane that shows protected mode
selectors and lets you look at the contents of memory locations
referenced by these selectors (see page 181).
•The device driver TDDEBUG.386 provides support for Ctrl-Alt-
SysRq program. In addition, this device driver supports the
hardware debug registers of the Intel 83086 processor (and
higher). See page 12 for TDDEBUG.386 installation information.
See page 118 and the online file HDWDEBUG.TDW for
information on hardware debugging.
• Debugging of DLLs is faster now that TOW simultaneously
loads both the application's symbol table and the symbol table
of any DLL you explicitly load or whose code you step into (see
page 138).

Hardware and software requirements


TOW has the same hardware and system software requirements
as Turbo C++ for Windows.
TOW supports Super VGA video through the use of a DLL named
TDVIDEO.DLL. A number of DLLs are distributed with TOW
that support different Super VGA cards (described in the
README file on your distribution diskettes). To use one of these
DLLs with TOW, copy it to the same directory that TOW.EXE is in
and name it TDVIDEO.DLL.
See page 5 to find out how If you can't find a DLL that matches your Super VGA video
to contact Borland.
adapter, contact Borland Technical Support.
To use TOW, you must have Turbo C++ for Windows. You must
already have compiled your source code into an executable (.EXE
file) with full debugging information turned on.

2 Turbo Debugger for Windows User's Guide


¢ When you run TOW, you'll need both the .EXE file and the
original source files. TOW searches for source files first in the
directory where the compiler found them when it compiled,
second in the directory specified in the Options I Path for Source
command, third in the current directory, and fourth in the
directory the .EXE file is in.

A note on terminology
For convenience and brevity, we use two terms in this manual in
slightly more generic ways than usual. These terms are module
and argument.
Module Refers to what is usually called a module in C++ and assembler,
but also to what is called a unit in Pascal.
Argument Is used interchangeably with parameter in this manual. This
applies to references to command-line arguments (or parameters),
as well as to arguments (or parameters) passed to functions.

What's in the manual


Here is a brief synopsis of the chapters and appendixes in this
manual:
Chapter 1: Getting started describes the contents of the distri-
bution disk and tells you how to load TOW files into your system.
It also gives you advice on which chapter to go to next, depending
on your level of expertise.
Chapter 2: TOW basics explains the TOW environment, menus,
and windows, and shows you how to respond to prompts and
error messages.
Chapter 3: A quick example leads you through a sample session-
using a C program-that demonstrates many of the powerful
capabilities of TOW.
Chapter 4: Starting TOW shows how to run the debugger from the
command line, when to use command-line options, and how to
record commonly used settings in configuration files.

Introduction 3
Chapter 5: Controlling program execution demonstrates the
various ways of starting and stopping your program, as well as
how to restart a session or replay the last session.
Chapter 6: Examining and modifying data explains the unique
capabilities TOW has for examining and changing data inside
your program.
Chapter 7: Breakpoints introduces the concept of actions, and
how they encompass the behavior of what are sometimes referred
to as breakpoints, watchpoints, and tracepoints. Both conditional
and unconditional actions are explained, as well as the various
things that can happen when an action is triggered.
Chapter 8: Examining files describes how to examine program
source files, as well as how to examine arbitrary disk files, either
as text or binary data.
Chapter 9: Expressions describes the syntax of C and assembler
expressions accepted by the debugger, as well as the format
control characters used to modify how an expression's value is
displayed.
Chapter 10 Object-oriented debugging explains the debugger's
special features that let you examine objects in Turbo C++ for
Windows.
Chapter 11: Using Windows debugging features describes how to
use the TOW features that support debugging of Windows
applications.
Chapter 12: Assembler-level debugging describes the CPU
window. Additional information about this window and about
assembler-level debugging is in the file ASMOEBUG.TOW.
Chapter 13: Command reference is a complete listing of all main
menu commands and all local menu commands for each window
type.
Chapter 14: Debugging a standard C application is an intro-
duction to strategies for effective debugging of your programs.
Chapter 15: Debugging an ObjectWindows application leads you
through a debugging session on a sample Windows program
written using the ObjectWindows class library.
Appendix A: Summary of command-line options summarizes all
the command-line options described in Chapter 4.

4 Turbo Debugger for Windows User's Guide


Appendix B: Error and information messages lists all the TOW
prompts and error messages that can occur, with suggestions on
how to respond to them.

How to contact Borland


Boriand offers a variety of services to answer your qucstior.s
about this product. Be sure to send in the registration card;
registered owners are entitled to technical support and may
receive information on upgrades and supplementary products.

Resources in your
package This product contains many resources to help you:
• The manuals provide information on every aspect of the
program. Use them as your main information source.
•While using the program, you can press Ft for help.
• Some common questions are answered in the file
HELPME!.TDW, located in the DOC subdirectory of your
language compiler directory, and the README file, located in
the main language compiler directory.

Borland resources
Borland Technical Support publishes technical information sheets
on a variety of topics and is available to answer your questions.
800-822-4269 (voice) TechFax is a 24-hour automated service that sends free technical
TechFax
information to your fax machine. You can use your touch-tone
phone to request up to three documents per call.
408-439-9096 (modem) The Borland File Download BBS has sample files, applications,
File Download BBS
2400Baud
and technical information you can download with your modem.
No special setup is required.
Subscribers to the CompuServe, GEnie, or BIX information
services can receive technical support by modem. Use the
commands in the following table to contact Borland while
accessing an information service.

Introduction 5
Online information services
Service Command
CompuServe GO BORLAND
BIX JOIN BORLAND
GEnie BORLAND

Address electronic messages to Sysop or All. Don't include your


serial number; messages are in public view unless sent by a
service's private mail system. Include as much information on the
question as possible; the support staff will reply to the message
within one working day.
408-438-5300 (voice) Borland Technical Support is available weekdays from 6:00 a.m.
Technical Support to 5:00 p.m. Pacific time to answer any technical questions you
6 a.m. to 5 p.m. PST
have about Borland products. Please call from a telephone near
your computer, and have the program running. Keep the
following information handy to help process your call:
•product name, serial number, and version number
•the brand and model of any hardware in your system
•operating system and version number (use the DOS command
VER to find the version number)
•contents of your AUTOEXEC.BAT and CONFIG.SYS files
(located in the root directory (\) of your computer's boot disk)
•the contents of your WIN.INI and SYSTEM.IN! files (located in
your Windows directory) for TDW questions
•a daytime phone number where you can be contacted
•if the call concerns a problem, the steps to reproduce the
problem
408-438-5300 (voice) Borland Customer Service is available weekdays from 7:00 a.m. to
Customer Service 5:00 p.m. Pacific Time to answer any nontechnical questions you
7 a.m. to 5 p.m. PST
have about Borland products, including pricing information,
upgrades, and order status.

Recommended reading
The manuals accompanying your language compiler contain
excellent information on programming Windows applications.
The Help system also has a complete Windows API reference.

6 Turbo Debugger for Windows User's Guide


In addition, the following books on programming for Windows
might be helpful to you, although they don't take into account the
ObjectWindows library or Resource Workshop, both of which
make Windows programming much easier than these books
indicate:
Microsoft staff. Microsoft Windows Software Development Kit, Guide
to Programming, Microsoft Corporation. (Redmond, WA: 1990).
~1icrosoft staff. ."Aicrosoft
. Wind07..t'S Softu are De! elapment Kit
1 1

Reference, Vols. 1and2, Microsoft Corporation. (Redmond, WA:


1990).
Microsoft staff. Microsoft Windows Software Development Kit, Tools,
Microsoft Corporation. (Redmond, WA: 1990).
Petzold, Charles. Programming Windows, Microsoft Press.
(Redmond, WA: 1990).

Introduction 7

__ , _____ - - - -
8 Turbo Debugger for Windows User's Guide
c H A p T E R

Getting started
See the FILELIST.DOC file for Turbo Debugger for Windows is part of the Turbo C++ for
information about the online
Windows package, which consists of a set of distribution disks,
files that document subjects
not covered in this manual. the Turbo Debugger for Windows User's Guide (this manual), and the
Turbo C++ for Windows manuals. The distribution disks contain
all the programs, files, and utilities needed to debug programs
written in Turbo C ++ for Windows.
The Turbo Debugger for Windows User's Guide provides a subject-
by-subject introduction of TDW's capabilities and a complete
command reference.

The distribution disks


When you install Turbo C++ for Windows on your system, files
from the distribution disks, i)1cluding the TDW files, are copied to
your hard disk. Just run INST ALL.EXE, the easy-to-use installa-
tion program on your distribution disks.
For a list of the files on the distribution disks, see the
FILELIST.DOC file on the installation disk.

Online text files


There are a number of online files the installation program puts
on your hard disk. The three you should definitely look at are

Chapter 7, Getting started 9


README, FILELIST.DOC, and MANUAL.TDW. The first two are
accessible on the disk labeled "Installation Disk," and are also
copied to your main language directory. The other is in the DOC
subdirectory of the main language directory, along with files
describing TDW features.
Additional files that provide information not found in the manual
are UTILS.TDW (descriptions of utilities), HDWDEBUG.TDW
(hardware debugging), ASMDEBUG.TDW (debugging of
Assembler programs), and TDWINST.TDW (configuring TDW
using TDWINST.TDW).

The README file


You can use the Turbo C++ It's very important that you take the time to look at the README
for Windows editor or the
file before you do anything else with TDW. This file contains last-
Windows Notepad program
to access the README file. minute information that might not be in the manual.

The MANUAL.TOW
file After installation, the\ TCW\DOC directory on your hard disk
also contains a file called MANUAL.TDW that indicates
corrections and additions to the TDW manual. Be sure to consult
this file before making extensive use of the manual.

The HELPME!.TDW
file Your installation disk also contains a file called HELPME!.TDW,
which contains answers to problems that users commonly run
into. Consult it if you find yourself having difficulties. The
HELPME!.TDW file discusses:
• the syntactic and parsing differences between TDW and Turbo
C ++ for Windows
•debugging multi-language programs with TDW
• common questions about using TDW with Windows

The
ASMDEBUG.TDW This file contains information on debugging Turbo Assembler
programs. You might also find the information in this file helpful
file
for debugging your inline assembler code.

10 Turbo Debugger for Windows User's Guide


The UTILS.TDW file
This file describes the command-line utilities included with TDW.
These utility programs are TDWINST, TDSTRIP, and TDUMP.
Here's a brief description of each of the TDW utilities:
• TDWINST.EXE lets you customize TDW. Using this utility, you
can permanently set such things as the display options and
c:::creen colorc:::
• TDSTRIP.EXE lets you strip the debugging information (the
symbol table) from your programs without relinking. You can
perform this operation with a .COM file and save the stripped
symbol table information in a .TDS file to use in debugging the
.COM file.
Use TDSTRIP to prepare A typical use of this utility is to create a .TDS file to use in
.COM files for debugging.
debugging a .COM file. Because a .COM file you produce with
a compiler has no symbol table information in it, you can debug
it only by doing the following:
Compile the source code, with debugging information turned
on, into a single-segment .EXE file, then run TDSTRIP on the
.EXE. If the .EXE can be converted to a .COM file, TDSTRIP
produces a .TDS file and a .COM file. You can now debug the
.COM file by using the .TDS file with it.
• TDUMP.EXE displays the contents of object modules and .EXE
files in a readable format.
¢ For a list of all the command-line options available for the TDW
utility programs TDSTRIP.EXE and TDUMP.EXE, just type the
program name and press Enter. For example, to see the command-
line options for TDUMP.EXE, you'd type
TD UMP

To see the command-line options for TDWINST.EXE, type the


program name and use the -? or -h option, then press Enter. For
example, you would type
TDWINST -?

Chapter 7, Getting started 11


Installing TDW
The INSTALL.EXE program for Turbo C++ for Windows also
installs TDW. It creates a program group in the Windows
program manager and creates icons for Turbo C++ for Windows
and TDW. See the README file for general installation
information.

Installing
TDDEBUG.386 There's a file on your installation disks, TDDEBUG.386, that
provides the same functionality as the Windows SDK file
WINDEBUG.386. In addition, it provides support for the
hardware debugging registers of Intel 80386 (and higher)
processors.
The installation program should copy this file to your hard disk
and alter your Windows SYSTEM.IN! file so that Windows loads
TDDEBUG.386 instead of WINDEBUG.386. If the installation
program can't complete this task for you, it tells you. You then
have to do it by hand, as follows:

1. The installation program will have copied TDDEBUG.386


from the installation disks to your hard disk. The standard
directory for this file is C: \ TCW\ BIN. If you move the file to
another directory, substitute that directory in the instructions.
2. With an editor, open the Windows SYSTEM.IN! file, search for
[386enh], and add the following line to the 386enh section:
device=c:\tcw\bin\tddebug.386
3. If there's a line in the 386enh section that loads
WINDEBUG.386, either comment the line out with a
semicolon or delete it altogether. (You can't have both
TDDEBUG.386 and WINDEBUG.386 loaded at the same
time.)
For example, if you load WINDEBUG.386 from the C: \
WINDOWS directory, the commented-out line would be
;device=c:\windows\windebug.386

12 Turbo Debugger for Windows User's Guide


Hardware debugging
You can use the debugging registers of the Intel 80386 (and
higher) processor to debug a Windows program. To use these
registers, you must load TDDEBUG.386 when you start Windows
(see the previous section).
Sc:'<:' the onlin<:' doc:- filP HOWDFBUC.TOW for more information
on debugging Windows programs using hardware debugging
registers.

Where to now?
Now you can start learning about TOW. Since this User's Guide is
written for three types of users, different chapters of the manual
might appeal to you. The following road map will guide you.

Programmers
learning Turbo If you're just starting to learn C or C++, you want to be able to
create small programs using it before you learn about the de-
C++
bugger. After you have gained a working knowledge of the
language, work your way through Chapter 3, "A quick example,"
for a speedy tour of the major functions of TOW. There you'll
learn enough about the features you need to debug your first pro-
gram; you'll find out about the debugger's more sophisticated
capabilities in later chapters.

Turbo C++ pros,


but Turbo If you're an experienced Turbo C++ programmer but you're
Debugger unfamiliar with Turbo Debugger, you can learn about the features
of the TOW environment by reading Chapter 2, "TOW basics." If
novices it suits your style, you can then work through the tutorial in
Chapter 3, or, if you prefer, move straight on to Chapter 4,
"Starting TOW." For a complete rundown of all commands, turn
to Chapter 13, "Command reference."

Chapter 7, Getting started 13


Programmers
experienced with If you've used Turbo Debugger in the past, you're probably
Turbo Debugger already familiar with TDW's standard features. In that case, you
can go directly to Chapter 11, "Using Windows debugging
features," which discusses the features of TDW that support
Windows debugging. Another chapter you'll find helpful is
Chapter 15, "Debugging an ObjectWindows application," which
takes you through a debugging session on a Windows application
written using the ObjectWindows library.

14 Turbo Debugger for Windows User's Guide


c H A p T E R

TOW basics
Debugging is the process of finding and correcting errors (''bugs")
in your programs. It's not unusual to spend more time on finding
and fixing bugs in your program than on writing the program in
the first place. Debugging is not an exact science; the best debug-
ging tool you have is your own "feel" for where a program has
gone wrong. Nonetheless, you can always profit from a system-
atic method of debugging.
The debugging process can be broadly divided into four steps:

1. realizing you have an error


2. finding where the error is
3. finding the cause of the error
4. fixing the error

Is there a bug? The first step can be really obvious. The computer freezes up (or
hangs) whenever you run it. Or perhaps it crashes in a shower of
meaningless characters. Sometimes, however, the presence of a
bug is not so obvious. The program might work fine until you
enter a certain number (like 0 or a negative number) or until you
examine the output closely. Only then do you notice that the
result is off by a factor of .2 or that the middle initials in a list of
names are wrong.

Chapter 2, TOW basics 15


Where is it? The second step is sometimes the hardest: isolating where the
error occurs. Let's face it, you simply can't keep the entire pro-
gram in your head at one time (unless it's a very small program
indeed). Your best approach is to divide and conquer-break up
the program into parts and debug them separately. Structured
programming is perfect for this type of debugging.

What is it? The third step, finding the cause of the error, is probably the
second-hardest part of debugging. Once you've discovered where
the bug is, it's usually somewhat easier to find out why the pro-
gram is misbehaving. For example, if you've determined the error
is in a procedure called PrintNames, you have only to examine the
lines of that procedure instead of the entire program. Even so, the
error can be elusive and you might need to experiment a bit
before you succeed in tracking it down.

Fixing it The final step is fixing the error. Armed with your knowledge of
the program language and knowing where the error is, you can
squash the bug. Now you run the program again, wait for the
next error to show up, and start the debugging process again.
See Chapter 14 for a more Many times this four-step process is accomplished when you are
detailed discussion of the
writing the program itself. Syntax errors, for example, prevent
debugging process.
your programs from compiling until they're corrected. Turbo C++
for Windows has a built-in syntax checker that informs you of
these errors and lets you fix them on the spot.
But other errors are more insidious and subtle. They lie in wait
until you enter a negative number, or they're so elusive you're
stymied. That's where TOW comes in.

What TDW can do for you


With TOW, you have access to a much more powerful debugger
than could exist in your language compiler.
You can use TOW with any program written in Turbo C++ for
Windows. TOW runs in character mode and allows you to switch
to your application running under Windows.

16 Turbo Debugger for Windows User's Guide


TDW helps with the two hardest parts of the debugging process:
finding where the error is and finding the cause of the error. It
does this by slowing down program execution so you can
examine the state of the program at any given spot. You can even
test new values in variables to see how they affect your program.
With TDW, you can perform tracing, back tracing, stepping, viewing,
inspecting, changing, and watching.

Tracing Executing your program one lme at a time.


Back tracing Stepping backward through your executed code,
reversing the execution as you go.
Stepping Executing your program one line at a time, but
stepping over any routines or function calls. If
you're sure your routines and functions are
error-free, stepping over them speeds up
debugging.
Viewing Opening a special TDW window to see the state
of your program from various perspectives:
variables, their values, breakpoints, the contents
of the stack, a log, a data file, a source file, CPU
code, memory, registers, numeric coprocessor
information, object or class hierarchies, execution
history, or program output.
Inspecting Delving deeper into the workings of your pro-
gram by examining the contents of complicated
data structures like arrays.
Changing Replacing the current value of a variable, either
globally or locally, with a value you specify.
Watching Isolating program variables and keeping track of
their changing values as the program runs.

You can use these powerful tools to dissect your program into
discrete chunks, confirming that one chunk works before moving
to the next. In this way, you can burrow through the program, no
matter how large or complicated, until you find where that bug is
hiding. Maybe you'll find there's a function that inadvertently
reassigns a value to a variable, or maybe the program gets stuck
in an endless loop, or maybe it gets pulled into an unfortunate
recursion. Whatever the problem, TOW helps you find where it is
and what's at fault.

Chapter 2, TOW basics 17


TDW lets you debug object-oriented C++ programs. It is smart
about objects, and it correctly handles late binding of virtual
methods so that it always executes and displays the correct code.

What TDW won't


do With all the features built into TDW, you might be thinking that
it's got it all. In truth, there are at least three things TDW won't do
for you.
• TDW cannot recompile your program for you. You need Turbo
C++ for Windows to do that.
• TDW doesn't run in graphics mode under Windows, but rather
runs in character mode.
• TDW does not take the place of thinking. When you're
debugging a program, your greatest asset is using your head.
TDW is a powerful tool, but if you use it mindlessly, it's
unlikely to save you time or effort.

How TDW does it


Here's the really good news: TDW gives you all this power and
sophistication, and at the same time it's easy-even intuitive-to
use.
TDW accomplishes this blend of power and ease by offering an
integrated debugging environment. The next section examines the
advantages of this environment.

The TOW advantage


Once you start using TDW, we think you'll be unable to get along
without it. TDW has been especially designed to be as easy and
convenient as possible. To this end, TDW offers you these
features:
• Convenient and logical global menus.
• Context-sensitive local menus throughout the product, which
practically do away with memorizing and typing commands.
• Dialog boxes in which you can choose, set, and toggle options
and type in information.

18 Turbo Debugger for Windows User's Guide


•When you need to type, TDW keeps a history list of the text
you've typed in similar situations. You can choose text from the
history list, edit the text, or type in new text.
•Full macro control to speed up series of commands and
keystrokes.
• Copying and pasting between windows and dialog boxes.
•Convenient, complete window management.
•Mouse support.
•Access to several types of online help.
• Reverse execution.
•Single and dual monitor support.
The rest of this chapter discusses these features of the TDW
environment.

Menus and
dialog boxes As with many Borland products, TDW has a convenient global
menu system accessible from a menu bar running along the top of
the screen. This menu system is always available except when a
dialog box is active.
A pull-down menu is available for each item on the menu bar.
Through the pull-down menus, you can
•execute a command.
•open a pop-up menu. Pop-up menus appear when you choose a
menu item that is followed by a menu icon (Ii>).
•open a dialog box. Dialog boxes appear when you choose a
menu item that is followed by a dialog box icon (... ).

Using the menus There are four ways you can open the menus on the menu bar:
Getting in •Press F10, use~ or (----to go to the desired menu, and press
Enter.
•Press F10, then press the first letter of the menu name (Spacebar,
F, E, V, R, B, 0, 0, W, H).
•Press Alt plus the first letter of any menu bar command
(Spacebar, F, E, V, R, B, D, 0, W, H). For example, wherever you are
in the system, Alt-F takes you to the File menu. The = (System)
menu opens with Alt-Spacebar.
iii.&, • Click the menu bar command with the mouse.

Chapter 2, TOW basics 19


Once you are in the global menu system, here is how you move
around in it:
Getting around •Use~ and f- to move from one pull-down menu to another.
(For example, when you are in the File menu, pressing ~ takes
you to the Edit menu.)
•Use i and .J, to scroll through the commands in a specific menu.
•Use Home and End to go to the first and last menu items,
respectively.
• Highlight a menu command and press Enter to move to a
lower-level (pop-up) menu or dialog box.
¥ •Click the mouse on a command to move to a lower-level (pop-
up) menu or dialog box.
This is how you get out of a menu or the menu system:
Getting out •Press Esc to exit a lower-level menu and return to the previous
menu.
•Press Esc in a pull-down menu to leave the menu system and
return to the active window.
•Press F10 in any menu (but not in a dialog box) to exit the menu.
¥ •Click a window with the mouse to leave the menu system and
go to that window.
Some menu commands have a shortcut hot key that you press to
execute them. The hot key appears in the menu to the right of
these commands.
Figure 13.1 in Chapter 13 shows the complete pull-down menu
tree for TDW. Table 13.1 on page 186 lists all the hot keys. For a
summary of all the commands available in TDW, see Chapter 13.

Dialog boxes Many of TDW's command options are available to you in dialog
boxes. A dialog box contains one or more of the following items:

20 Turbo Debugger for Windows User's Guide


Table 2.1
What goes in a dialog box Item What it looks like, what it does

Buttons Buttons are "shadowed" text (on monochrome systems


they appear in reverse video). If you choose a button,
TDW carries out the related action immediately. Get
out of a dialog box by pressing the button marked OK
The hot key for the OK button to confirm your choices, or Cancel to cancel them.
is Alt-K. Dialog boxes also contain a Help button that brings up
onlme help.
[X] Check boxes A check box is an on/off toggle. Choose it to turn the
option on or off. When a check box option is turned on,
an X appears in brackets: [X) .
( ) Radio buttons Radio buttons offer a set of toggles, but the choices are
(.)
( ) mutually exclusive: you can choose only one radio
button in a set at a time. When you do, a bullet appears
between the parentheses, as follows: ( •) .
,_ Input boxes An input box prompts you to type in a string (the name
of a file, for example). An input box often has a history
list associated with it (see the section "History lessons"
for more on these).
List boxes A list box contains a list of items from which you can
THIS FI LE. EXE
lllfilllllW!:tW choose (for example, a list of possible files to open).
TOTHERFL.EXE

You navigate around dialog boxes by pressing Tab and Shift-Tab.


Within sets of radio buttons, use the arrow keys to change the
settings. To choose a button, tab to it and press Enter.
M, If you have a mouse, it is even easier to get around in a dialog
box. Just click the item you want to choose. To cancel the dialog
box, click the close box in the upper left corner.
¢ You can also choose items in a dialog box by pressing their hot
key, the highlighted letter in each command.

Knowing where
you are In addition to the convenient system of Borland pull-down
menus, the TOW advantage consists of a powerful feature that
lessens confusion by actually reducing the number of menus.
To understand this feature, you must realize that first and fore-
most, TOW is context-sensitive. That means it keeps tabs on

Chapter 2, TOW basics 21


exactly which window you have open, what text is selected, and
which subdivision, or pane, of the window your cursor is in. In
other words, it knows precisely what you're looking at and where
the cursor is when you choose a command. And it uses this
information when it responds. Let's take an example to illustrate.
Suppose your program has a line like this:
MyCounter[TheGrade] += MyCounter[TheGrade];
As you'll discover when you work with TOW, getting information
on data structures is easy; all you do is press Ctr/-/, the hot key that
opens an Inspector window, to inspect it. When the cursor is at
MyCounter, TOW shows you information on the contents of the
entire array variable. But if you were to select (that is, highlight)
the whole array name and the index and then press Ctr/-/, TOW
knows that you want to inspect one member and shows you only
that member.
You can tunnel down to finer and finer program detail in this
way. Pressing Ctr/-/ on a highlighted member while you're already
inspecting an array gives you a look at that member.
This sort of context-sensitivity makes TOW extremely easy to use.
It saves you the trouble of memorizing and typing complicated
strings of menu commands or arcane command-line switches.
You simply move to the item you want to examine (or select it
using the Ins key or drag over it with the mouse), and then invoke
the command (Ctr/-/ for Inspect, for example).
This context-sensitivity, which makes life easy for the user, also
makes the task of documenting commands difficult. This is
because Ctr/-/, for example, in TOW does not have a single result;
instead, the outcome of a command depends on where your cursor is or
what text is selected.

Local menus Another aspect of TOW's context-sensitivity is in its use of local


menus specific to different windows or panes within windows.
Local menus in TOW are tailored to the particular window or
pane you are in. It's important not to confuse them with global
menus. Here is a composite screen shot of both kinds of menus
(when you're actually working in TOW, however, you could
never have both types of menus showing at the same time):

22 Turbo Debugger for Windows User's Guide


Figure 2.1
Global and local menus

Compare the following two lists:


Global menus •Global menus are those that you access by pressing F10 and
using the arrow keys or typing the first letter of the menu name.
•The global menus are always available from the menu bar,
visible at the top of the screen.
•Their contents never change.
•Some of the menu commands have hot key shortcuts that are
available from any part of TOW.
Local menus •You call up a local menu by pressing Alt-F10 or by clicking the
right button on your mouse.
•The placement and contents of the menu depends on which
window or pane you are in and where your cursor is.
• Contents can vary from one local menu to another. (Even so,
many of the local commands appear in almost all of the local
menus, so that there's a predictable core of commands from one
to another.) The results of like-named commands can be
different, however, depending on the context.
• Every command on a local menu has a hot key shortcut
consisting of Ctr/ plus the highlighted letter in the command.
• Because of this arrangement, a hot key, say Ctrl-S, might mean
one thing in one context but quite another in a different context.
(A core of commands, however, is still consistent across the
local menus. For example, the Goto command and the Search

Chapter 2, TDW basics 23


command always do the same thing, even when they are
invoked from different panes.)
From a user's standpoint, local menus are a great convenience. All
possible command choices relevant to the moment are laid out at
a glance. This prevents you from trying to choose inappropriate
commands and keeps the menus small and uncluttered.

History lessons
Menus and context-sensitivity comprise just two aspects of the
convenient environment of TDW. Another habit-forming feature
is the history list.
Conforming to the philosophy that the user shouldn't have to
type more than absolutely necessary, TDW remembers whatever
you enter into input boxes and displays that text whenever you
call up the box again.
For example, to search for the function called MyPercentage, you
have to type in all or part of that word. Then suppose you want to
search for a variable called ReturnOnlnvestment. When you see the
dialog box this time, you'll notice that MyPercentage appears in
the input box. When you search for another text string, both pre-
viously entered strings appear in the input box. The list keeps
growing as you continue to use the Search command.
The search input box might look like this:
Figure 2.2
Ahistorylistinanlnputbox TDD~ .c
if! PROMPT
ll[!=Mo.u e: TDDEM. File: l=[tJ [~]=;i
/* program entry point

~
*/
int PASCAL WinMain(HANDLE hlnstance, HANDLE hPrevlnstance,
LPSTR lpszCmdLine, int nCmdShow )
I
I

unsigned int n1i nes, nwords, wordcount;


unsigned long totalcharacters;

InitWinCrt();
iilines = O;
nwords = O;
totalcharacters = O;
showargs( argc, argv);
while (readaline\) != O) {
wordcount = makei ntowords
nwords += wordcount;

24 Turbo Debugger for Windows User's Guide


The first item in a search list is You can use this history list as a shortcut to typing by using the
always the word the cursor is arrow keys to select any previous entry then pressing Enter to start
on in the Module window.
the search. If you have a mouse, you can also use the scroll bar to
scroll to the entry you want. If you use an unaltered entry from
the history list, that entry is copied to the top of the list.
You can also edit entries (use the arrow keys to insert the cursor
in the highlighted text, then edit as usual, using Del or Backspace).
For exarr1ple, y·ot1. can select lv1yPe;centage arld change it to
HisPercentage, instead of typing in the entire text. If you start to
type a new item when an entry is highlighted, you will overwrite
the highlighted item.
A history list lists the last ten responses unless you've used
TOWINST to configure TOW otherwise. (The TOWINST program
is described in the file TOWINST.TOW.)
TOW keeps a separate history list for most input boxes. That way,
the text you enter to do a search does not clutter up the box for,
say, going to a particular label or line number.

Automatic name Whenever you are prompted for text entry in an input box, you
completion can type in just part of a symbol name in your program, then
press Ctrl-N.
Warning! When the word READY ••• appears in the upper right corner of the
screen with three dots after it, it means the symbol table is being
sorted. Ctrl-Nwon't work until the three dots go away, indicating
that the symbol table is available for name completion.
• If you have typed enough of a name to uniquely identify it,
TOW simply fills in the rest of it.
•If the name you have typed so far is not the beginning of any
known symbol name, nothing happens.
•If what you have typed matches the beginning of more than
one symbol name, a list of matching names is presented for you
to pick the one you want.

Incremental
matching TOW also lets you use incremental matching to find entries in a
dialog box list of file and directory names. Start typing the name
of the file or directory; if the file is available from the names at or
below the current position in the list box, the highlight bar moves

Chapter 2, TOW basics 25


to the name as soon as you have typed enough characters to
identify it uniquely. Then all you have to do is choose the OK
button.

Making macros
Whenever you find yourself Macros are simply hot keys you define to perform a series of
repeating a series of steps,
commands and other keystrokes.
say to yourself, "Shouldn't I
be using a macro for this?° You can assign any series of TDW commands and keystrokes to a
single key, for playback whenever you want.
See page 64 in Chapter 4 for an explanation of how to define
macros.

Window shopping
TDW displays all information and data in menus (local and
global), dialog boxes (which you use to set options and enter
information), and windows. There are many types of windows; a
window's type depends on what sort of information it holds. You
open and close all windows using menu commands (or hot key
shortcuts for those commands). Most of TDW's windows come
from the View menu, which lists fifteen types of windows.
Another class of window, called the Inspector window, is opened
by choosing either Data I Inspect or Inspect from a local menu.

Windows from the View To the left is a list of the fifteen types of windows you can open
menu from the View menu.
Breakpoints Once you have opened one or more of these windows, you can
Stack
Log move, resize, close, and otherwise manage them with commands
Watches
Variables
from the Window and = (System) menus, which are discussed
Module... F3 later in this chapter in the section "Working with windows."
File ••.
CPU
Dump
Registers Breakpoints window
Numeric processor
Execution history Displays the breakpoints you have set. A breakpoint defines a
Hierarchy
Windows messages location in your program where execution stops so you can
Clipboard
Another ~ examine the program's status. The left pane lists the position of
every breakpoint (or indicates that it is global), and the right pane
See Chapter 7 for a indicates the conditions under which the currently highlighted
complete description of this
breakpoint executes.
type of window and how
breakpoints work. Use this window to modify, delete, or add breakpoints.

26 Turbo Debugger for Windows User's Guide


Stack window
Chapter 5 provides more Displays the current state of the stack, with the function called
information on the Stack
window.
first on the bottom and all subsequently called functions on top,
in the order in which they were called.
You can bring up and examine the source code of any function in
the stack by highlighting it and pressing Ctr/-/.
By highlighting a function name in the stack and pressing Ctr!-L,
you open a Variables window displaying variables global to the
program, variables local to the function, and the arguments with
which the function was called.

Log window
Chapter 7 tells you more Displays the contents of the message log. The log contains a
about the Log window.
scrolling list of messages and information generated as you work
in TDW. It tells you such things as why your program stopped,
the results of breakpoints, the contents of windows you saved in
the log, and Windows information.
You can also use the log window to obtain information about
memory usage and modules for a Windows application.
This window lets you look back into the past and see what led up
to the current state of affairs.

Watches window
See Chapter 6 for more Displays variables and expressions and their changing values.
about the Watches window.
You can add a variable to the window by pressing Ctrl-Wwhen the
cursor is on the variable in the Module window.

Variables window
Chapter 5 describes the Displays all the variables accessible from a given spot in your pro-
Variables window in more
detail.
gram. The upper pane has global variables; the lower pane shows
variables local to the current function or module, if any.
This window is helpful when you want to find a function or
variable that you know begins with, say, "abc," and you can't
remember its exact name. You can look in the global Symbol pane
and quickly find what you want.

Chapter 2, TOW basics 27


Module window
Displays the program code that you're debugging. You can move
around inside the module and examine data and code by posi-
tioning the cursor on program variable names and issuing the
appropriate local menu command.
You will probably spend more time in Module windows than in
Chapter 8 details the Module
window and its commands.
any other type, so take the time to learn about all the various local
menu commands for this type of window.
You can also press F3 to open a Module window.

File window
You can learn more about Displays the contents of a disk file. You can view the file either as
the File window in Chapter 8.
raw hex bytes or as ASCII text, and you can search for specific text
or byte sequences.

CPU window
Chapter 12 discusses the Displays the current state of the central processing unit (CPU).
CPU window and assembler-
This window has six panes: one that contains disassembled
/eve/ debugging.
machine instructions, one that shows the contents of a selector,
one that shows hex data bytes, one that displays a raw stack of
hex words, one that lists the contents of the CPU registers, and
one that indicates the state of the CPU flags.
The CPU window is useful when you want to watch the exact
sequence of instructions that make up a line of source code or the
bytes that comprise a data structure. If you know assembler code,
this can help locate subtle bugs. You do not need to use this
window to debug the majority of programs.
TDW sometimes opens a CPU window automatically if your
program stops in Windows code or on an instruction in the
middle of a line of source code.

Dump window
See Chapter 12, which Displays a raw display of an area of memory. (This window is the
discusses assembler
debugging, for more on this
same as the Data pane of a CPU window.) You can view the data
window. as characters, hex bytes, words, doublewords, or any floating-
point format. You can use this window to look at some raw data
when you don't need to see the rest of the CPU state or to gain
direct access to I/ 0 ports. The local menu has commands to let

28 Turbo Debugger for Windows User's Guide


you modify the displayed data, change the format in which you
view the data, and manipulate blocks of data.

Registers window
Chapter 72, which discusses Displays the contents of the CPU registers and flags. This window
assembler debugging, has
more information on this
has two panes, which are the same as the registers pane and flags
window. pane, respectively, of a CPU window. Use this window when you
want to iook at the contents of the registers but don't need to see
the rest of the CPU state. You can change the value of any of the
registers or flags through commands in the local menu.

Numeric Processor window


See the file ASMDEBUG. TOW Displays the current state of the numeric coprocessor. This
for more information about
window has three panes: one pane that shows the contents of the
using the Numeric Processor
window. floating-point registers, one that shows the status flag values, and
one that shows the control flag values.
This window can help you diagnose problems in programs that
use floating-point numbers. You need to have a fair understand-
ing of the inner workings of the numeric coprocessor in order to
really reap the benefits of this window.

Execution History window


See Chapter 5 for more Displays source lines for your program, up to the last line
information on the Execution executed. The window indicates
History window.

1. whether you are tracing or stepping


2. the line of source code for the instruction about to be executed
3. the line number of the source code

You can examine it or use it to rerun your program to a particular


spot.

Hierarchy window
Lists and displays a hierarchy tree of all classes used by the
~
See Chapter 70 for more
current module. The window has two panes: one for the class list,
information about using the the other for the class hierarchy tree. This window shows you the
Hierarchy window. relationship of the classes used by the current module. By using

Chapter 2, TOW basics 29


this window's local menu commands, you can examine any class's
data members and member functions.

Windows Messages window


Chapter 11 explains how to Displays a list of messages passed between the windows in your
use the Windows Messages
Windows application. This window has three panes:
feature.
•The left pane shows which procedures or handles you're
tracking messages for.
•The right pane shows the type of messages you're tracking.
•The bottom pane displays the messages being tracked.

Clipboard window
See page 36 for an Displays the items that have been clipped into the Clipboard,
explanation of how to use
showing you their types and allowing you to inspect or delete an
the Clipboard.
item and to freeze the value of any item in the Clipboard.

Duplicate windows

Module •••
You can also open duplicates of three types of windows-Dump,
Dump File, and Module-by choosing View IAnother. This lets you keep
File ..•
track of several separate areas of assembly code, different files the
program uses or generates, or several distinct program modules
at once.
Don't be alarmed if TDW opens one of these windows all by itself.
It will do this in some cases in response to a command.

User screen The User screen shows your program's full output screen. The
screen you see is exactly the same as the one you would see if
your program was running directly under Windows and not
underTDW.
Alt·F5 is the hot key that You can use this screen to check that your program is at the place
toggles between the
environment and the User
in your code that you expect it to be, as well as to verify that it is
screen. displaying what you want on the screen. To switch to the User
screen, choose Window IUser Screen. After viewing the User
screen, press any key to go back to the debugger screen.

30 Turbo Debugger for Windows User's Guide


Inspector windows An Inspector window displays the current value of a selected
variable. Open it by choosing Data I Inspect or Inspect from a local
menu. Usually, you close this window by pressing Esc or clicking
M,_ the close box with the mouse. If you've opened more than one
Inspector window in succession, as often happens when you
examine a complex data structure, you can remove all the Inspec-
tor windows by pressing Alt-F3 or using the Window I Close
command.
You can open an Inspector wmdow to iook at an array of items or
at the contents of a variable or expression. The number of panes in
the window depends on the nature of the data you are inspecting.
An Inspector window adapts to the type of data being displayed.
It can display not only simple scalars (int, float, and so on), but
also pointers, arrays, structures, and unions. Each type of data
item is displayed in a way that closely mimics the way you're
used to seeing it in your program's source code.
¢ You create additional Inspector windows simply by choosing the
Inspect command, whereas you can create additional Module,
File, or CPU windows only by choosing View I Another.

The active window Even though you can have many windows open in TDW at the
same time, only one window can be active. You can spot the active
window by the following criteria:
• The active window has a double outline around it, not a single
line.
•The active window contains the cursor or highlight bar.
• If your windows are overlapping, the active window is the
topmost one.
When you issue commands, enter text, or scroll, you affect only
the active window, not any other windows that are open.

Chapter 2, TOW basics 31


Figure 2.3
The active window has a
double outline
/• program ent
•I
~ int PASCAL Wi
LPSTR l

unsigned int
unsigned lon
•=um
ds :0000 00 00 00 00 00 00 50 lE
InitWinCrt( [[ ds:0008 00 00 C2 OA 2C lE 2C lE
iilines = O; ds:OOlO 00 00 08 00 00 00 4D OA
nwords = O; ds:0018 66 OA 36 OA 80 00 01 00
total charact
showar~s ( argc, argv ;
while (readalineTl != OJ {
wordcount = makeintowords(buffer);
nwords += wordcount;

What's in a window A window always has most or all of the following features, which
give you information about it or let you do things to it:
Figure 2.4 ZoOll and
Window Iconlze
A typical window Close box Title number boxes
~ ~ ~ ~
[•]=Module: TDDEMO File: TDDEMO.C 37========l=[t] [~]
static void showargs(int argc, char •argv[]);
/• program entry point
•/
~ int PASCAL Wi nMai n (HANDLE hlnstance, HANDLE hPrevinstance,
LPSTR l pszCmdli ne, int nCmdShow )
unsigned int nlines, nwords, wordcount;
unsigned long totalcharacters;

InitWinCrt();
iilines = 0;
nwords = O; + Scroll bar
total characters = O;
showarQs( argc, argv);
while (readalineT) != OJ {
wordcount = makei ntowords (buffer); ,.
IL<QllllllJIMllllllllillilliRllliiliililllliiiiiililrilllBllllll~~
t t
Scroll bar Resize box

•An outline (double if the window is active, single otherwise).


•A title, located at the left top.
Ii.&. • A scroll bar or bars on the right or bottom if the window opens
on more information than it can hold at one time. You operate
the scroll bars with the mouse:
• Click the direction arrows at the ends of the bar to move one
line or one character in the indicated direction.

32 Turbo Debugger for Windows User's Guide


• Click the gray area in the middle of the bar to move one
window size in the indicated direction.
• Drag the scroll box to move as much as you want in the
direction you want.
•A resize box in the lower right corner. Drag it with your mouse
to make the window larger or smaller. If no scroll bar is present
on the bottom or right side of a window, that side of the
window border also activates window resizing.
•A window number in the upper right, reflecting the order in
which the window was opened.
•A zoom box and iconize box in the upper right corner. The one
on the left contains the zoom icon, the one on the right the
iconize icon. Click these with your mouse to expand the
window to full screen size, restore it to its original size, or
iconize it. (When a window is zoomed to full size, only the
unzoom box is available, and when it is iconized, only the zoom
box is available.)
•A close box in the upper left corner. Click it with your mouse to
close the window.

Working with windows With all these different windows to work with, you will probably
have several open onscreen at a time. TOW makes it easy for you
to move from one window to another, move them around, pile
them on top of one another, shrink them to get them out of your
way, expand them to work in them more easily, and close them
when you are through.
Press Alt-Spacebar to open the Most of the window-management commands are in the Window
=menu, or Aff-W to open the menu. You'll find a few more commands in the = (System) menu,
Window menu.
the menu marked with the =icon at the far left of the menu bar.

Window hopping
Each window that you open is numbered in the upper right
corner. Usually, the Module window is window 1 and the
Watches window is window 2. Whatever window you open after
that will be window 3, and so on.
This numbering system gives you a quick, easy means of moving
from one window to another. You can make any of the first nine
open windows the active window by pressing Alt in combination
with the window number. If you press Alt-2, for example, to make

Chapter 2, TDW basics 33


the Watches window active, any commands you choose will affect
that window and the items in it.
F6 is the hot key for the You can also cycle through the windows onscreen by choosing
Window I Next Window. Window I Next or pressing F6. This is handy if an open window's
number is covered up so you don't know which number to press
to make it active.
If you have a mouse, you can also activate a window by clicking
it.
To see a list of all open windows, choose Window from the menu
bar. The bottom half of the Window menu lists up to nine open
windows from which you can make a selection. Just press the
number of a window to make it the active one.
If you have more than nine windows open, the window list will
include a Window Pick command; choose it to open a pop-up
menu of all the windows open onscreen.
Tab and Shift-Tab are the hot If a window has panes-areas of the window reserved for a
keys for Window I Next Pane. specific type of data-you can move from one pane to another by
choosing Window I Next Pane or pressing Tab or Shift-Tab.
You can also click the pane with the mouse.
The most pane-full window in TDW is the CPU window, which
has six panes.
Refer to Chapter 13 for a As you hop from pane to pane, you'll notice that a blinking cursor
table of keystroke appears in some panes, and a highlight bar appears in others. If a
commands in panes.
cursor appears, you move around the text using standard keypad
commands. (PgUp, Ctrl-Home, and Ctrl-PgUp, for example, move the
cursor up one screen, to the top of pane, or to the top of the list,
respectively.) If you've disabled shortcut keys, you can also use
WordStar-like hot keys for moving around in the pane.
If there's a highlight bar in a pane instead of a cursor, you can still
use standard cursor-movement keys to get around, but a couple
of special keystrokes also apply. In alphabetical lists, for example,
you can select by typing. As you type each letter, the highlight bar
moves to the first item starting with the letters you've just typed.
The position of the cursor in the highlighted item indicates how
much of the name you have already typed. Once the highlight bar
is on the desired item, your search is complete. This incremental
matching or select by typing minimizes the number of characters
you must type in order to choose an item from a list.

34 Turbo Debugger for Windows User's Guide


Once an item is selected (highlighted) from a list, you can press
Alt-F10 to choose a command relevant to it from its local menu. In
many lists, you can also just press Enter once you have selected an
item. This acts as a hot key to one of the commonly used local
menu commands. The exact function of the Enter key in these cases
is described in the reference section starting on page 190.
Finally, a number of panes let you start typing a new value or
search string without choosing a command first. This usually
applies to the most frequently used local menu command in a
pane or window-like Goto in a Module window, Search in a File
window, or Change in a Registers window.

Moving and resizing windows


When you open a new window in TDW, it appears near the
current cursor location and has a default size suitable for the kind
of window it is. If you find either the size or the location of the
window inconvenient, you can use the Window I Size/Move
command to adjust the size or location of the window.
Ctrl-F5 is the hot key for the When you move or resize a window, your active window border
Window I Size/Move
command.
changes to a single-line border. You can then use the arrow keys
to move the window around or Shift with the arrow keys to
change the size of the window onscreen. Press Enter when you're
satisfied.
If you have a mouse, moving and resizing a window is even
easier:
• Drag the resize box in the lower right corner to change the size
of the window.
•Drag the title bar or any edge (but not the scroll bars) to move
the window around.
F5 is the hot key for the If you want to enlarge or reduce a window quickly, choose
Window I Zoom command.
Window I Zoom, or click the mouse on the zoom box or the iconize
box in the upper right corner.
Finally, if you want to get a window out of the way temporarily
but don't want to close it, make the window active, then choose
Window I lconize/Restore. The window will shrink to a tiny box
(icon) with only its name, close box, and zoom box visible. To
restore the window to its original form, make it active and choose
Window I lconize/Restore again, or click your mouse on the zoom
box.

Chapter 2, TOW basics 35


Closing and recovering windows
Alt-F3 is the hot key for When you are through working in a window, you can close it by
Window 1Close. choosing Window I Close.
M, If you have a mouse, you can also click the Close box in the upper
left corner of the window.
Alt-F6 Is the hot key for If you close a window by mistake, you can recover it by choosing
Window I Undo Close. Window I Undo Close or by pressing Alt-F6. This works only for the
last window you closed.
You can also restore your TDW screen to the layout it had when
you first entered the program. Just choose = (System) I Restore
Standard.
Finally, if your program has overwritten your environment screen
with output (because you turned off screen swapping), you can
clean it up again with = (System) I Repaint Desktop.

Saving your window layout


Use the Options I Save Options command to save a specific
window configuration once you have the screen arranged the way
you like. In the Save Configuration dialog box, tab to Layout and
press Spacebarto toggle it on. The screen will then appear with
your chosen layout each time you start TOW, if the configuration
has been saved to a file called TDCONFIG.TDW. This configu-
ration file is the only one loaded automatically when TOW is
loaded. Other configurations can be loaded by using the Options I
Restore Options command if they have been saved to configu-
ration files with a different name.

Copying and
pasting TOW has an extensive copy and paste feature called the
Clipboard. With the Clipboard you can copy and paste between
TOW windows and dialog boxes.
The items you copy into the Clipboard are dynamic; if an item has
an associated value, the Clipboard keeps that value current as it
changes in your program.
You can use the Ins key to To copy an item into the Clipboard, position the cursor on the
mark multiple items in a list. item or highlight it with the Ins key, then press Shift-F3. To paste
something into a window or dialog box from the Clipboard, press

36 Turbo Debugger for Windows User's Guide


Shift-F4 or use the Clip button in the dialog box to bring up the
Pick dialog box.
¢ You can paste into any dialog box prompt (any place in a dialog
box where you can type text) by pressing Shift-F4, even if the
dialog box doesn't have a Clip button. You can also paste into
dialog box prompts with multiple fields.

The Pick dialog box Pressing Shift-F4 er the Clip butter. brings up a dialcg box listing
Clipboard contents and showing the categories you can use for
pasting an item into the dialog box.
Figure 2.5
The Pick dialog box

This dialog box shows a scrolling list of items in the Clipboard


and allows you to interpret the item to be pasted in up to three
ways: as a string, as an address, or as contents of an address. The
categories you can use in pasting the item depend on its type and
its destination (discussed later).
For example, if you clip text from the Log window, it can be
pasted only as a string. If you clip text from the Module window,
it can be pasted elsewhere as a string or as an address, but not as
contents. If you clip a variable from an Inspector window, it can
be pasted as a string, a location, or as contents (unless it's a C
register variable, in which case you can paste it only as a string or
as contents, not as an address).
To paste an item into a dialog box, highlight the item, select the
appropriate category, then either press Enter or the Paste button,
depending on what effect you want to have on the dialog box.
•Pressing Enter simply pastes the item in and returns you to the
dialog box.
• Pressing the Paste button both pastes the item in and passes an
Enter to the dialog box, causing it to perform its function.

Chapter 2, TOW basics 37


The Clipboard window There's a View window that lets you see the contents of the
Clipboard. Choosing View I Clipboard displays the Clipboard
window, which lists all clipped items.
Figure 2.6
The Clipboard window

The leftmost field of this window describes the type of the entry,
followed by a colon and the clipped item. If the clipped item is an
expression from the Watches window, a variable from the
Inspector window, or data, a register, or a flag from the CPU
window, the item is followed by its value or values.

Clipboard item types


When you clip an item from a Window, Turbo Debugger assigns
it a type to help you identify the source of the item. The following
table shows the Clipboard types:
Table 2.2
Clipboard item types Type Description
~~~~~~~~~~~~~~~~~~~~~~~~~~-

String A text string, like a marked block from the File window
Module A module context, including a source code position,
like a variable from the Module window
File A position in a file (in the File window) that isn't a
module in the program
CPU code An address and byte list of executable instructions
from the Code pane of the CPU window
CPU data An address and byte list of data in memory from the
Data pane of the CPU window or the Dump window
CPU stack A source position and stack frame from the Stack pane
of the CPU window
CPU register A register name and value from the Register pane of
the CPU window or the Registers window
CPU flag A CPU flag value from the Flags pane of the CPU
window
Inspector One of the following:
A variable name from an Inspector window
A constant value from an Inspector or Watches
window

38 Turbo Debugger for Windows User's Guide


Table 2.2: Clipboard item types (continued)
A register-based variable from an Inspector
window
A bit field from an Inspector window
Address An address without data or code attached
Expression An expression from the Watches window
Coprocessor An 80x87 numeric coprocessor register
Control flag An 80x87 control flag value
Status flag An 80x87 status flag value

The Clipboard window local menu

Inspect If you're in the Clipboard window and you press Alt-F10 or click
Remove the right mouse button, you see the menu at the left. Alterna-
Delete all tively, you can press Ctr/ and the highlighted key of the local menu
Freeze
command to execute a command.
Table 2.3
Clipboard local menu Command Description
commands Inspect Positions the cursor in the window from which the
item was clipped.
Remove Removes the highlighted item or items. Pressing Del has
the same effect on a highlighted item.
Delete All Deletes everything in the Clipboard.
Freeze Stops the Clipboard item from being dynamically
updated.

Dynamic updating
The Clipboard dynamically updates any item with an associated
value, such as an expression from the Watches window, a variable
from the Inspector window, or a register from the CPU window.
You can use the Clipboard as a large Watches window if you
wish, and you can freeze the value of any item you like.
See Chapter 6 for more For example, you might want to put a Watches window
information on watching
expression in the Clipboard. To do so, first put it in the Watches
expressions.
window, then press Shift-F3 to copy it into the Clipboard. The
value of the item then changes just as it would in a Watches
window, unless you use the local menu Freeze command to
disable the watchpoint.

Chapter 2, TOW basics 39


One advantage of watching an expression in the Clipboard is that
you can freeze the expression at a certain value, then continue
running the program and compare the frozen value to the
changing values in the Watches window.

Tips for using the The possible uses of the Clipboard are too numerous to list here.
Clipboard Some of the things you can do with it are
•clipping from lines in Module windows as a way of marking
locations that you can later return to using the local menu Goto
command (by pasting a location into the dialog box displayed
by the Goto command)
• watching an expression (see the previous section)
• pasting new values into variables using the Data I Evaluate
dialog box or the dialog box for the Change command of the
Inspector window or the Watches window
• pasting strings into the Log window to help you keep track of
what you did during a debugging session
•pasting an address (the location category of an item) into any of
the places where an address is requested (such as the
Breakpoints I Options dialog box Address field, or the Run I
Execute To dialog box)
• pasting expressions into conditions and actions of breakpoints
• pasting parameters into the Run I Arguments dialog box
• pasting a Window proc name or an OWL object name into the
Windows Messages window
•pasting a string into the dialog box for the Module window
Search command
•copying data from and pasting it to the CPU data pane
• copying code from one part of the CPU window to another and
then running the program with the copied code

Getting help
As you've seen, TOW goes out of its way to make debugging easy
for you. It doesn't require you to remember obscure commands; it
keeps lists of what you type, in case you want to repeat it; it lets
you define macros; and it offers sophisticated control of your
windows. To avoid potential confusion, TOW offers the following
help features:

40 Turbo Debugger for Windows User's Guide


•An activity indicator in the upper right corner always displays
-READY I the current activity. For example, if your cursor is in a window,
the activity indicator reads READY; if there's a menu visible, it
reads MENU; if you're in a dialog box, it reads PROMPT. If you ever
get confused about what's happening in TOW, look at the
activity indicator for help. (Other activity indicator modes are
SIZE/MOVE, MOVE, ERROR, RECORDING, WAIT, RUNNING, HELP, STATUS, and
PLAYBACK.)
•The active window i:s alway:::. iupmust anJ has a double line
around it.
•You can access an extensive context-sensitive help system by
pressing F1. Press Ft again to bring up an index of help topics
from which you can select what you need.
•The status line at the bottom of the screen always offers a quick
reference summary of keystroke commands. The line changes
as the context changes and as you press Alt or Ctr/. Whenever
you are in the menu system, the status line offers a one-line
synopsis of the current menu command.
For more information on the last two avenues for help, read the
following two sections.

Online help TOW, like other Borland products, gives context-sensitive


onscreen help at the touch of a single key. Help is available
anytime you're within a menu or window, as well as when an
error message or prompt is displayed.
Press F1 to bring up a Help screen showing information pertinent
to the current context (window or menu). If you have a mouse,
M, you can also bring up help by clicking Fl on the status line. Some
Help screens contain highlighted keywords that let you get addi-
tional help on that topic. Use the arrow keys to move to any key-
word and then press Enterto get to its screen. Use the Home and
End keys to go to the first and last keywords on the screen,
respectively.

Index Shi ft-Fl You can also access the onscreen help feature by choosing Help
Previous topic Alt-Fl from the menu bar (Alt-H).
Help on help
If you want to return to a previous Help screen, press Alt-Ft or
choose Previous Topic from the Help menu. From within the
Help system, use PgUp to scroll back through up to 20 linked help
screens. (PgDn only works when you're in a group of related
screens.) To access the Help Index, press Shift-Ft (or Ft from within

Chapter 2, TOW basics 41


the Help system), or choose Index from the Help menu. To get
help on Help, choose Help I Help on Help. To exit from Help, press
Esc.

The status line Whenever you're in TOW, a quick-reference help line appears at
the bottom of the screen. This status line provides at-a-glance
keystroke or menu command help for your current context.

In a window
The normal status line shows the commands performed by the
function keys and looks like this:

If you hold down the Alt key for a second or two, the commands
performed by the Alt keys are displayed.
Figure 2.8
The status line with Alt pressed A1t' F2a!IBEIF3lilill!IF4&11F!ill!lli'mF6mrilF7llililaFl!IDIF91BFlOIBI

If you hold down the Ctr/ key for a second or two, the commands
performed by the Ctr/ letter keys are displayed. This status line
changes depending on the current window and current pane, and
it shows the single-keystroke equivalents for the current local
menu. If there are more local menu commands than can be
described on the status line, only the first keys are shown. You
can view all the available commands on a local menu by pressing
Alt-F10to pop up the entire menu.
Figure 2.9
The status line with Ctrl Ctrl' 1 ~FIDl!llPIH411FU•Lllasmt41M
pressed

In a menu or dialog box


Whenever you are in a menu or a dialog box, the status line
displays a one-line explanation of what the current item does. For
example, if you have highlighted View I Registers, the status line
says Open a CPU registers window.
The status line gives you menu help whether you are in a global
menu or a local menu.

42 Turbo Debugger for Windows User's Guide


c H A p T E R

A quick example
If you're eager to use TDW and aren't the sort of person to work
through the whole manual first, this chapter gives you enough
knowledge to debug your first program. Once you've learned the
basic concepts described here, the integrated environment and
context-sensitive Help system make it easy to learn as you go
along.
This chapter leads you through all TDW's basic features. After
describing the demo program TDDEMO provided on the
distribution disks, it shows you how to
• run and stop program execution
• examine the contents of program variables
•look at complex data objects, like arrays and structures
• change the value of variables

The demo program


The demo program (TDDEMO) introduces you to the two main
things you need to know to debug a program: how to stop and
start your program and how to examine your program's variables
and data structures. The program itself is not meant to be
particularly useful: Some of its code and data structures exist
solely to show you TDW's capabilities.

Chapter 3, A quick example 43


The program uses the Easy Win module to display its output in a
window under Windows. It's not a full-featured Windows
application, but it does illustrate some useful TDW concepts.
The demo program lets you type in some lines of text, then counts
the number of words and letters that you entered. At the end of
the program, it displays some statistics about the text, including
the average number of words per line and the frequency of each
letter.
¢ Make sure your working directory contains the two files needed
for the tutorial: TDDEMO.C and TDDEMO.EXE.
Getting in To start the demo program,

1. Make sure Windows is running in standard or 386 enhanced


mode. (TDW doesn't run in real mode.)
2. In the Windows Program Manager, open the program group
that contains TDW and choose the TDW icon.
3. When TDW starts up, choose File I Open and enter the full
path to TDDEMO (you might need to compile TDDEMO.C
first with debugging information), then press Enter.

TDW loads the demo program, displays the startup screen, and
positions the cursor at the start of the program.
Figure 3.1
The startup screen showing
TD DEMO
/* program entry point
*/
.. int main(int argc, char **argv) {
unsigned int nlines, nwords, wordcount;
unsigned 1ong tota lcharacters;
nlines = O;
nwords = O;
totalcharacters • O;
showargs(argc, argv);
while (readaline() != O) {
wordcount = makei ntowords (buffer);
nwords += wordcount;
totalcharacters += analyzewords(buffer);
nl ines++;

The startup screen consists of the menu bar, the Module and
Watches windows, and the status line.

44 Turbo Debugger for Windows User's Guide


Getting out To exit from TDW at any time, press Alt-X. If you get hopelessly
lost following the tutorial, press Ctrl-F2 to reload the program and
start at the beginning. However, Ctrl-F2 doesn't clear breakpoints
or watches; you'll have to use Alt-8 D to do that.
Getting Help Press Ft whenever you need Help with the current window,
menu command, dialog box, or error message. You can learn a lot
by working your way through the menu system and pressing Ft
at each command to get a summary of vvhat it does.

Using TDW

The menus
The top line of the screen shows the menu bar. To pull down a
menu from it, press FtO. Then, to choose a menu command, you
can either use f- or ~ to highlight your selection and press Enter,
or press Alt in combination with the highlighted letter of one of the
menu names.
Figure 3.2
The menu bar

Press FtO now. Notice that the cursor disappears from the Module
window, and the = command on the menu bar becomes high-
lighted. The bottom line of the screen also changes to indicate
what sort of functions the =menu performs.
Use the arrow keys to move around the menu system. Press t to
pull down the menu for the highlighted item on the menu bar.
You can also open a menu by clicking an item in the menu bar
with your mouse.
Press Esc to move back through the levels of the menu system.
When just one menu item on the menu bar is highlighted, pres-
sing Esc returns you to the Module window, with the menu bar
no longer active.

Chapter 3, A quick example 45


The status line
The status line at the bottom of the screen shows relevant function
keys and what they do.

This line changes depending on what you are entering (menu


commands, data in a dialog box, and so on). Hold Alt down for a
second or two, for example. Notice that the status line changes to
show you the function keys you can use with Alt.
Now press Ctr/ for a second. The commands shown on the status
line are the hot keys to the local menu commands for the current
pane (area of the window). They change depending on which sort
of window and which pane you are in. (More about these later.)
As soon as you enter the menu system, the status line changes
again to show you what the currently highlighted menu option
does. Press F10 to go to the menu bar, and press~ to highlight the
File option. The status line now reads, File oriented functions.
Use .!. to scroll through the options on the File menu, and watch
iii.&. the message change. Press Esc or click the Module window with
your mouse to leave the menu system.

The windows
The window area takes up most of the screen. This area is where
you examine various parts of your program through the different
windows.
The display starts up with two windows: a Module window and
the Watches window. Until you open more windows or adjust
these two, they remain tiled, filling the entire screen without
overlapping. New windows automatically overlap existing
windows until you move them.

46 Turbo Debugger for Windows User's Guide


Figure 3.4
i!li•
ll["Jo9!~hl~YH!t DON~~HIN.C
The Module and Watches READY
File: 3
windows, tiled /* program DoNuthin */
~ main()
{}

This is the Module window

Notice that the Module window has a double-line border and a


highlighted title, which indicate that it's the active window. You
use the cursor keys (the arrow keys, Home, End, PgUp, and so on) to
move around inside the active window. Now press F6 to switch to
another window. The Watches window becomes active, with a
double-line border and a highlighted title.
You use commands from the View menu to create new windows.
For example, choose View IStack to open a Stack window. The
Stack window pops up on top of the Module window.
Now press Alt-F3 to remove the active window. The Stack window
disappears.
TOW stores the last-closed window, making it possible for you to
recover it if you need to. If you accidentally close a window,
choose Window I Undo Close. If you do so now, you see the Stack
window reappear. You can also press Alt-F6 to recover the last-
closed window.
The Window menu contains the commands that let you adjust the
appearance of the windows you already have onscreen. You can
both move the window around the screen and change its size.
(You can use Ctrl-F5 to do the same thing.)
Choose Window ISize/Move and use the arrow keys to reposition
the active window (the Stack window) on the screen. Next, hold
Shift down and use the arrow keys to adjust the size of the

Chapter 3, A quick example 47


window. Press Enter when you have defined a new size and
position that you like.
Now, to prepare for the next section, remove the Stack window by
pressing Alt-F3. Then continue with the next section.

Using the C demo program


The filled arrow(.-) in the left column of the Module window
shows where TDW stopped your program. Since you haven't run
your program yet, the arrow is on the first line of the program.
Press Fl to trace a single source line. The arrow and cursor are
now on the next executable line.
Look at the right margin of the Module window title. It shows the
line that the cursor is on. Move the cursor up and down with the
arrow keys and notice how the line number in the title changes.
To position the cursor on a As you can see from the Run menu, there are a number of ways to
line in the Module window,
control the execution of your program. Let's say you want to
press Ctrl-G, type the line
number, and press Enter. execute the program until it reaches line 48.
First, position the cursor on line 39, then press F4 to run the
program up to (but not including) line 39. Now press Fl, which
executes one line of source code at a time; in this case, it executes
line 39, a call to the function showargs. The cursor immediately
jumps to line 151, where the definition of showargs is found.
Continuing to press Fl would step you through the function
showargs and then return you to the line following the call-line
40. Instead, press Alt-FB, which causes showargs to execute and
then return, at which point the program stops. This command too,
returns you to line 40, and is very useful when you want to jump
past the end of a function.
If you had pressed FB instead of Fl on line 39, the cursor would
have gone directly to line 40 instead of into the function. FB is
similar to Fl in that it executes a procedure or source line, but it
skips any function calls.

48 Turbo Debugger for Windows User's Guide


Figure 3.5
Program stops on return from lm[~.!o~~umtUf1~il~e~:~td!ci!~m!o~'.c~4fca!!!!~!·!!·!!~!!!~L\ll!!!•!!!~["tJ1~~~~
function showargs nwords = O; •
tota 1characters = 0;
showargs (argc, ar~v);
while (readaline() != 0) {
wordcount = makei ntowords (buffer);
nwords += wordcount;
I•
total characters += ana lyzewords (buffer);
nlines++;
}
printstatistics(nlines, nwords, totalcharacters);
r-:it11rn{Q):

/*make the buffer into a list of null-terminated words that end in


* in two nulls, squish out white space
*/
static int makeintowords(char *bufp)
unsi ned int nwords;

To execute the program until a specific place is reached, you can


directly name the function or line number, without moving the
cursor to that line in a source file and then running to that point.
Press Alt-F9 to specify a label to run to. A dialog box appears. Type
readaline and press Enter. The program runs, then stops at the
beginning of function readaline (line 142).

Setting
breakpoints Another way to control where your program stops running is to
set breakpoints. The simplest way to set a breakpoint is with the
[ill F2 key. Move the cursor to line 44 and press F2. TDW highlights
the line, indicating there is a breakpoint set on it.
You can also use the mouse to toggle breakpoints by clicking the
first two columns of the Module window.

Chapter 3, A quick example 49


Figure 3.6
A breakpoint at line 44 •511FllmE!aVlmf<l!llmllliiii&ri•iiiiMW1i1W411'1!11'1 1-jf(l~EADY

I
r,=[iJ=MOOiiTe: TDDEMO Fire;=tddemo.c 4 l=LfJ [+]=;i
nwords = 0; •
totalcharacters = O;
showargs(argc, ar9v);
while (readal ine() != O) (
wordcount = makei ntowords (buffer); •
nwords += wordcount;
tota lcharacters += ana lyzewords (buffer);
.. nlines++;
I
pri ntstati sti cs (nl i nes, nwords, totalcharacters);
return (0);

/*make the buffer into a list of null-tenninated words that end in


* in two nulls, squish out white space
*/
static int makeintowords(char *bufp) {

=====
G ~


Now press F9 to execute your program without interruption. The
screen switches to the program's display. The demo program is
now running and waiting for you to enter a line of text. Type abc,
a space, def, and then press Enter. The display returns to the TDW
screen with the arrow on line 44, where you set a breakpoint that
has stopped the program. Now press F2 again to toggle it off.
See Chapter 7 for a complete description of breakpoints, including
conditional and global breakpoints.

Using watches
The Watches window at the bottom of the screen shows the value
[]D[]QJ of variables you specify. For example, to watch the value of the
variable nwords, move the cursor to the variable name on line 42
and choose Watch from the Module window local menu (bring it
up with A/t-F10 or the right-hand mouse button, or use the shortcut
Ctrl-W).

50 Turbo Debugger for Windows User's Guide


Figure 3.7
A C variable in the Watches

I
[• ,.f.lodu e: TDDEMO Fi e: tddemo.c 4 l=lfJ [+]=;i
window nwords = O; '"
total characters = 0;
showargs(argc, ar9v);
while (readaline(J I= O) {
wordcount = makeintowords(buffer);
nwords += wordcount;
total characters += anal yzewords (buffer);
""' nlines++;
}

l
printstati sti cs(nl ines, nwords, totalcharacters);
return(O);

~* make the buffer into a list of null-terminated words that end in


* in two nulls, squish out white space
*/
static int makei ntowords (char *bufp) {
unsi ned int nwords;

nwords now appears in the Watches window at the bottom of the


screen, along with its type (unsigned int) and value. As you
execute the program, TOW updates this value to reflect the
variable's current value.

Examining simple
C data objects Once you have stopped your program, there are a number of
ways of looking at data using the Inspect command. This facility
lets you examine data structures in the same way that you
visualize them when you write a program.
The Inspect commands (in various local menus and in the Data
menu) let you examine any variable you specify. Suppose you
want to look at the value of the variable nlines. Move the cursor so
it is under one of the letters in nlines and choose Inspect from the
Module window local menu (press Ctr/-/). An Inspector window
pops up.

Chapter 3, A quick example 51


Figure 3.8
An Inspector window -a:.111~li
..----- o u e: T
nwords = O;
'!ltl•11·~--···
Fi\lt
tota lcharacters = 0;
showa1s(argc, arr);
l.c A

while readaline( I• 0) {
... 1-
lEADY

wordcount • makeintowords(buffer);
nwords += wordcount;
.. totalcharacters +• analyiewords(buffer);
nlines++;

}~ ers);
printstati fil793E:FFCO
return(O);
}

/*make the buffer into a list of null-tenninated words that end in


* in two nulls, squish out white space
•/
static int makeintowords(char *bufp) {
unsigned int nwords;

liSii
F F3M1lf4l!l!!Pf
uiii:Uilb\nt;;u
' ' F•"'!,'Jlmfl
,,21
The title tells you the variable name; the next line shows you its
address in memory. The third line shows you what type of data is
stored in nlines (it's a C unsigned int). To the right is the current
value of the variable.
Now, having examined the variable, press Esc to close the
Inspector window. You can also use Alt-F3to remove the Inspector
window, just like any other window, or you can click the close
box with your mouse.
Let's review what you actually did here. By pressing Ctr/, you took
a shortcut to the local menu commands in the Module window.
Pressing I specified the Inspect command.
To examine a data item that is not conveniently displayed in the
Module window, choose Data IInspect. A dialog box appears,
asking you to enter the variable to inspect. Type :ietterinfo and
press Enter. An Inspector window appears, showing the values of
the letterinfo array elements. The title of the Inspector window
shows the name of the data you are inspecting. The first line
under the title is the address in main memory of the first element
of the array letterinfo. Use the arrow keys to scroll through the 26
elements that make up the letterinfo array. The next section shows
you how to examine this compound data object.

52 Turbo Debugger for Windows User's Guide


Examining
compound C A compound data object, such as an array or structure, contains
data objects multiple components. Move to the fourth element of the letterinfo
array (the one indicated by [3J). Press Alt-F10to bring up the local
menu for the Inspector window, then press I to choose Inspect. A
new Inspector window appears, showing the contents of that
element in the array. This Inspector window shows the contents
of a structure cf type !info.
Figure 3.9
-=·m~e·'·''''I.·-··
READY
Inspecting a structure o u e: TDDEM Fi e: t emo.c 4
nwords = O;
totalcharacters = 0;
showargs(argc, ar9v);
while (readaline() != 0)
wordcount = mak
nwords += wordc
tota lcharacters
• nlines++;
)
pri ntstati sti cs (n 1i nes,
return(O);

/* make the buffer into a list of


* in two nulls, squish out white
*/
static int makeintowords(char *buf ~•
unsigned int nwords;

When you place the cursor over one of the member names, the
data type of that member appears in the bottom pane of the
Inspector window. If one of these members were in turn a com-
pound data object, you could issue an Inspect command and dig
down further into the data structure.
Press Alt-F3 to remove both Inspector windows and return to the
Module window. (Alt-F3 is a convenient way of removing several
Inspector windows at once. If you had pressed Esc, only the latest
Inspector window would have been deleted.)

Changing C data
values So far, you've learned how to look at data in the program. Now,
let's change the value of data items.
Use the arrow keys to go to line 38 in the source file. Place the
cursor at the variable totalcharacters and press Ctr/-/ to inspect its

Chapter 3, A quick example 53


value. With the Inspector window open, press Alt-F10to bring up

-
the Inspector's local menu, and choose the Change option. (You
could also have done this directly by pressing Ctr/-C.) A dialog box

.........,_.
appears, asking for the new value.
Figure 3.10
The Change dialog box odule: rnoEMOfi:tdd:o.c 3
static void showargs(int argc, char *argv[]);

total characters += analyzewords(buffer);


nlines++;

Enter item prompted for in dialog title

At this point, you can enter any C expression that evaluates to a


number. Type totalcharacters + 4 and press Enter. The value in the
Inspector window now shows the new value, 101 (OxA).
To change a data item that isn't displayed in the Module window,
choose Data I Evaluate/Modify. A dialog box appears. Enter the
name of the variable to change in the first input box: Type nlines
and press Enter. Then press Tab twice to move to the input box
labeled New Value. Type 123 and press Enter. The result (second
box) changes to int 123 (Ox7B).

54 Turbo Debugger for Windows User's Guide


Figure 3.11
The Evaluate/Modify dialog
box
Eva 1uate/modi f

That's a quick introduction to using TOW with a program written


using Turbo C++ for Windows. Chapter 14 offers a more
extensive debugging sample.

Chapter 3, A quick example 55


56 Turbo Debugger for Windows User's Guide
c H A p T E R

Starting TOW
This chapter tells you how to prepare programs for debugging.
We show you how to start TOW from Windows and how to tailor
its many command-line options to suit the program you are
debugging. We explain how to make these options permanent in a
configuration file and, finally, how to return to Windows when
you are done.

Preparing programs for debugging


When you compile and link with Turbo C++ for Windows, you
can tell the compiler to generate full debugging information. If
you have compiled your program's object modules without any
debugging information, be sure to recompile them with debug-
ging information before invoking TOW.
If you need to recompile your modules with debugging informa-
tion, it's possible to generate debug information only for specific
modules (you might have to do this if you're debugging a large
program), but you will find it annoying later to enter a module
that doesn't have any debug information available. We suggest
recompiling all modules.
If you're using the integrated environment of Turbo C++ for
Windows, the generation of debug information is turned on by
default. If these options have been turned off, you need to do the
following before compiling to produce debug information:

Chapter 4, Starting TOW 57


1. Use the Options I Linker I Settings command to bring up the
Linker Settings window, then check the Include Debug
Information check box.
2. Use the Options I Compiler I Advanced Code Generation
command to bring up the Advanced Code Generation
window, then check the Debug Info in OBJs check box.
Alternatively, you can use the options -v pragma directive to
add debug information to each of your modules by inserting
the following line at the beginning of each module:
#pragma option -v

Starting TDW
There are four ways to run TOW:
•If you are in Turbo C++ for Windows, you can debug the
program in the active window by choosing Run I Debugger.
You can also choose Run I Debugger Arguments if you want to
set TOW command-line arguments.
• If you are in Windows, the easiest method is to open the
appropriate program group in the Windows Program Manager
and choose the TOW icon. Then choose File I Open to load the
program you're debugging.
For this and the next option, unless TOW is in your path and
warning! your program is in your Windows directory, you must be
careful to type in the correct path for both TOW and your
application.
• If you are in Windows and you want to enter command-line
options, you can start TOW by using the Windows Program
Manager File I Run command to open the Run dialog box. Then,
in the Command Line input box, just type TDW, followed by any
command-line options and, optionally, the name of the
program you're debugging, as if you were at the DOS prompt.
• If you are at the DOS prompt, you can start TOW by entering
the following and pressing Enter:
WIN TOW [options] [progname [progargs]]

58 Turbo Debugger for Windows User's Guide


Entering
command-line If you start TOW from the DOS prompt or by using the Program
options Manager File I Run command, you can add command-line options
after typing TDW.
If you start TOW from Turbo C ++ for Windows, you can enter
command-line options by choosing Run IDebugger Arguments.

Directly entering The generic command-line format is


command-line options
TDW [options] [progname [progargs]]

The items enclosed in brackets are optional; if you include any,


type them without the brackets. Progname is the name of the pro-
gram to debug.
You can follow a program name with arguments. Here are some
sample command lines:

Command Action
tdw -tc:\progl progl ab Starts the debugger in the C:\PROGl
directory and loads program progl
with two command-line arguments, a
andb.
tdw prog2 -x Starts the debugger with default
options and loads program prog2
with one argument, -x.

If you simply type TDW Enter, TDW loads and uses its default
options.

Entering command-line If you start TOW from Turbo C++ for Windows and you want to
options from TCW indicate command-line options, chose Run IDebugger Arguments
to enter any TOW command-line options except the program
name and program arguments.
The program to be run in TOW is the one in the current Edit
window. If you want to enter arguments for the program before
running TOW on it, choose Run IArguments and type the
arguments in the Program Arguments window.

Chapter 4, Starting TOW 59


Things to remember When you run a program in TDW, you need to have both its .EXE
file and the original source files available. TDW searches for
source files first in the directory the compiler found them in when
it compiled, second in the directory specified in the Options I Path
for Source command, third in the current directory, and fourth in
the directory the .EXE file is in.
¢ You must already have compiled your source code into an
executable (.EXE) file with full debugging information turned on
before debugging with TDW.
¢ TDW works only with Windows programs compiled with a
Borland compiler.
¢ If you're running your program from Windows and notice a bug,
you have to exit your program and load it under TDW before you
can begin debugging.

Running TOW
When you run TDW, it comes up in full-screen character mode,
not in a window. Despite this appearance, TDW is a Windows
application and will run only under Windows.
Unlike other applications that run under Windows, you can't use
the Windows shortcut keys (like Alt-Esc or Ctrl-Esc) to switch out of
the TDW display and run another program. However, if the appli-
cation you are debugging is active (the cursor is active in one of
its windows), you can use Alt-Esc, Ctrl-Esc, or the mouse to switch
to other programs.
¢ If you do use Ctrl-Esc to switch out of an application running
under TDW, you see the application name on the list of tasks. You
will never see TDW on the task list because TDW is not a normal
Windows task that you can switch into or out of.

Command-line options
Appendix A has an easy-to- All TDW command-line options start with a hyphen(-) and are
use list of TDW:S command-
separated from the TDW command and each other by at least one
line options.
space. You can explicitly turn a command-line option off by
following the option with another hyphen. For example, -p-

60 Turbo Debugger for Windows User's Guide


disables the mouse. Turning a command-line option off works
even if an option has been permanently enabled in the configu-
ration file. You can modify the configuration file by using the
TDWINST configuration program described in the file
TDWINST.DOC.
The following sections describe all available TDW command-line
options.

Loading the
configuration file This option loads the specified configuration file. There must not
(-C) be a space between -c and the file name.
If the -c option isn't included, TDCONFIG.TDW is loaded if it
exists. Here's an example:
TDW -cMYCFG.TDW TDDEMO
This command loads the configuration file MYCONF.TDW and
the source code for TDDEMO.

Display updating
(-d) The -d options affect the way in which display updating is
performed.
-do Runs TDW on your secondary display. View your pro-
gram's screen on the primary display, and run the
debugger on the secondary one.
-ds The default option for all displays, it's also called screen
swapping. Required for a monochrome display. Maintains
a separate screen image for the debugger and the
program being debugged by loading the entire screen
from memory each time your program is run or the de-
bugger is restarted. This technique is the most time-
consuming method of displaying the two screen images,
but works on any display hardware and with programs
that do unusual things to the display.

Getting help (-h


and-?) These options display a window that describes TDW's command-
line syntax and options.

Chapter 4, Starting TOW 61


Assembler-mode
startup (-1) This option forces startup in assembler mode, showing the CPU
window. TDW does not execute your program's startup code,
which usually executes automatically when you load your
program into the debugger. This means that you can step through
your startup code.
If you are debugging a DLL, this option also allows you to debug
the assembly-language code that starts up the DLL. See Chapter
11, page 173, for more information on debugging DLLs.

Mouse support
(-p) This option enables mouse support. However, since the default
for mouse support in TDW is On, you won't have much use for
the -p option unless you use TDWINST to change the default to
Off. If you want to disable the mouse, use -p-.
If the mouse driver is disabled for Windows, it will be disabled
for TDW as well, and the -p command-line option will have no
effect.

Source code
handling (-s)
-SC Ignores case when you enter symbol names, even if your
program has been linked with case sensitivity enabled.
Without the -sc option, Turbo Debugger ignores case
only if you've linked your program with the case ignore
option enabled.
This option doesn't change -sd Sets one or more source directories to scan for source files;
the starting directory. the syntax is
-sddirname[;dirname ... ]

To set multiple directories, use multiple dirnames sepa-


rated with semicolons (;) with the -sd option or use the
-sd option repeatedly or both. TDW searches for
directories in the order specified. dirname can be a relative
or absolute path and can include a disk letter. If the
configuration file specifies any directories, the ones
specified by the -sd option are added to the end of that
list.

62 Turbo Debugger for Windows User's Guide


Starting directory
(-t) This option changes TOW's starting directory, which is where
TOW looks for the configuration file and for .EXE files not
specified with a full path. There must not be a space between the
option and the directory path name.
-t<dir> Set the starting directory to <dir>. The syntax is
-tdirname
You can set only one starting directory with this option. If you
enter multiple directories for one -t option, TOW ignores all the
directories. If you enter the option more than once on the same
command line, TOW uses only the last entry.
For example, the following entry would start TOW in the
0: \WORKING directory:
tdw -tc:\utils\screensv -td:\working

Configuration files
See the file TDWlNST. TDW for TOW uses a configuration file to override built-in default values
a description of how to use
TDWlNST to create
for command-line options. You can use TOWlNST to set the
configuration files. options that TOW will default to if there is no configuration file.
You can also use it to build configuration files.
TOW looks for the configuration file TOCONFIG.TOW first in the
current directory, next in the TOW directory set up with the
Turbo C++ for Windows installation program, and then in the
directory that contains TOW.EXE.
If TOW finds a configuration file, the settings in that file override
its built-in defaults. Any command-line options that you supply
when you start TOW from DOS override both the corresponding
default options and any corresponding values in
TDCONFIG.TOW.

Chapter 4, Starting TOW 63


The Options menu
Language... Source The Options menu lets you set or adjust a number of parameters
Macros " that control the overall appearance and operation of TOW. The
Display options •••
Path for source ••• following sections describe each menu command and refer you to
Save options ••• other sections of the manual where you can find more details.
Restore options •••

The Language
command Chapter 9 describes how to set the current expression language
and how it affects the way you enter expressions.

The Macros menu


Create Alt= The Macros command displays another menu that lets you define
Stop recording Alt- new keystroke macros or delete ones that you have already
Remove ••• assigned to a key. It has the following commands: Create, Stop
Delete all
Recording, Remove, and Delete All.

Create When issued, the Create command starts recording keystrokes


into an assigned macro key. As an alternative, press the Alt= (Alt-
Equal) hot key for Create.
When you choose Create to start recording, a prompt asks for a
key to assign the macro to. Respond by typing in a keystroke or
combination of keys (for example, Shift-F9). The message RECORDING
will be displayed in the upper right comer of the screen while you
record the macro.

Stop Recording The Stop Recording command terminates the macro recording
session. Use the Alt- (Alt-Hyphen) hot key to issue this command
or press the macro keystroke that you are defining to stop
recording.
¢ Do not use the Options I Macro IStop Recording menu selection to
stop recording your macro, as these keystrokes will then be added
to your macro! (The menu item is added to remind you of the Alt-
hot key.)

64 Turbo Debugger for Windows User's Guide


Remove Displays a dialog box listing all current macros. To delete a
macro, select one from the list and press Enter

Delete All Removes all keystroke macro definitions and restores all keys to
the meaning that they originally had.

Display Options
command This command opens a diaiog box in which you can set several
options that control the appearance of the TDW display.
Figure 4.1
. . .FllmmllmVll!lm. .B!Wainii#Mllm!llC~Hllii•PROMPT
The Display Options dialog [iJ=MoiliiTe7"11iiiEMOrfle: TOOEMIT.c 3r.;;;;;;,. 1 Lt] [•J=n
box static void showargs (int argc, char •argv []);
/• program entry point
•/
.. int PASCAL WinMain(HAND
LPST

Display Swapping The Display Swapping radio buttons let you choose from two
ways of controlling how the User screen gets swapped back and
forth with TDW's screen:
Smart Swap to the User screen only when display output may
occur. TDW swaps the screens any time that you step
over a routine.
Always Swap to the User screen every time the user program
runs. Use this option if the Smart option is not catching
all the occurrences of your program writing to screen.
If you choose this option, the screen flickers every time
you step through your program because TDW's screen
is replaced for a short time with the User screen.

Chapter 4, Starting TOW 65


Integer Format These radio buttons let you choose from three display formats for
displaying integers:
Hex Shows integers as hexadecimal numbers, displayed in
a format appropriate to the current language.
Decimal Shows integers as ordinary decimal numbers.
Both Shows integers as both decimal numbers and as hex
numbers in parentheses after the decimal value.

Screen Lines These radio buttons are used to determine whether TDW's screen
uses the normal 25-line display or the 43- or SO-line display
available on EGA and VGA display adapters.

Tab Size This input box lets you set how many columns each tab stop
occupies. You can reduce the tab column width to see more text in
source files that have a lot of code indented with tabs. You can set
the tab column width from 1 to 32.

Path for Source


command Sets the directories that TOW searches for your source files. See
the discussion of the Module window in Chapter 8 for more
information.

Save Options
command This command opens a dialog box from which you can save your
current options to a configuration file on disk. The options you
can save are
•your macros
• the current window layout and pane formats
• all settings made in the Options menu

66 Turbo Debugger for Windows User's Guide


Figure 4.2
The Save Options dialog box

I• program entry point


•/
LPSTR lpszCmdLine,
unsigned int nl ines, nwords,
1•
• int PASCAL WinMain(HANDLE hlnstance, HANDLE hPrevinstance,
=Save Confi uratio
pt ions
unsigned long totalcharacters; Layout . .lliii. .
Macros
ln1tWinCrt();
iil ines = O;
nwords = O;
total characters = O;
showarQs( argc, argv};
while (readalineTJ != O) {
wordcount = makei ntowords buffer};

TDW lets you save your options in any or all of these ways,
depending on which of the Save Configuration check boxes you
turn on:
Options Saves all settings made in the Options menu.
Layout Saves only the windowing layout.
Macros Saves only the currently defined macros.
You can also use the Save To input box to change the name of the
configuration file to which you are saving the options.

Restore Options
command Restores your options from a disk file. You can have multiple
configuration files, containing different macros, window layouts,
and so forth. You must choose a configuration file that was
created with the Save Options command or with TDWINST.

Returning to Windows
You can end your debugging session and return to the Windows
Program Manager at any time by pressing Alt-X, except when a
dialog box is active (in that case, first close the dialog box by
pressing Esc). You can also choose File IQuit.

Chapter 4, starting TOW 67


68 Turbo Debugger for Windows User's Guide
c H A p T E R

Controlling program execution


When you debug a program, you usually execute portions of it
and check at a stopping point to see that it is behaving correctly.
TDW gives you many ways to control your program's execution.
You can
• execute single machine instructions or single source lines
•skip over calls to functions or procedures
•"animate" the debugger (perform continuous tracing)
•run until the current function or procedure returns to its caller
• run to a specified location
•continue until a breakpoint is reached
• reverse program execution
A debugging session consists of alternating periods when either
your program or the debugger is running. When the debugger is
running, you can cause your program to run by choosing one of
the Run menu's command options or pressing its hot key equiva-
lent. When your program is running, the debugger starts up again
when either the specified section of your program has been exe-
cuted, or you interrupt execution with a special key sequence, or
TDW encounters a breakpoint.
This chapter shows you how to examine the state of your pro-
gram whenever TDW is in control. You'll see various ways to
execute portions of your program, and also how to interrupt your
program while it's running. Finally, you'll learn the ways you can

Chapter 5, Controlling program execution 69


restart a debugging session, either with the same program or with
a different program.

Examining the current program state


The "state" of your program consists of the following elements:
• its command-line arguments
•the stack of active functions or procedures
• the current location in the source code or machine code
• register values
• the contents of memory
•the reason the debugger stopped your program
• the value of your program data variables
The following sections explain how to use the Variables window,
the Stack window, the local menus of the Global and Static panes,
and the Origin and Get Info commands. See Chapter 6 for more
information on how to examine and change the values of your
program data variables.

The Variables
window You open the Variables window by choosing View I Variables.
This window shows you all the variables (names and values) that
are accessible from the current location irt your program. Use it to
find variables whose names you can't remember. You can then
use the local menu commands to further examine or change their
values. You can also use this window to examine the variables
local to any function that has been called.
Figure 5.1
CRTWINPROC$QUIUIUIL ""
The Variables window

11------1
CreateWinCrt$qv ????
Ex i tWinCrt$qv "??
In1 tWinCrt$qv ""
EGINPAINT ""
REATECAREI ""
RfA TEW I NDOh " 77

anal yzeviords @OA25: 0205


printstat1st1cs @OA25.027D
readaline @OA25:0378
sh01,args @OA25. 03A8
buffer "ABC\ODEF\ 0\0\0\0\ 0\ 0\0\ 0\ 01 0 10\0\ 0\0\
VJordcounts 10,0,2,0,0,0,0,0,0,0}

The Variables window has two panes:

70 Turbo Debugger for Windows User's Guide


•The Global pane (top) shows all the global symbols in your
program.
•The Static pane (bottom) shows all the static symbols in the
current module (the module containing the current program
location, CS:IP) and all the symbols local to the current
function.
Both panes show the name of the variable at the left margin and
its value at the right margin. If TD\V can't find any data type
information for the symbol, it displays four question marks(????).
Press Alt-F10 (as with all local menus) to pop up the Global pane's
local menu. If control-key shortcuts are enabled, you can also
press Ctr/ with the first letter of the desired command to access it.
If your program contains routines that perform recursive calls, or
if you want to view the variables local to a function that has been
called, you can examine the value of a specific instance of a func-
tion's local data. First create a Stack window with View I Stack,
then move the highlight to the desired instance of the function
call. Next, press Alt-F10 and choose Locals. The Static pane of the
Variables window then shows the values for that specific instance
of the function.

The Global pane local This local menu consists of three commands: Inspect, Change, and
menu Watch.

Inspect

Inspect Opens an Inspector window that shows you the contents of the
Change ..• currently highlighted global symbol.
Watch
If the variable you want to inspect is the name of a function, you
are shown the source code for that function, or if there is no
source file, a CPU window shows you the disassembled code.
See Chapter 6 for more If the variable you inspect has a name that is superseded by a
information on how Inspector
local variable with the same name, you'll see the actual value of
windows behave.
the global variable, not the local one. This characteristic is slightly
different than the usual behavior of Inspector windows, which
normally show you the value of a variable from the point of view
of your current program location (CS:IP). This difference gives
you a convenient way of looking at the value of global variables
whose names are also used as local variables.

Chapter 5, Controlling program execution 71


Change
See Chapter 9 for more Changes the value of the currently selected (highlighted) global
information on assignment symbol to the value you enter in the Change dialog box. TDW
and data type conversion.
performs any necessary data type conversion exactly as if the
assignment operator for your current language had been used to
change the variable.
You can also change the value of the currently highlighted symbol
by opening the Inspector window and typing a new value. When
you do this, the same dialog box appears as if you had first
specified the Change command.

Watch
See Chapter 6 for more Opens a Watches window and puts the currently selected
information on the Watches (highlighted) global symbol in the window. This command
window.
simply puts a character string in the Watches window.
The Watches window doesn't keep track of whether the variable
is local or global. If you insert a global variable using the Watch
command and later encounter a local variable by the same name,
the local variable takes precedence as long as you are in the local
variable's block. In other words, the Watches window always
shows you the value of a variable from the point of view of your
current program location (CS:IP).

The Static pane local Press the Alt-F10 key combination to pop up the Static pane's local
menu menu; if control-key shortcuts are enabled, use the Ctr/ key with
the first letter of the desired command to access it.

Inspect The Static pane has four local menu commands: Inspect, Change,
Change •.• Watch, and Show.
Watch
Show •••

Inspect
See Chapter 6 for more Opens an Inspector window that displays the contents of the
information on how Inspector
windows behave.
currently highlighted module's local symbol.

Change
See Chapter 9 for more Changes the value of the currently selected (highlighted) local
information on assignment
symbol to the value you enter in the Change dialog box. TDW
and data type conversion.
performs any data type conversion necessary, exactly as if the
assignment operator had been used to change the variable.

72 Turbo Debugger for Windows User's Guide


You can also change the value of the currently highlighted symbol
by opening the Inspector window (see previous command) and
starting to type a new value. When you do this, the same dialog
box appears as if you had first specified the Change command.

Watch
See Chapter 6 for more The Watch command opens a Watches window and puts the
!r:farmat!ar: or: how ~A/atches
windows behave.
currentiy seiected (h1ghhghted) static or iocal symbol in the
window.

Show
Choosing Show brings up the Local Display dialog box, which
enables you to change both the scope of the variables being
shown (static, auto, or both) and the module from which these
variables are selected.
The following radio buttons appear in this dialog box:
Static Show only static variables.
Auto Show only variables local to the current block.
Both Show both types of variables (the default).
Module Change the current module. Brings up a dialog box
showing the list of modules for the program, from
which you can select a new module.

Figure 5.2
The Local Display dialog box

The Stack window


You create a Stack window by choosing View I Stack. The Stack
window lists all active functions or procedures. The most recently
called routine is displayed first, followed by its caller and the
previous caller, all the way back to the WinMain function. For each
function, you see the value of each parameter it was called with.

Chapter 5, Controlling program execution 73


Figure 5.3
The Stack window

The Stack window likewise displays the names of member


functions, each of which is prefixed with the name of the class
that defines the member function:
SHAPES::ACIRCLE(174, 360, 75.0) /* C++ */
Press Alt-F10 to pop up the Stack window local menu, or press Ctr/
with the first letter of the desired command to access it.

The Stack window local The Stack window local menu has two commands: Inspect and
menu Locals.
Inspect
Locals
Inspect
Opens a Module window positioned at the active line in the
currently highlighted function. If the highlighted function is the
top (most recently called) function, the Module window shows
the current program location (CS:IP). If the highlighted function is
one of the functions that called the most recent function, the
cursor is positioned on the line in the function that will be
executed after the called function returns.
You can also invoke this command by positioning the highlight
bar over a function, then pressing Enter.

Locals
Opens a Variables window that shows the symbols local to the
current module, as well as the symbols local to the currently high-
lighted function. If a function calls itself recursively, there are
multiple instances of the function in the Stack window. By posi-
tioning the highlight bar on one instance of the function, you can
use this command to look at the local variables in that instance.

74 Turbo Debugger for Windows User's Guide


The Origin local
menu command Both the Module window and the Code pane of a CPU window
have an Origin command on their local menus. Origin positions
the cursor at the current code segment (CS:IP). This is very useful
when you have been looking at your code and want to get back to
where your program stopped.

The Get info


command You can choose File I Get Info to look at memory use and to
determine why the debugger gained control. This command
produces a text box that disappears when you press Enter,
Spacebar, or Esc.

Figure 5.4
The Get Info text box

The following information appears in the System Information


box:
•The name of the program you're debugging.
•A description of why your program stopped.
• Information about the global memory on your system.
•The DOS version you're running.
• The current date and time.

Global memory TOW provides you with the following information about global
information memory:
Mode Memory modes can be large-frame EMS, small-
frame EMS, and non-EMS (extended memory).

Chapter 5, Controlling program execution 75


Banked The amount in kilobytes of memory above the EMS
bank line (eligible to be swapped to expanded
memory if the system is using it).
Not banked The amount in kilobytes of memory below the EMS
· bank line (not eligible to be swapped to expanded
memory).
Largest The largest contiguous free block of memory, in
kilobytes.

Status line messages Here are the messages you'll see on the second (status) line,
describing why your program stopped:
Stopped at_
Your program stopped as the result of a completed Run I
Execute To, Run IGo to Cursor, or Run IUntil Return
command. This status line message also appears when your
program is first loaded, and the compiler startup code in your
program has been executed to put you at the start of your
source code.
No program loaded
You started TOW without loading a program. You cannot
execute any code until you either load a program or assemble
some instructions using the Assemble local menu command in
the Code pane of a CPU window.
Trace
You executed a single source line or machine instruction with
F7 (Run ITrace).
Step
You executed a single source line or machine instruction,
skipping function calls, with FB (Run IStep Over).
Breakpoint at _
Your program encountered a breakpoint that was set to stop
your program. The text after "at" is the address in your pro-
gram where the breakpoint occurs.
Window message breakpoint at_
Your program encountered a Windows message breakpoint
that was set to stop your program. The text after "at" is the
window procedure the message was destined for.

76 Turbo Debugger for Windows User's Guide


Terminated, exit code_
Your program has finished executing. The text after "code" is
the numeric exit code returned to Windows by your program.
If your program does not explicitly return a value, a garbage
value might be displayed. You cannot run your program until
you reload it with Run I Program Reset.
Loaded
You either reset )Tour program or loaded TD\A/ and specified
both a program and the option that prevents the compiler
startup code from executing. Because no instructions have
been executed at this point, including those that set up your
stack and segment registers, if you try to examine certain data
in your program, you might see incorrect values.
Interrupt
You pressed the interrupt key (Ctrl-Alt-SysRq) to regain control.
Your program was interrupted and control passed back to the
debugger.
Exception_
A processor exception has occurred, which usually happens
when your program attempts to execute an illegal instruction
opcode. The Intel processor documentation describes each
exception code in complete detail.
The most common exception to occur with a Windows
program is Exception 13. This exception indicates that your
program has attempted to perform an invalid memory access.
(Either the selector value in a segment register is invalid or the
offset portion of an address points beyond the end of the
segment.) You must correct the invalid pointer causing the
problem.
Divide by zero
Your program has executed a divide instruction where the
divisor is zero.
Global breakpoint_ at_
A global breakpoint has been triggered. You are told the
breakpoint number and the location in your program where
the breakpoint occurred.

Chapter 5, Controlling program execution 77


The Run menu
The Run menu has a number of options for executing different
parts of your program. Since you use these options frequently,
most are available on function keys.
Run F9
Go to cursor F4
Trace into F7
Step over F8
Execute to ... Alt-F9
Until return Alt-F8
Animate •••
Back trace Alt-F4
Instruction trace Alt-F7
Arguments ...
Program reset Ctrl-F2

Run
Runs your program at full speed. Control returns to TDW when
[ff] one of the following events occurs:
•Your program terminates.
•A breakpoint with a break action is encountered.
•You interrupt execution with Ctrl-Alt-SysRq.

Goto Cursor
Executes your program up to the line that the cursor is on in the
current Module window or CPU Code pane. If the current
window is a Module window, the cursor must be on a line of
source code.

Trace Into
Executes a single source line or assembly level instruction. If the
current window is a Module window, a single line of source code
is executed; if it's a CPU window, a single machine instruction. If
the current line contains any function calls, TDW traces into the
routine. If the current window is a CPU window, pressing Fl on a
CALL instruction steps to the routine being called
Turbo Debugger treats a class member function just like any other
function. Fl traces into the source code if it's available.

78 Turbo Debugger for Windows User's Gulde


Step Over
Executes a single source line or machine instruction, skipping
over any function calls. If the current window is a Module
window, this command usually executes a single source line. If
the current window is a CPU window, pressing FB on a CALL
instruction steps over the routine being called.
If you step over a single source line, TOW treats any function calls
in that line as part of the line. You don't end up at the start of one
of the functions. Instead, you end up at the next line in the current
routine or at the previous routine that called the current one.
If you are in a CPU window, TOW treats certain instructions as a
single instruction, even when they cause multiple assembly
instructions to be executed. Here is a complete list of the
instructions TOW treats as single instructions:
CALL Subroutine call, near, and far
INT Interrupt call
LOOP Loop control with CX counter
LOOPZ Loop control with CX counter
LOOPNZ Loop control with CX counter
Also stepped over are REP, REPNZ, or REPZ followed by CMPS,
CMPS, CMPSW, LODSB, LODSW, MOVS, MOVSB, MOVSW,
SCAS, SCASB, SCASW, STOS, STOSB, or STOSW.
The Run I Step Over command treats a call to a class member
function like a single statement, and steps over it like any other
function call.

Execute To
Executes your program until the address you specify in the dialog
box is reached. The address you specify might never be reached if
a breakpoint action is encountered first or you interrupt
execution.

Until Return
Executes until the current function returns to its caller. This is
useful in two circumstances: When you have accidentally exe-
cuted into a function you aren't interested in with Run I Trace
instead of Run I Step, or when you've determined that the current

Chapter 5, Controlling program execution 79


procedure works to your satisfaction, and you don't want to
slowly step through the rest of it.

Animate
Performs a continuous series of Trace Into commands, updating
the screen after each one. (The effect is to run your program in
slow motion.) You can watch the current location in your source
code and see the values of variables changing. Press any key to
interrupt this command.
After you choose Run I Animate, TOW prompts you for a time
delay between successive traces. The time delay is measured in
tenths of a second; the default is 3.

Back Trace
If you are tracing (F7 or Alt-Fl) through your program, Back Trace
reverses the order of execution. Reverse execution is handy if you
trace beyond the point where you think there may be a bug, and
want to reverse program execution back to that point. This feature
Some restrictions apply to lets you "undo" the execution of your program by stepping
using the Execution History
window. See page 82 for
backward through the code, either a single step at a time or to a
more information. specified point highlighted in the Execution History window.
Reverse execution is always available in the CPU window.
However, you can only execute source code in reverse if full
history is On. (Use the View I Execution History command to
bring up the Execution History window, then in the local menu
set Full History On.)
TOW will not execute in reverse any Windows code called by
your program unless you are in the CPU window and the code is
in a DLL you have selected for debugging.

Instruction Trace
Executes a single machine instruction. Use this command when
you want to trace into an interrupt, or when you're in a Module
window and you want to trace into a procedure or function that's
in a module with no debug information (for example, a library
routine).
Since you will no longer be at the start of a source line, this
command usually places you in a CPU window.

80 Turbo Debugger for Windows User's Guide


Arguments
This command lets you set new command-line arguments for
your program. For a discussion of this command, see "Changing
the program arguments" on page 86.

Program Reset
Reloads from disk the program you're debugging. You might use
.,_i..,.; ..... ,... ...... _...--~-....l
Ui..li.'.) LU.l.ll11la.tlU

•When you've executed past the place where you think there is a
bug.
•When your program has terminated and you want to run it
again.
•If you're in a Module or CPU window, you've suspended your
Windows application program with Ctr/-A/t-SysRq, and you want
to terminate it and start over.
•If you've already loaded your application, you've just set
startup debugging for one or more dynamic link libraries
(DLLs), and you now want to debug those DLLs.
If you're in a Module or CPU window, the debugger sets the
current-line marker at the start of the program, but the display
stays exactly where you were when you chose Program Reset.
This behavior makes it easier for you to set the cursor near where
you were and run the program to that line.
If you chose Program Reset because you just executed one source
statement more than you intended, you can position the cursor up
a few lines in your source file and press F4 to run to that location.
Alternatively, if Full History had been on (see the local menu of
the View I Execution History window), you could have chosen
Run I Back Trace to step back through previously executed code
instead of choosing Program Reset.

The Execution History window


TOW has a special feature called the execution history that keeps
track of each instruction as it's executed (provided that you're
tracing into the code). You can examine these instructions and, if
you wish, undo them to return to a point in the program where

Chapter 5, Controlling program execution 81


you think there might be a bug. TOW can record about 400
instructions.
Figure5.5
The Execution History window

You can examine the execution history in the Execution History


window, which you open by choosing View I Execution History.
The Execution History window shows instructions already
executed that you can examine or undo. Use the highlight bar to
make your selection.
¢ The execution history only keeps track of instructions that have
been executed with the Trace Into command (F7) or the Instruction
Trace command (Alt-F7). It also tracks for Step Over, as long as you
don't encounter one of the commands listed on page 79 or 83. As
soon as you use the Run command or execute an interrupt, the
execution history is deleted. (It starts being recorded again as
soon as you go back to tracing.)
¢ You cannot backtrace into an interrupt call.
¢ If you step over a function call, you will not be able to trace back
beyond the instruction following the return.
¢ Backtracing through a port-related instruction has no effect, since
you can't undo reads and writes.

The local menu


The local menu for the Instructions pane contains three options,
Inspect, Reverse Execute, and Full History.

Inspect
Reverse execute Inspect
Full history No This command takes you to the command highlighted in the
Instructions pane. If it is a line of source code, you are shown that
line in the Module window; if there is no source code, the CPU
window opens, with the instruction highlighted in the Code pane.

Reverse Execute
This command reverses program execution to the location
~[ill highlighted in the Instructions pane. If you selected a line of

82 Turbo Debugger for Windows User's Gulde


source code, you are returned to the Module window; otherwise,
the CPU window appears with the highlight bar of the Code pane
on the instruction.
Wamingl You can never reverse back over a section of your program that
you didn't trace through. For example, if you set a breakpoint and
then pressed F9 to run until the breakpoint was reached, all your
reverse execution history will be thrown away.
Wamlngl The INT instruction causes any previous execution history to be
thrown out. You can't reverse back over this instruction, unless
you press Alt-Fl to trace into the interrupt.
The following instructions do not cause the history to be thrown
out, but they cannot have their effects undone. You should be on
the lookout for unexpected side effects if you back up over these
instructions:
IN INSW
OUT OUTSB
INSB OUTSW

Full History
This command is a toggle. If it is set to On, backtracing is enabled.
If it is Off, backtracing is disabled.

Interrupting program execution


Because Windows applications are interactive programs, the best
way to debug one is to run the application and then interrupt it or
cause it to encounter a breakpoint.
As a primary debugging technique, stepping or tracing through a
Windows application can be of marginal utility because even-
tually you reach code that sits in a loop, waiting for a message for
a window. Instead, you should set code and message breakpoints
if possible, run your program until it encounters one of these
breakpoints, and then step or trace if necessary.
If you do step into the message loop, you can press the Alt-F5 key
combination to see the application screen, but you won't be able
to interact with the program. Instead, you can press F9 to run the
program so you can use the application's windows. But what
happens if you need to get back to TDW to track down a bug that
shows up while you're using one of your application's windows?

Chapter 5, Controlling program execution 83


What you can do is interrupt your program by pressing the Ctrl-
Alt-SysRq key combination. Once you're back in TDW, you can set
code or message breakpoints, set up view's, look at any messages
you might have been logging, or whatever else you need to do to
track the bug. When you're ready to return to the application
again, press F9 to run it.
¢ When you return to TDW, if you see a CPU window without any
lines corresponding to lines in your code, you're probably in
Windows code. You can display the Module window and set
breakpoints or whatever else you need to do, but there are some
things you should not do:
•Single-step through your program. Attempting to single-step
after interrupting your application can have unpredictable
effects if your application was executing Windows code. A
typical result is that Windows terminates both your application
and TDW, generating the message, "Unrecoverable application
error." ·
•Terminate or reload either your application or TOW. If you do,
Windows gets confused and hangs, forcing you to reboot. If
you do try to exit or reload in this situation, TOW displays the
following prompt in a dialog box:
Ctrl-Alt-SysRq interrupt, system crash possible, Continue?
At this point, the best course of action is to select No,
return to TDW and set a breakpoint you know your code will
hit, then run your application again and cause it to hit the
breakpoint and exit to TOW.

Program termination
When your program terminates and exits back to Windows, TDW
regains control. It displays a message showing the exit code that
your program returned to Windows. Once your program
terminates, using any of the Run menu options causes TDW to
reload your program.
The segment registers and stack are usually not correct when your
program has terminated, so do not examine or modify any pro-
gram variables after termination.

84 Turbo Debugger for Windows User's Guide


Restarting a debugging session
TDW has a feature that makes restarting a debugging session as
painless as possible. When you're debugging a program, it's easy
to go just a little too far and overshoot the real cause of the
problem. In that case, TDW lets you restart debugging but
suspends execution before the last few commands that caused
you to mlss the problem lhcti yuu wanted tu ubserve. How? Ii lets
you reload your last program from disk, and preserves any
previous command-line arguments.
To reload the program you were debugging, choose Run I Pro-
gram Reset (Ctrl-F2). TDW reloads the program from disk, with
any data you have added since you last saved to disk. Reloading
is the safest way to restart a program. Restarting by executing at
the start of the program can be risky, since many programs expect
certain data to be initialized from the disk image of the program.
¢ Program Reset leaves breakpoints and watchpoints intact.

Opening a new program to debug


You load a new program to debug by choosing File I Open to open
the Enter Program Name to Load dialog box.
Figure 5.6
The Enter Program Name to
Load dialog box

bi dsp.exe
donuthin.exe
dotota l . exe myprogs
drwhappy. exe
echo.exe
hell o.exe
little.exe
mytest.exe
pwrs.exe
reverse. exe
small .exe
tcdemo.exe

You can enter a file name (extension .EXE) in the File Name input
box, or press Enter to activate a list box of all the .EXE files in the
current directory. Move the highlight bar to the file you want to
load and press Enter.

Chapter 5, Controlling program execution 85


Another way of specifying a file in the list box is to type in the
name of the file you want to load. The highlight bar in the Files
list box moves to the file that begins with the first letter(s) you
typed. When the bar is positioned on the file you want, press
Enter.
You can supply arguments to the program to debug by placing
them after the program name, as follows:
myprog a b c
This command loads program MyProg with three command-line
arguments, a, b, and c.

Changing the program arguments


If you forgot to supply some necessary arguments to your pro-
gram when you loaded it, you can use the Run IArguments
command to set or change the arguments. Enter new arguments
exactly as you would following the name of your program on the
command line.
Once you have entered new arguments, TDW asks you if you
want to reload your program from disk. You should answer Yes,
because for most programs, the new arguments will only take
effect if you reload the program first.

86 Turbo Debugger for Windows User's Guide


c H A p T E R

Examining and modifying data


TOW provides a unique and intuitive way to examine and even
change your program's data.
•Inspector windows let you look at your data as it appears in
your source file. You can "follow" pointers, scroll through
arrays, and see structures, records, and unions exactly as you
wrote them.
• You can also put variables and expressions into the Watches
window, where you can watch their values as your program
executes.
•The Evaluate/Modify dialog box shows you the contents of any
variable and lets you assign a new value to it.
This chapter assumes that you understand the various data types
that can be used in Turbo C++ for Windows. If you are fairly new
to the language and have not yet explored all its data types (char,
int, short, long, unsigned, float, double, and so on), this chapter
can give you valuable information about them. When you have
delved into the more complex data types (arrays, pointers,
structures, files, classes, and so on), return to this chapter to learn
more about looking at them with TOW.
For how to examine or This chapter shows you how to examine and modify variables in
modify arbitrary blocks of
memory as hex data bytes,
your program. First, we explain the Data menu and its options.
see Chapter 12. We then discuss how you can modify program data by evaluating
expressions that have side effects, and show you how to point
directly at data items in your source modules. Finally, we

Chapter 6, Examining and modifying data 87


introduce the Watches window and describe the way that the data
types of each language appear in Inspector windows.

The Data menu

Inspect .•• The Data menu lets you choose how to examine and change pro-
Evaluate/modify ..• Ctrl-F4 gram data. You can evaluate an expression, change the value of a
Add watch... Ctrl-F7
Function return variable, and open Inspector windows to display the contents of
your variables.

Inspect
Prompts you for the variable that references the data you want to
inspect, then opens an Inspector window that shows the contents
of the program variable or expression. You can enter a simple
variable name or a complex expression.
If the cursor is on a variable in a text pane when you issue this
command, the dialog box automatically contains the variable at
the cursor, if any. If you select an expression in a text pane (using
Ins), the dialog box contains the selected expression.
Inspector windows really come into their own when you want to
examine a complicated data structure, such as an array of
structures or a linked list of items. Since you can inspect items
within an Inspector window, you can "walk" through your pro-
gram's data objects as easily as you scroll through your source
code in the Module window.
¢ See the "Inspector windows" section later in this chapter for a
complete description of how Inspector windows behave.

Evaluate/Modify
Opens the Evaluate/Modify dialog box (Figure 6.1), which
See Chapter 9 for a
prompts you for an expression to evaluate, then evaluates it
complete discussion of exactly as the compiler would during compilation when you
expressions. choose the Eval button.
If the cursor is in a text pane when you issue this command, the
dialog box automatically contains the variable at the cursor, if
any. If you select an expression (using Ins), the dialog box contains
the marked expression.

88 Turbo Debugger for Windows User's Guide


Figure 6.1 Evaluate/modif
The Evaluate/Modify dialog
box

See Chapter 9 for a Remember that you can add a format control string after the
discussion of format control.
expression you want to watch. TDW displays the result in a
format suitable for the data type of the result. To display the
result in a different format, put a comma (,) separator, then a
format control string after the expression. Displaying in a
different format is useful when you want to watch something, but
your program displays it in a format other than TDW's default
display format for the data type.
The dialog box has three fields.
•In the top field, you type the expression you want to evaluate.
This field is the Evaluate input box, and it has a history list just
like any other input box.
•The middle field displays the result of evaluating your
expression.
•The bottom field is an input box where you can enter a new
value for the expression. If the expression can't be modified,
this box reads <Not available>, and you can't move your cursor
into it.
Your entry in the New Value input box takes effect when you
choose the Modify button. Use Tab and Shift-Tab to move from one
box to another, just as you do in other dialog boxes. Press Esc from
inside any input box to remove the dialog box, or click the Cancel
button with your mouse.
Data strings too long to display in the Result input box are termi-
nated by an arrow(•). You can see more of the string by scrolling
to the right.
If you're debugging a C++ program, the Evaluate/Modify dialog
box also lets you display the members of a class instance. You can
use any format specifier with an instance that can be used in
evaluating a record.

Chapter 6, Examining and modifying data 89


When you're tracing inside a member function, TOW knows
about the scope and presence of the this parameter. You can
evaluate this and follow it with format specifiers and qualifiers.
You can't execute Turbo Debugger also lets you call a member function from inside
constructors or destructors in
the Evaluate/Modify dialog box. Just type the instance name
the Evaluate window.
followed by a dot, followed by the member function name,
followed by the actual parameters (or empty parentheses if there
are no parameters). With these declarations,
class point {
public:
int x, y, visible;
point ();
Npoint ();
int Show();
int Hide{);
void MoveTo(int NewX, int NewY);
};

point APoint;
you could enter any of these expressions in Turbo Debugger's
Evaluate window:

Expression Result
APoint.x int 2 (Ox2)
APoint class point (1,2,27489)
APoint.MoveTo void() @6B61:0299
APoint.Show int() @6B61:0285
APoint.Show() int 1 (Oxl)

Expressions with side effects The C language has a feature called expressions with side effects that
can be powerful and convenient, as well as a source of surprises
and confusion.
An expression with side effects alters the value of one or more
variables or memory areas when it is evaluated. For example, the
increment(++) and decrement(·-) operators and the assignment
operators (=, +=, and so on) have this effect. If you execute
functions in your program within a C expression (for example,
myfunc(2)), note that your function can have unexpected side
effects.
If you don't intend to modify the value of any variable but merely
want to evaluate an expression containing some of your program
variables, don't use any of the operators that have side effects. On
the other hand, side effects can be a quick and easy way to change

90 Turbo Debugger for Windows User's Guide


the value of a variable or memory area. For example, to add 1 to
the value of your variable named count, evaluate the C expression
count++.
You can also use the Evaluate/Modify dialog box as a simple
calculator by typing in numbers as operands instead of program
variables.

Add Watch
Prompts you for an expression to watch, then places the expres-
sion or program variable on the list of variables displayed in the
Watches window when you press Enter or choose the OK button.
If the cursor is in a text pane when you issue this command, the
dialog box automatically contains the variable at the cursor, if
any. If you select an expression (using Ins), the dialog box contains
the selected expression.

Function Return
Shows you the value the current function is about to return. Use
this command only when the function is about to return to its
caller.
The return value is displayed in an Inspector window, so you can
easily examine return values that are pointers to compound data
objects.
Function Return saves you from having to switch to a CPU
window to examine the return value placed in the CPU registers.
And since TOW also knows the data type being returned and
formats it appropriately, this command is much easier to use than
a hex dump.

Pointing at data objects in source files


See Chapter 8 for a full TOW has a powerful mechanism to relieve you from always
discussion of using Module
windows.
typing in the names of program variables that you want to
inspect. From within any Module window, you can place the
cursor anywhere within a variable name and use the local menu
Inspect command to create an Inspector window showing the
contents of that variable. You can also select an expression or

Chapter 6, Examining and modifying data 91


variable to inspect by pressing Ins and using the cursor keys to
highlight it before choosing Inspect.

The Watches window


The Watches window lets you list variables and expressions in
your program whose values you want to track. You can watch the
value of both simple variables (such as integers) and complex
data objects (such as arrays). In addition, you can watch the value
of a calculated expression that does not refer directly to a memory
location. For example, x * y + 4.
Figure6.2
The Watches window

Choose View IWatches to access the Watches window. It holds a


list of variables or expressions whose values you want to watch.
For each item, the variable name or expression appears on the left
and its data type and value on the right. Compound values like
arrays and structures appear with their values between braces
({}).If there isn't room to display the entire name or expression, it
is truncated.
See Chapter 9 for a When you enter an expression to watch, you can use variable
complete discussion of
scopes and when a variable
names that are not valid yet because they are in a function that
or parameter is valid. hasn't been called. TOW lets you set up a watch expression before
its scope becomes active. This situation is the only time you can
enter an expression that can't be immediately evaluated.

Wamingl If you mistype the name of a variable, the mistake won't be


detected because TOW assumes it is the name of a variable that
will become available as your program executes.
Unless you use the scope-overriding mechanism discussed in
Chapter 9, TOW evaluates expressions in the Watches window in
the scope of the current location where your program is stopped.
Hence an expression in the Watches window is evaluated as if it
appeared in your program at the place where the program is
stopped. If a watch expression contains a variable name that is not
accessible from the current scope-for example, if it's private to

92 Turbo Debugger for Windows User's Guide


another module-the value of the expression is undefined and is
displayed as four question marks(????).
When you' re tracing inside a member function, you can add the
this parameter to the Watches window.

The Watches
window local As with all local menus, press Alt-F10to pop up the Watches
window local menu. If you have control-key shortcuts enabled,
menu
press Ctr/ with the first letter of the desired command to access it.
Watch •••
Edit •••
Remove
Delete all
Inspect
Change •••

Watch Prompts you for the variable name or expression to add to the
Watches window. It is added at the current cursor location.

Edit Opens a dialog box in which you can edit an expression in the
Watches window. You can change any watch expression that's
there, or enter a new one.
You can also invoke this command by pressing Enter once you've
positioned the highlight bar over the watch expression you want
to change. Press Enter or choose the OK button to put the edited
expression into the Watches window.

Remove Removes the currently selected item from the Watches window.

Delete All Removes all the items from the Watches window. This command
is useful if you move from one area of your program to another,
and the variables you were watching are no longer relevant.
(Then use the Watch command to enter more variables.)

Inspect Opens an Inspector window to show you the contents of the


currently highlighted item in the Watches window. If the item is a
compound object (array, class, or struct), you can view all its
elements, not just the ones that fit in the Watches window. (The
next section, "Inspector Windows," explains all about Inspector
windows.)

Chapter 6, Examining and modifying data 93


Change Changes the value of the currently highlighted item in the
Watches window to the value you enter in the dialog box. If the
See Chapter 9 for more
Information on the current language you're using permits it, TOW performs any
assignment operator and necessary type conversion exactly as if the assignment operator
type conversion (casting). had been used to change the variable.

Inspector windows
An Inspector window displays your program data appropriately,
depending on the data type you're inspecting. Inspector windows
behave differently for scalars (for example, char or int), pointers
(char*), arrays (long x[4]), functions, and structures.
The Inspector window lists the items that make up the data object
being inspected. The title of the window shows the expression or
the name of the variable being inspected.
The first item in an Inspector window is always the memory
address of the data item being inspected, expressed as a segment:
offset pair, unless it has been optimized to a register or is a
constant (for example, 3).
To examine the contents of a variable in an Inspector window as
raw data bytes, choose View I Dump while you're in the Inspector
window. The Dump window comes up, with the cursor posi-
tioned to the data displayed in the Inspector window. You can
return to the Inspector window by closing the window with the
Window I Close command (Alt-F3), or clicking the close box with
your mouse.
The following sections describe the different Inspector windows
that can appear for two of the languages supported by TOW: C++
and assembler. The programming language used dictates the
format of the information displayed in Inspector windows. Data
items and their values always appear in a format similar to the
one they were declared with in the source file.
Remember that you don't have to do anything special to cause the
different Inspector windows to appear. The right one appears
automatically, depending on the data you're inspecting.

94 Turbo Debugger for Windows User's Guide


C data Inspector
windows
Scalars Scalar Inspector windows show you the value of simple data
items, such as
char x = 4;
unsigned long y = 1234561;

Following the top line, these Inspector windows have oniy a


single line of information that gives the address of the variable. To
the left on the following line appears the type of the scalar
variable (char, unsigned long, and so forth), and to the right
appears its present value. The value can be displayed as decimal,
hex, or both. It's usually displayed first in decimal, with the hex
values in parentheses (using the standard C hex prefix of Ox). Use
TDWINST to change how the value is displayed.
If the variable being displayed is of type char, the equivalent
character is also displayed. If the present value does not have a
printing character equivalent, TOW uses the backslash (\)
followed by a hex value to display the character value. This
character value appears before the decimal or hex values.
Figure 6.3 l!i(•]=Inspecting wordcount=3=[t] (+]1
A C scalar Inspector window llf82: FFC4
ns1gned int 2 (OxZ) ~

Pointers Pointer Inspector windows show you the value of data items that
point to other data items, such as
char *p = "abc";
int *ip = 0;
int **ipp = &ip;

Pointer Inspector windows usually have a top line that contains


the address of the variable, followed by a single line of informa-
tion about the data pointed to. To the left appears [O], indicating
the first member of an array. To the right appears the value of the
item being pointed to. If the value is a complex data item, such as
a structure or an array, however, only as much of it as possible is
displayed with the values enclosed in braces ({and}).
If the pointer is of type char and appears to be pointing to a null-
terminated character string, more information appears, showing
the value of each item in the character array. To the left in each

Chapter 6, Examining and modifying data 95


line appears the array index ([1], [2], and so on), and the value
appears to the right as it would in a scalar Inspector window. In
this case, the entire string is also displayed on the top line, along
with the address of the pointer variable and the address of the
string that it points to.
You also get multiple lines if you open the Inspector window and
then use the Range local menu command. This is an important
technique for C programmers who use pointers to point to arrays
of items as well as single items. For example, if you had the code
int array [10];
int *arrayp = array;
and you wanted to look at what arrayp pointed to, use the Range
local command on arrayp, specifying a start index of 0 and a range
of 10. If you had not done this, you would only have seen the first
item in the array.
Flgure6.4
A C pointer Inspector
window

Pointer Inspector windows also have a lower pane indicating the


data type to which the pointer points.

Structures and unions Structure and union Inspector windows show you the value of
the members in your structure and union data items. For
example,
struct linfo {
unsigned int count;
unsigned int firstletter;
letterinfo [26];
union {
int small;
long large;
) holder;
These Inspector windows have another pane below the one that
shows the values of the members. This additional pane shows the
data type of the member highlighted in the top pane.

96 Turbo Debugger for Windows User's Guide


Figure 6.5

liiiii
(17937:0852
A C structure or union
Inspector window

Structures and unions appear the same in Inspector windows. The


lower pane of the Inspector window tells you whether you are
looking at a structure or a union. These Inspector windows have
as many items after the address as tht!re art! membt!r~ in tht! ~truc­
ture or union. Each item shows the name of the member on the
left and its value on the right, displayed in a format appropriate
to its C data type.

Arrays Array Inspector windows show you the value of arrays of data
items, such as ·
long thread[3] [4] [5];
char message[] = "eat these words";
There is a line for each member of the array. To the left on each
line appears the array index of the item. To the right appears the
value of the item. If the value is a complex data item such as a
structure or array, as much of it as possible is displayed.
You can use the Range local menu command to examine any
portion of an array. This is useful if the array has a lot of elements,
and you want to look at something in the middle of the array.
Figure6.6 [•]=Inspecting letterinf0=3=[t] [~]9
(17682:0852 ..
A C array Inspector window I

Functions Function Inspector windows show each parameter with which a


function is called. The parameters are displayed below the
memory address at the top of the window.

Chapter 6, Examining and modifying data 97


Figure 6.7

lliiii
A C function Inspector tl71E9:02DD
window

They also give you information about the calling parameters,


return data type, and calling conventions for a function. The
lower pane indicates the data type returned by the function.

Assembler data
Inspector
windows
Scalars Scalar Inspector windows in assembly language programs show
you the value of simple data items, such as
VARl DW 99
MAGIC DT 4.608
BIGNUM DD 123456
These Inspector windows have only a single line of information
following the top line that gives the address of the variable. To the
left appears the type of the scalar variable (BYTE, WORD,
DWORD, QWORD, and so forth), and to the right appears its
present value. The value can be displayed as decimal, hex, or
both. It's usually displayed first in decimal, with the hex values in
parentheses (using the standard assembler hex postfix H). You
can use TDWINST to change how the value is displayed.
Flgure6.8
~]
~
An assembler scalar
Inspector window

Pointers Pointer Inspector windows in assembler programs show you the


value of data items that point to other data items, such as
X DW 0
XPTR DW X
FARPTR DD X

Pointer Inspector windows usually have only a single line of


information following the top line that gives the address of the
variable. To the left appears [O], indicating the first member of an
array. To the right appears the value of the item being pointed to.
If the value is a complex data item such as an array, however, only

98 Turbo Debugger for Windows User's Guide


as much of it as possible is displayed, with the values enclosed in
braces ( {} ).
If the pointer is of type BYTE and appears to be pointing to a
null-terminated character string, more information appears,
showing the value of each item in the character array. To the left
in each line appears the array index ([1], [2], and so on), and the
value appears to the right as it would in a scalar Inspector win-
dow. In this case, the entire string is also displayed on the top
line, along with the address of the variable and the address of the
string that it points to.
You also get multiple lines if you open the Inspector window with
a Range local menu command and specify a count greater than 1.
Figure6.9
An assembler pointer
Inspector window

Arrays Array Inspector windows in assembler programs show you the


value of arrays of data items, such as
WARRAY DW 10 DUP (0)
MSG DB "Greetings",0
There is a line for each member of the array. To the left on each
line appears the array index of the item and to the right is its
present value. If the value is a complex data item such as a
STRUC, however, only as much of it as possible is displayed.
You can use the Range local command to examine a portion of an
array. This is useful if the array has a lot of elements, and you
want to look at something in the middle of the array. When you
choose Range, you are prompted to enter a starting index
followed by a comma and the number of members to inspect.

Chapter 6, Examining and modifying data 99


Flgure6.10
An assembler array Inspector
window

Structures and unions Structure Inspector windows in assembler programs show you
the value of the fields in your STRUC and UNION data objects. For
example,
x STRUC
MEMl DB ?
MEM2 DD ?
x ENDS
ANX x <l,ANX>
y UNION
ASBYTES DB 10 DUP (?)
ASFLT DT ?
y ENDS
AY y <?I 1. 0>
These Inspector windows have another pane below the one that
shows the values of the fields. This additional pane shows the
data type of the field highlighted in the top pane.
Figure6.l l
An assembler structure
Inspector window

The Inspector window local menu

Range ••• The commands in this menu give the Inspector window its real
Change ••• power. By choosing the Inspect local menu command, for
Inspect example, you create another Inspector window that lets you go
Descend into your data objects. Other commands in the menu let you
New expression •••
Type cast ••• inspect a range of values or a new variable.

100 Turbo Debugger for Windows User's Guide


Press Alt-F10 to pop up the Inspector window local menu. If you
have control-key shortcuts enabled, press Ctr/ with the first letter
of the desired command to access it.

Range
Sets the starting element and number of elements that you want
to display. Use this command when you are inspecting an array,
an<l you only wanl lo look at a ('t:rtain subrange of all the
members of the array.
If you have a long array and want to look at a few members near
the middle, use this command to open the Inspector window at
the array index that you want to examine.

Change
Changes the value of the currently highlighted item to the value
you enter in the dialog box. If the current language permits it,
TOW performs any necessary casting exactly as if the appropriate
assignment operator had been used to change the variable. See
Chapter 9 for more information on the assignment operator and
casting.

Inspect
Opens a new Inspector window that shows you the contents of
the currently highlighted item. This is useful if an item in the
Inspector window contains more items itself (like a structure or
array), and you want to see each of those items.
You can also invoke this command by pressing Enter after high-
lighting the item you want to inspect.
You return to the previous Inspector window by pressing Esc to
close the new Inspector window. If you are through inspecting a
data structure and want to remove all the Inspector windows, use
the Window I Close command or its shortcut, Alt-F3.

Descend
This command works like the Inspect local menu command
except that instead of opening a new Inspector window to show
the contents of the highlighted item, it puts the new item in the

Chapter 6, Examining and modifying data 101


current Inspector window. This is like a hybrid of the New
Expression and Inspect commands.
¢ Once you have descended into a data structure like this, you can't
go back to the previous unexpanded data structure. Use this
command when you want to work your way through a compli-
cated data structure or long linked list, but you don't care about
returning to a previous level of data. This helps reduce the
number of Inspector windows onscreen.

New Expression
Prompts you for a variable name or expression to inspect, without
creating another Inspector window. This lets you examine other
data without having to put more Inspector windows on the
screen. Use this command if you are no longer interested in the
data in the current Inspector window.
Inspector windows for C++ classes are somewhat different from
regular Inspector windows. See Chapter 10 for a description of
class Inspector windows.

Type Cast
Chapter 11 explains on page Lets you specify a different data type (int, char *, gh2fp, lh2fp) for
175 how to use the gh2fp
and lh2fp types.
the item being inspected. Typecasting is useful if the Inspector
window contains a symbol for which there is no type information,
as well as for explicitly setting the type for untyped pointers.

102 Turbo Debugger for Windows User's Guide


c H A p T E R

Breakpoints
TOW uses the single term "breakpoint" to refer to the group of
functions that other debuggers usually call breakpoints,
watchpoints, and tracepoints.
Traditionally, breakpoints, watchpoints, and tracepoints are
defined like this: A breakpoint is a place in your program where
you want execution to stop so that you can examine program
variables and data structures. A watchpoint causes your program
to be executed one instruction or source line at a time, watching
for the value of an expression to become true. A tracepoint causes
your program to be executed one instruction or source line at a
time, watching for the value of certain program variables or
memory-referencing expressions to change.
TOW unifies these three concepts by defining a breakpoint in
three parts:
•the location in the program where the breakpoint occurs
•the condition under which the breakpoint is triggered
• the action that takes place when the breakpoint triggers
The location can be either a single source line in your program or it
can be global in context; a global breakpoint checks the
breakpoint condition after the execution of each source line or
instruction in your program.
The condition can be
•always
•when an expression is true

Chapter 7, Breakpoints 103


•when a data object changes value
See Chapter 17, page 764 •when a Windows message comes in
for a description of message
breakpoints. A pass count can also be specified, requiring that a condition be
true a designated number of times before the breakpoint is
triggered.
The action taken when a breakpoint triggers can be one of the
following:
• stop program execution (a breakpoint)
• log the value of an expression
•execute an expression (code splice)
•enable a group of breakpoints
•disable a group of breakpoints
In this chapter, you'll learn about the Breakpoint and Log
windows; how to set simple breakpoints, conditional breakpoints,
and breakpoints that log the value of your program variables; and
how to set breakpoints that watch for the exact moment when a
program variable, expression, or data object changes value.
When debugging, you'll often want to set a few simple break-
points to make your program pause execution when it reaches
certain locations. You can set or clear a breakpoint at any location
in your program by simply placing the cursor on the source code
line and pressing F2. You can also set a breakpoint on any line of
machine code by pressing F2 when you are pointing at an
instruction in the Code pane of a CPU window.
M. If you have a mouse, just click either of the leftmost two columns
of the line where you want to set or remove a breakpoint. (If
you're in the correct column, an asterisk(*) appears in the
position indicator.)
There are two ways to access the dialog boxes for setting and
customizing breakpoints. The Breakpoints menu offers a quick
approach for setting breakpoints, and the Breakpoints window
provides a view of the breakpoints already set, and gives access to
the dialog boxes that control breakpoint settings.

The Breakpoints menu


Access the Breakpoints menu at any time by pressing the A/t-8 hot
key.

104 Turbo Debugger for Windows User's Guide


Toggle F2
At... Alt-F2
Changed memory g1oba1. ••
Expression true global ..•
Hardware breakpoint ••.
Delete all

Toggle The Toggle command sets or clears a breakpoint at the currently


highlighted address in the Module or CPU window. The hot key
is F2.

At At lets you set a breakpoint at a specific location in your program.


See page 109 for a
description of the Breakpoint
When selected, At opens the Breakpoint Options dialog box, from
Options dialog box. which you can set all breakpoint options. Alt-F2 is the hot key for
At.

Changed memory Changed Memory Global sets a global breakpoint that's triggered
global when an area of memory changes value. You are prompted for
For more information, see the the area of memory to watch with the Enter Memory Address,
"Changed Memory" section Count input box. The variable expression entered is checked for
onpage 117. change each time a line of source code is executed.

Expression true global Expression True Global sets a global breakpoint that is triggered
when the value of a supplied expression is true (nonzero). You are
For more information, see
"Conditional Breakpoints" on prompted for the expression to evaluate with the Enter
page 778. Expression for Condition Breakpoint input box. The expression
entered is evaluated each time a line of source code is executed.

Hardware breakpoint Use this command to access the Hardware Breakpoints Options
For more information on
dialog box. You must have the proper system setup in order to
hardware debugging, see use hardware debugging.
page 178.
Delete all The Delete All command erases all the breakpoints you've set. Use
this command when you want to start over from scratch.

The Breakpoints window


The Breakpoints window is accessed by choosing the View I
Breakpoints command. This gives you a way of looking at and
adjusting the conditions that trigger a breakpoint.

Chapter 7, Breakpoints 105


Figure 7.1
Breakpo1 nt
The Breakpoints window AI ways
En ab I ed

The Breakpoints window has two panes; the Breakpoint List (left
pane) shows a list of all the addresses at which breakpoints are set
and the Breakpoint Detail (right pane) shows the details of the
breakpoint highlighted in the left pane. Although a breakpoint
can have several sets of actions and conditions associated with it,
only the first set of details is displayed in the Breakpoint Detail
pane.
The Breakpoints window has a local menu, which you access by
pressing Alt-F10when inside the left pane. If you have control-key
shortcuts enabled, press Ctr/ with the first letter of the command
to access that command directly.

The Breakpoints
window local The commands in this menu let you add new breakpoints, delete
menu existing breakpoints, and change how a breakpoint behaves.
Set options •••
Add •••
Remove
Delete all
Inspect
Group ••.

Set Options Once a breakpoint is set, the Set Options command opens the
Breakpoint Options dialog box, allowing you to modify the
breakpoint. Using this box, you can
For a detailed explanation of • declare a global breakpoint
the Breakpoint Options
dialog box, see page 709. •disable/ enable the breakpoint
•attach the breakpoint to a specific group
• access the Conditions and Actions dialog box

Add The Add command on the Breakpoints local menu opens the
Breakpoint Options dialog box, much like the Set Options
command does. The difference is that the cursor is positioned on
an empty Address text box. Enter into the Address text box the
address for which you'd like the breakpoint to be set. For

106 Turbo Debugger for Windows User's Guide


example, if you'd like to set a breakpoint at line number 3201 in
your C source code, enter #32O1 into the text box. If the line of
code is in a module not displayed in the Module window, type a
pound sign(#), followed by the module name, followed by
another pound sign, and then the line number. For example:
#OTHERMOD#3201.

The Add command can also be accessed by simply typing an


address into the Breakpoint Window. After typing the first
character of the address, the Breakpoint Options dialog box
opens, placing you in the Address text box.
Once you've entered the breakpoint address, use the other
commands in the Breakpoint Options dialog box to complete the
breakpoint entry.

Remove The Remove command erases the currently highlighted break-


point. Del is the hotkey for this command.

Delete all Delete All removes all breakpoints, both global and those set at
specific addresses. You will have to set more breakpoints if you
want your program to stop on a breakpoint. Use this command
with caution!

Inspect The Inspect command displays the source code line or assembler
instruction that corresponds to the currently highlighted break-
point item. If the breakpoint is set at an address that corresponds
to a source line in your program, a Module window is opened
and set to that line. Otherwise, a CPU window is opened, with the
Code pane set to show the instruction at which the breakpoint is
set.
You can also invoke this command by pressing Enter once you
have the highlight bar positioned over a breakpoint.

Group The Group command allows you to gather breakpoints into


groups. A breakpoint group is identified by a positive integer,
generated automatically by TOW or assigned by you. The
debugger automatically assigns a new group number to each
breakpoint as it's created. The group number generated is the
lowest number not already in use. Thus, if the numbers l, 2, and 5
are already used by groups, the next breakpoint created is
automatically given the group number 3.

Chapter 7, Breakpoints l 07
Once a breakpoint is created, you may modify the breakpoint
group number from the Breakpoint Options dialog box, placing
the breakpoint into a group associated with other breakpoints.
Grouping breakpoints together allows you to enable, disable, or
remove a collection of breakpoints with a single action.
When the Group command is chosen from the Breakpoint
window's local menu, the Edit Breakpoint Groups dialog box is
displayed. This dialog box shows a listing of the current
breakpoint groups and allows you to easily collect all functions
within a module into a single group.

Figure 7.2 Edit break oi nt rou


The Edit Breakpoint Groups
dialog box

Groups
The Groups list box displays the currently assigned breakpoint
groups.

Add
The Add button activates the Add Group dialog box.

Figure 7.3 [•] dd rou


odule/Clas
The Add Group dialog box TDD EMO

The Add Group dialog box has a single list box and a single set of
radio buttons that allow you to add all functions in a single
module, or all member functions in a class, to a breakpoint group.
•The Module/Class list box displays a list of the modules or
classes contained in the program loaded into the Module
window. Highlight the desired module or class, then press OK

108 Turbo Debugger for Windows User's Guide


to set breakpoints on all functions in the module or class. All
breakpoints set are collected into a single breakpoint group.
• Two radio buttons allow you to select the type of functions that
are displayed in the Module/Class list box:
• The Modules radio button selects all modules contained in the
current program, displaying them in the Module/Class list
box.
• The Classes radio button selects all the C++ classes contained
in the current program for display in the Module/Class list
box.

Delete
The Delete button in the Edit Breakpoint Groups dialog box
removes the group currently highlighted in the Groups list box.
All breakpoints in this group, along with their settings, will be
erased.

Enable
The Enable button activates a breakpoint group that has been
previously disabled.

Disable
The Disable command temporarily masks the breakpoint group
that is currently highlighted in the Groups list box. Breakpoints
that have been disabled are not erased; they are merely set aside
for the current debugging session. Enabling the group reactivates
all the settings for all the breakpoints in the group.

The Breakpoint
Options dialog The Breakpoint Options dialog box is reached from the
Breakpoints IAt command, and from the Set Options and Add
box
commands on the Breakpoints window local menu.

Chapter 7, Breakpoints 109


Figure 7.4
The Breakpoint Options
dialog box

Address The Address text box contains the address tag associated with the
currently highlighted breakpoint. Normally, you will not edit this
field. However, if you want to change the name of the tag
associated with the breakpoint, type the new name into the
Address text box.

Group ID The Group ID text box allows you to assign the current
See page 107 for a breakpoint to a new or existing group. A breakpoint group is
description of breakpoint identified by a unique positive integer.
groups.

Global Global, when checked, enables global checking. This means that
every time a source line is executed, the breakpoint conditions
will be checked for validity. Because global breakpoints are tested
after every line of code is executed, the Address field is set to <not
available> since it is no longer pertinent.
For more Information on When you set a global breakpoint, you must set a condition that
global breakpoints, see
page 116.
will trigger the global breakpoint. Otherwise, you'll end up with a
breakpoint that activates on every line of source code (if this is the
effect you want to achieve, use the Run I Trace Into command on
the Main menu).

Disabled The Disabled check box turns off the current breakpoint. While
this command is similar to the Toggle command on the
Breakpoints menu (see page 105), Disable does not clear the
breakpoint of its settings (as does the Toggle command). Disable
simply masks the breakpoint until you want to reenable it by
unchecking this box. When the breakpoint is reenabled, all
settings previously made to the breakpoint will become effective.
This check box is useful if you have defined a complex breakpoint
that you don't want to use just now, but will want to use again

110 Turbo Debugger for Windows User's Guide


later. It saves you from having to delete the breakpoint, and then
reenter it along with its complex conditions and actions.

Conditions and Actions The Conditions and Actions list box displays the set of conditions
and actions associated with the current breakpoint.

Change The Change button, when selected, opens up the Conditions and
A-=tions dialog box (see the next section). 'vVilh this rnmmand, you
can edit the item currently highlighted in the Conditions and
Actions list box.

Add To add a new set of conditions and actions to the current


breakpoint, select Add. Like the Change command above, Add
opens the Conditions and Actions dialog box.

Delete The Delete command removes the currently highlighted item in


the Condition and Actions list box from the breakpoint definition.

The Conditions
and Actions When you choose either the Change or the Add button from the
dialog box Breakpoint Options dialog box, you're presented with the
Conditions and Actions dialog box.

Figure 7.5
The Conditions and Actions
dialog box

See "Customizing When a breakpoint is set on a line of source code, its default
breakpoints• on page 116 for
characteristics are Always Break execution when the line of code
details on modifying
breakpoints. is encountered. With the Conditions and Actions dialog box, you
can customize the conditions under which the breakpoint will be
activated and specify different actions that take place once the
breakpoint does trigger.

Chapter 7, Breakpoints 111


You'll customize breakpoints through two sets of radio buttons
and three text entry boxes. In addition, a Hardware button leads
to the Hardware Breakpoints Options dialog box, allowing you to
specify hardware breakpoint conditions.

The condition radio The Condition radio buttons have four settings:
buttons
Always
When Always is chosen, it indicates that no additional conditions
need be true for the breakpoint to trigger; it will be triggered each
time program execution encounters the breakpoint.

Changed memory
See page 777 for more A Changed Memory breakpoint watches a memory variable or
information on Changed
Memory breakpoints.
object; the breakpoint is triggered if the object changes value. Use
the Condition Expression input box to enter an expression
representing the data object you want to watch.

Expression true
The Expression True button allows the breakpoint to be triggered
when an expression becomes true (nonzero). Use the Condition
See page 778 for details on Expression input box to enter an expression that's evaluated each
expressions.
time the breakpoint is encountered.

Hardware
See page 778 for more Causes the breakpoint to be triggered by the hardware-assisted
information about hardware
breakpoints.
device driver. Because you can use hardware assistance only with
a global breakpoint, you must check the Global check box in the
Breakpoint Options dialog box before you can access this option.
The Hardware I Breakpoint You must select the Hardware radio button before the Hardware
command offers an easy button at the bottom of the dialog box can become active. Pushing
way to set hardware
breakpoints. that button displays the Hardware Breakpoint Options dialog
box. The choices you can make in this box are described in the
online text file HDWDEBUG.TD.

112 Turbo Debugger for Windows User's Guide


The action radio The Action radio buttons have five settings:
buttons
Break
Break causes your program to stop when the breakpoint is
triggered. The TOW screen reappears, and you can once again
enter commands to look around at your program's data
structures.

Execute
Execute causes an expression to be executed. Enter the expression
in the Action Expression input box. The expression should have
some side effect, such as setting a variable to a value. By executing
an expression that has side effects each time a breakpoint is
triggered, you can effectively "splice in" new pieces of code
before a given source line. This is useful when you want to alter
the behavior of a routine to test a diagnosis or bug fix. This saves
you from going through the compile-and-link cycle just to test a
minor change to a routine.
Of course, this technique is limited to the insertion of an expres-
sion before an already existing line of code is executed; you can't
use this technique to modify existing source lines directly.

Log
See Chapter 9 for a The Log button causes the value of an expression to be recorded
description of expressions
and side effects.
in the Log window. You are prompted for the expression whose
value you want to log. Be careful that the expression doesn't have
any unexpected side effects.

Enable group
The Enable Group action button allows for a breakpoint to
reactivate a group of breakpoints that have been previously
disabled.

Disable group
The Disable Group radio button lets you disable a group of
breakpoints. When a group of breakpoints is disabled, the

Chapter 7, Breakpoints 113


breakpoints are not erased, they are simply masked for the
debugging session.

Setting conditions and The most important step when setting up breakpoints is
actions specifying the conditions under which the breakpoint triggers and
specifying the actions to be taken once the breakpoint takes effect.
Two text boxes control these settings, the Condition Expression
text box and the Action Expression text box.

Condition Expression When you choose either a Changed Memory, Expression True, or
Hardware Condition radio button, you must provide a set of
conditions so TDW knows when to trigger the breakpoint. A
condition set consists of one or more expressions; each condition
has to evaluate true in order for the whole set to evaluate true.
For more information on A condition set is associated with a set of actions. When the
specifying breakpoint
actions, see the "Action
condition set evaluates true, the corresponding action set is
Expression· section that performed.
follows.
To add a condition set to a breakpoint,

1. Select either the Changed memory, Expression True, or


Hardware radio button.
2. Select the Add button located under the Condition Expression
text box.
3. Enter the condition or variable expression into the Condition
Expression text box.
4. If you want more than one variable or condition to be tested
for a particular action set, repeat steps 2 and 3 until all
expressions have been added to the Condition Expression text
box.
5. Once you've specified a condition set, use the Action
Expression text box to list the action(s) you'd like to take when
the breakpoint triggers.

¢ A single breakpoint may have several condition and action sets


associated with it. If you want more than one set of conditions
and actions assigned to a single breakpoint, choose OK after you
have entered the first series of conditions and actions. This will
close the Conditions and Actions dialog box and return you to the
Breakpoint Options dialog box. From here, choose Add to enter a
new set of conditions and actions. When a breakpoint has
multiple condition and action sets, each one will be evaluated in

114 Turbo Debugger for Windows User's Guide


the order that they were entered. If more than one action set
evaluates to true, then more than one set of actions will be
performed.
The Delete button located below the Condition Expression text
box lets you remove the currently highlighted expression from the
Condition Expression text box. Select this button if you want to
delete a condition from the condition set.

Action Expression When either an Execute, Log, Enable Group, or Disable Group
Action radio button is chosen, an action set must be provided so
TOW knows what to do when the breakpoint triggers. An action
set is composed of one or more actions.
To add an action set to a breakpoint,

1. Select either the Execute, Log, Enable Group, or Disable Group


radio button.
2. Select the Add button located under the Action Expression text
box.
3. Enter the action into the Action Expression text box.
To perform more than one action when the breakpoint
triggers, repeat steps 2 and 3 until all actions have been added
to the Action Expression text box.
4. When you have finished entering actions, choose OK from the
Conditions and Actions dialog box.

¢ If the Enable Group or Disable Group radio button is chosen,


simply type the breakpoint group number into the Action
Expression text box to reference the group that you want to
enable or disable.
The Delete button located below the Action Expression text box
lets you remove the currently highlighted action from the action
set.

Pass count The Pass Count input box lets you set the number of times the
breakpoint condition set must be met before the breakpoint is
triggered. The default number is 1. The pass count is decremented
only when the entire condition set attached to the breakpoint is
true. This means that if you set a pass count ton, the breakpoint is
triggered the nth time that the condition set is true.

Chapter 7, Breakpoints 115


Customizing breakpoints
In addition to simply stopping your program at a particular point,
greater control can be given to debugging by stipulating when a
breakpoint should take action, and what it should do when it
triggers.

Simple
breakpoints When a breakpoint is initially set, it is given the default setting of
Always Break. Once a simple breakpoint is set, the actions and
conditions of the breakpoint may be customized. There are a
number of ways to set a simple breakpoint, each one being
convenient in different circumstances:
•Move to the desired source line in a Module window (or Code
pane of a CPU window) and issue the Breakpoints I Toggle
command (or press F2, or click the line with your mouse).
Doing this on a line that already has a breakpoint set causes
that breakpoint to be deleted.
• Issue the Add local menu command from the Breakpoint List
pane of the Breakpoints window and enter a code address at
which to set a breakpoint. (A code address has the same format
as a pointer in the language you're using. See Chapter 9 about
expressions.)
•Issue the Breakpoints I At command to set a breakpoint at the
current line in the Module window.

Global
breakpoints When a breakpoint is made global, TDW will check the
breakpoint on the execution of every line of code. If the set of
conditions evaluates true, then the corresponding set of actions
will be executed.
If you want a global check to occur on every machine code
instruction, set a global breakpoint, and press F9 from within the
CPU window. This type of code monitoring should only be done
once you have isolated a small area of your program known to
contain a problem. The CPU window can then be used to locate
the exact position of the difficulty.
You must check Global if you Since a debugger action will occur on every line of source code or
want to set hardware
breakpoints.
machine instruction, global breakpoints greatly slow the

116 Turbo Debugger for Windows User's Guide


execution of your program. Be careful with your use of global
breakpoints; they should be used only if you want to find out
exactly when a variable changes value, when some condition
becomes true, or when your program is ''bashing" data.
The Breakpoints menu offers Often, global breakpoints are used to watch for when a data item
shortcuts for defining global changes value. In this situation, TDW checks the area of memory
breakpoints. For more
information on the Changed for change after the execution of every line of code. As an
Memory Global and alternative to a global breakpoint, you may want to specify a
Expression True Global breakpoint that only watches for a change when a specific source
commands, see page 705.
statement is reached. This is a lot more efficient, since it reduces
the amount of processing TDW does in order to detect the change
(in this case, TDW isn't concerned with when the item has
changed, only that it has changed).

Changed
memory When you want to find out where in your program a certain data
breakpoints object is being changed, first set a breakpoint using one of the
techniques outlined in the preceding section. Then, using the
Changed Memory radio button in the Conditions and Actions
dialog box, enter an expression that refers to the memory area you
want to watch along with an optional count of the number of
objects to track. The total number of bytes in the watched area is
the size of the object that the expression references times the
number of objects. For example, suppose you have declared the
following C array:
int string[81];
If you want to watch for a change in the first ten elements of this
array, enter the following item into the Condition Expression
input box:
&string[O], 10
The area watched is 20 bytes long, since an Int is 2 bytes and you
said to watch ten of them.
If the Changed Memory breakpoint is global, your program
executes much more slowly because the memory area is checked
for change after every source line has been executed. If you've
installed a hardware device driver, TDW will try to set a
hardware breakpoint to watch for a change in the data area.
Different hardware debuggers support different numbers and
types of hardware breakpoints. You can see if a breakpoint is
using the hardware by opening a Breakpoint window with the

Chapter 7, Breakpoints 117


View I Breakpoints command. Any breakpoint that is hardware
assisted will have an asterisk (*) beside it. These breakpoints are
much faster than global breakpoints that are not hardware
assisted.

Conditional
expressions There are many occasions when you won't want a breakpoint to
be triggered every time a certain source statement is executed,
particularly if that line of code is executed many times before the
occurrence you are interested in. TOW gives you two ways to
qualify when a breakpoint is actually triggered: pass counts and
conditions.

Scope of breakpoint Both the action that a breakpoint performs and the condition
expressions under which it is triggered can be controlled by an expression you
supply. That expression is evaluated using the scope of the
See Chapter 9 for a address at which the breakpoint is set, not the scope of the current
complete discussion of
scopes and scope overrides.
location where the program is stopped. This means that your
breakpoint expression can use only variable names that are valid
at the address in your program where you set the breakpoint,
unless you use scope overrides.
If you want to set a breakpoint for an expression in a module that
isn't currently loaded and TOW cannot find that expression, you
can use either a scope override to specify the file that contains the
expression or the View I Module command to change modules.
If you use variables that are local to a routine as part of an expres-
sion, that breakpoint will execute much more slowly than a break-
point that uses only global or module local variables.

Hardware
breakpoints A hardware breakpoint uses hardware debugging support, either
through a hardware debugging board or through the debugging
registers of the Intel 80386 (or higher) processor. If your system is
See page 72 for information set up for hardware debugging (File I Get Info shows Breakpoints
on setting up device drivers set to Hardware), you can set a hardware breakpoint using one of
for hardware debugging.
the following methods:
• Choose Breakpoints I Changed Memory Global, the most
common use of hardware breakpoints.
•Choose Breakpoints I Hardware.

118 Turbo Debugger for Windows User's Guide


•Display the Breakpoint Options menu (choose Breakpoints I At
or the Set Options command of the View I Breakpoints window
local menu), then do the following:

1. Check the Global check box.


2. Push the Change button.
3. In the Conditions and Actions dialog box, choose the
Hardware radio button tc turn on the Hard•vare pushbutton
at the bottom of the dialog box.
4. Push the Hardware push button to display the Hardware
Breakpoint Options dialog box.
5. Choose the options you want from this dialog box. The
options are described in the online text file
HDWDEBUG.TD.

Logging variable
values Sometimes, you may find it useful to log the value of certain
variables each time you reach a certain place in your program.
For more information on the You can log the value of any expression, including, for example,
Log window, see page 120. the values of the parameters a function is called with. By looking
at the log each time the function is called, you can determine
when it was called with erroneous parameters.
Be careful of side effects Choose the Log radio button from the Breakpoint Options dialog
when logging expressions.
box. You are prompted for the expression whose value is to be
logged each time the breakpoint is triggered.

Breakpoints and
templates TOW supports breakpoints on C++ templates. Breakpoints get set
differently depending on if you use F2 in the Module window, F2
in the CPU window, or the Breakpoint Options dialog box to set
them.

Breakpoints on class There are several methods for setting breakpoints in templates:
templates
• If you set a breakpoint in the template itself by pressing F2
while the cursor is on a line of template source code in the
Module window, breakpoints are set in all class instances of
that template. This feature allows you to debug overall
behavior of the template.

Chapter 7, Breakpoints 119


• If you set a breakpoint in the template by pressing Alt-F2 to
display the Breakpoint Options dialog box, entering the Module
window address of a template expression brings up a dialog
box that lets you choose the class instance for which you want
to set the breakpoint.
•If you open the CPU window, you can see where template code
appears in each class instance of a template. If you position the
cursor on a line of template code in one of the class instances,
pressing F2will set a breakpoint on that class instance only.
You can remove a template breakpoint just as you remove any
breakpoint, by positioning in the Module window on the
highlighted line in the template and pressing F2 or by using the
delete command of the Breakpoints window. When you do so,
any associated class instance breakpoints are removed as well.
If you position in the CPU window on a breakpoint in a class
instance and press F2, only the breakpoint for that class instance is
removed.

Breakpoints on function You set and remove breakpoints for function templates just as you
templates do for class templates. The two methods for setting breakpoints,
pressing F2 or using the Breakpoint Options dialog box, have the
same effects on function instances as they do on class instances.

Breakpoints on You set breakpoints for template class instances and objects of
template class template class instances just like you do for ordinary classes and
instances and objects objects.

The Log window


You create a Log window by choosing the View I Log command.
This window lets you review a list of significant events that have
taken place in your debugging session.
Figure 7.6
The Log window

Log windows show a scrolling list of the lines output to the


window. If more than 50 lines have been written to the log, the

120 Turbo Debugger for Windows User's Guide


oldest lines are lost from the top of the scrolled list. If you want to
change the number of lines in the list, use the TDWINST
customization program (described in the file TDWINST.DOC).
You can also preserve the entire log, continuously writing it to a
disk file, by using the Open Log File local menu command.
Here's a list of what can cause lines to be written to the log:
•Your program stops at a location you specified. The location it
stops at is recorded in the log.
•You issue the Add Comment local menu command. You are
prompted for a comment to write to the log.
•A breakpoint is triggered that logs the value of an expression.
This value is put in the log.
•You use the Edit I Dump Pane to Log command (from the menu
bar) to record the current contents of a pane in a window.
•You are debugging a Windows application and use the Display
Windows Info command on the Log window local menu to
write global heap information, local heap information, or the
module list to the log.
•You are debugging a Windows application, have used the
View I Windows Messages command to display the Windows
Messages window, and are now in the local menu of the
Messages pane of that window. You toggle Send to Log
Window to Yes so all messages coming to this window will also
go to the Log window.

The Log window


local menu The commands in this menu let you control writing the log to a
disk file, stopping and starting logging, adding a comment to the
Open log file ••• log, clearing the log, and writing information about a Windows
Close log file program to the log.
Logging Yes
Add COITlllent ... Alt-Ft 0 pops up the Log window local menu. If you have control-
Erase log
Display Windows info ••• key shortcuts enabled, pressing Ctr/ and the first letter of the
command accesses the command directly.

Open Log File Causes all lines written to the log to be written to a disk file as
well. A dialog box appears that prompts you for the name of the
file to write the log to (or you can select a directory and file from
the list boxes).

Chapter 7, Breakpoints 121


When you open a log file, all the lines already displayed in the log
window's scrolling list are written to the disk file. This lets you
open a disk log file after you see something interesting in the log
that you want to record to disk.
If you want to start a disk log that does not start with the lines
already in the Log window, first choose Erase Log before
choosing Open Log File. ,

Close Log File Stops writing lines to the log file specified in the Open Log File
local menu command, and closes the file.

Logging Enables or disables the log, controlling whether anything is


actually written to the Log window.

Add Comment Lets you insert a comment in the log. You are prompted for a line
of text that can contain any characters you want.

Erase Log Clears the log list. The Log window will now be blank. Only the
log in memory is affected, not the parts of the log that have been
written to a disk file.

Display Windows Info Displays the Windows Information dialog box, which lets you list
10 global heap information, local heap information, or the list of
lEll modules making up your application. See page 166 in Chapter 11
for an explanation of how to use this feature.

122 Turbo Debugger for Windows User's Guide


c H A p T E R

Examining files
TDW treats disk files as a natural extension of the program you're
debugging. You can examine any file on the disk, viewing it either
as ASCII text or as hex data.
This chapter shows you how to examine disk files that contain
your program source code and other files on disk.

Examining program source files


Loading and debugging Program source files are your source files that are compiled to
Windows DLL modules is
described in Chapter 77 on
generate an object module (an .EXE file). You usually examine
page 769. them when you want to look at the behavior or design of a
portion of your code. During debugging, you often need to look
at the source code for a routine to verify either that its arguments
are valid or that it is returning a correct value.
As you step through your program, TDW automatically displays
the source code for the current location in your program.
Files that are included in a source file by a compiler directive and
generate line numbers are also considered to be program source
files, even though they don't appear in the Pick a Module list
pane when you choose View I Module. To select one of these files,
you must use the local menu File command.
You should always use a Module window to look at your
program source files because doing so informs TDW that the file

Chapter 8, Examining files 123


is a source module. TOW then lets you do things like setting
breakpoints or examining program variables simply by moving to
the appropriate place in your file. These techniques and others are
described in the following sections.

The Module
window Before you can open a module window, you must have a program
loaded. You create a Module window by choosing the View I
Module command from the menu bar (or pressing the hot key, F3).
Figure 8.1 [•]=4>1odule: TDDEMO File: TDDEMO.C 37=======1=[t] [~]
static void showargs (1 nt argc, char *argv []);
The Module window
f* program entry point
*/
.. int main(int argc, char *•argv)
{
unsigned int nl ines, nwords, wordcount;
unsigned long totalcharacters;

nlines = 0;
nwords = O;
totalcharacters = O;
showargs( argc, argv);
while (readalineTl != 0) {
wordcount = makeintowords(buffer); "
nwords += wordcount; "
totalcharacters += analyzewords(buffer); "

See page 769 for a A dialog box appears in which you can enter the name of the
description of this Dialog box.
module or OLL you want to view.
When you run TOW, you need TOW then loads the source file for the module you select. If you
both the .EXE file and the select a source module (and not a OLL), TOW searches for the
original source file.
source file in the following places:

1. in the directory where the compiler found the source file


2. in the directories specified by the Options I Path for Source
command or the -sd command-line option
3. in the current directory
4. in the directory that contains the program you're debugging

Module windows show the contents of the source file for the
module you've selected. The title of the Module window shows
the name of the module you're viewing, along with the source file
name and the line number the cursor is on. An arrow <~) in the
first column of the window shows the current program location
(CS:IP).

124 Turbo Debugger for Windows User's Guide


If the abbreviation opt appears after the file name in the title, the
program has been optimized by the compiler. You might have
trouble finding some variables that have been optimized away. In
addition, variables that have become register variables won't have
an address.
If the word modified appears after the file name in the title, the file
has been changed since it was last compiled or linked to make the
program you are debugging. In this case, the rcutines in the
updated source file may no longer have the same line numbers as
those in the version used to build the program you are debug-
ging. If the line numbers are different, the arrow that shows the
current program location (CS:IP) will be displayed on the wrong
line.

The Module
window local The Module window local menu provides a number of com-
menu mands that let you move around in the displayed module, point
at data items and examine them, and set the window to display a
Inspect new file or module.
Watch
Module ... You will probably use this menu more than any other menu in
File ... TDW, so you should become quite familiar with its various
Previous options.
Line ...
Search .•. Use the Alt-F10 key combination to pop up the Module window
Next local menu. If you have control-key shortcuts enabled, you can
Origin
Goto ..• access local menu commands without popping up the menu: Use
the Ctr/ key with the highlighted letter of a command to access that
command (for example, Ctrl-S for Search).

Inspect Opens an Inspector window to show you the contents of the


program variable at the current cursor position. If the cursor isn't
currently on a variable, you're prompted to enter one.
Because this command saves you from having to type in each
name you are interested in, you'll end up using it a lot to examine
the contents of your program variables.

Watch Adds the variable at the current cursor position to the Watches
window. Putting a variable in the Watches window lets you
If the cursor isn't currently on
a variable, you're prompted monitor the value of that variable as your program executes.
to enter one.

Chapter 8, Examining files 125


Module Lets you view a different module by picking the one you want
from the list of modules displayed. This command is useful when
you are no longer interested in the current module, and you don't
want to end up with more Module windows onscreen.

File Lets you switch to view one of the other source files that makes
up the module you are viewing. Pick the file that you want to
view from the list of files presented. Most modules only have a
single source file that contains code. Other files included in a
module usually only define constants and data structures. Use
this command if your module has source code in more than one
file.
Use View I Module to look at the first file. If you want to see more
than one, use View IAnother I Module to open subsequent Module
windows.

Previous Returns you to the last source module location you were viewing.
You can also use this command to return to your previous
location after you've issued a command that changed your
position in the current module.

Line Positions you at a new line number in the file. Enter the new line
number to go to. If you enter a line number after the last line in
the file, you will be positioned at the last line in the file.

Search Searches for a character string, starting at the current cursor


position. Enter the string to search for. If the cursor is positioned
over something that looks like a variable name, the Search dialog
box will come up initialized to that name. Also, if you have
marked a block in the file using the Ins key, that block will be used
to initialize the Search dialog box. This saves you from typing if
what you want to search for is a string that is already in the file
you are viewing.
You can search using simple wildcards, with ? indicating a match
on any single character, and * matching zero or more characters.
The search does not wrap around from the end of the file to the
beginning. To search the entire file, go to the first line by pressing
Ctrl-PgUp.

126 Turbo Debugger for Windows User's Guide


Next Searches for the next instance of the character string you specified
with the Search command; you can only use this command after
initially choosing Search.
Sometimes, Search matches an unexpected string before reaching
the one you really wanted to find. Next lets you repeat the search
without having to reenter what you want to search for.

Origin Positions you at the module and line number that is the current
program location (CS:IP). If the module you are currently viewing
is not the module that contains the current program location, the
Module window will be switched to show that module. This com-
mand is useful after you have looked around in your code and
want to return to where your program is currently stopped.

Goto Positions you at any location within your program. Enter the
address you want to examine; you can enter a procedure name or
a hex address. See Chapter 9 for a complete description of the
ways to enter an address.
If the address doesn't have a You can also invoke this command by simply starting to type the
corresponding source line, a
CPU window is opened.
label to go to. This brings up a dialog box exactly as if you had
chosen the Goto command. Entering the label name is a handy
way to invoke this frequently used command.

Examining other disk files


You can examine any file on your system by using a File window.
You can view the file either as ASCII text or as hex data bytes,
using the Display As command described in a later section of this
chapter.

The File window


You create a File window by choosing View I File from the menu
bar. You can use DOS-style wildcards to get a list of file choices, or
you can type a specific file name to load.

Chapter 8, Examining files 127


.
Figure 8.2 [•]=File ••• S\DEBUG\DEMOS\TDDEMO.C 1==3=[t][H91
The File window /* file <tddemo.c> •
* I
[ * Demonstration program to show off Turboll
* Reads words from standard input, analyzl
* Copyright (c) 1988, 1991 - Borland lnte.,
~
I

• 11 1 1 111 1 n 11 111 __)

File windows show the contents of the file you've selected. The
name of the file you are viewing is displayed at the top of the
window, along with the line number the cursor is on if the file is
displayed as ASCII text.
When you first create a File window, the file appears either as
ASCII text or as hexadecimal bytes, depending on whether the file
contains what TOW thinks is ASCII text or binary data. You can
switch between ASCII and hex display at any time using the
Display As local menu command described later.

~ I
Figure 8.3 [•]=File ••• S\DEBUG\DEMOS\TDDEMO.C 3=[t)[~]"'il
0000: 2f 2a 09 66 69 6c 65 20 /*ofile •
The File window showing hex 0008: 3c 74 64 64 65 6d 6f 2e <tddemo. •
data 0010: 63 3e Od Oa 20 2a Od Oa c>Jll *JI
0018: 20 2a 09 44 65 6d 6f 6e *oDemon
0020: 73 74 72 61 74 69 6f 6e stration
0028: 20 70 72 6f 67 72 61 6d program
0030: 20 74 6f 20 73 68 6f 77 to show .,
•I Ill 11111111 I 111111 __)

The File window


local menu The File window local menu has a number of commands for
moving around in a disk file, changing the way the contents of the
file are displayed, and making changes to the file.
Goto •.•
Search •••
Next
Display as Asci i
File •..

Use the A/t-F10 key combination to pop up the File window local
menu or, if you have control-key shortcuts enabled, use the Ctr/
key with the highlighted letter of the desired command to access
the command without invoking the local menu.

128 Turbo Debugger for Windows User's Guide


Goto Positions you at a new line number or offset in the file. If you are
viewing the file as ASCII text, enter the new line number to go to.
If you are viewing the file as hexadecimal bytes, enter the offset
from the start of the file at which to start displaying. You can use
the full expression parser for entering the offset. If you enter a line
number after the last line in the file or an offset beyond the end of
the file, TOW positions you on the last line of the file.

Search Searches for a character string, starting at the current cursor


position. You are prompted to enter the string to search for. If the
cursor is positioned on something that looks like a symbol name,
the Search dialog box comes up initialized to that name. Also, if
you have marked a block in the file using the Ins key, that block
will be used to initialize the Search dialog box. This saves you
from typing if what you want to search for is a string that is
already in the file you are viewing. The format of the search string
depends on whether the file is displayed in ASCII or hex.
If the file is displayed in ASCII, you can use simple DOS
wildcards, with ? indicating a match on any single character, and *
matching 0 or more characters.
See page 739 for complete If the file is displayed in hexadecimal bytes, enter a byte list
information about byte lists.
consisting of a series of byte values or quoted character strings,
using the syntax of whatever language you are using for
expressions.
For example, if the language is C++, a byte list consisting of the
hex numbers 0408 would be entered as follows:
Ox0804

If the language is Pascal, the same byte list is entered as


$0804
The search does not wrap around from the end of the file to the
beginning. To search the entire file, go to the first line of the file by
pressing Ctrl-PgUp.
You can also invoke this command by simply starting to type the
string that you want to search for. This brings up a dialog box
exactly as if you had specified the Search command.

Chapter 8, Examining files 129


Next Searches for the next instance of the character string you specified
with the Search command; you can only use this command after
initially choosing Search.
Next is useful when your Search command didn't find the
instance of the string you wanted; you can keep issuing this
command until you find what you want.

Display As Toggles between displaying the file as ASCII text or as


hexadecimal bytes.
• If you choose ASCII display, the file appears as you are used to
seeing it on the screen in an editor or word processor.
•If you choose Hex display, each line starts with the hex offset
from the beginning of the file for the bytes on the line. Eight
bytes of data are displayed on a line. To the right of the hex
display of the bytes, the display character for each byte appears.
The full display character set can be displayed, so byte values
less than 32 or greater than 127 appear as the corresponding
display symbol.

File Lets you switch to a different file. You can use DOS wildcards to
get a list of file choices, or you can type a specific file name to
load. File lets you view a different file without putting a new File
window onscreen. If you want to view two different files or two
parts of the same file simultaneously, choose View IAnother I File
to make another File window.

130 Turbo Debugger for Windows User's Guide


c H A p T E R

Expressions
Expressions can be a mixture of symbols from your program (that
is, variables and names of routines), and constants and operators
from one of the supported languages: C, Pascal, or assembler.
Each language evaluates an TDW can evaluate expressions and tell you their values. You can
expression differently. also use expressions to indicate data items in memory whose
value you want to know. You can supply an expression in any
dialog box that asks for a value or an address in memory.
Use Data I Evaluate/Modify to open the Evaluate/Modify dialog
box, which tells you the value of an expression. (You can also use
this dialog box or the Watches window as a simple calculator.)
In this chapter, you'll learn how TDW chooses which language to
use for evaluating an expression and how you can make it use a
specific language. We describe the components of expressions that
are common to all the languages, such as source-line numbers and
access to the processor registers. We then describe the
components that can make up an expression in each language,
including constants, program variables, strings, and operators.
For each language, we also list the operators that TDW supports
and the syntax of expressions.
For a complete discussion of C, C++, a.nd assembler expressions,
refer to your Turbo C++ for Windows User's Guide.

Chapter 9, Expressions 131


Choosing the language for expression evaluation
TOW normally determines which expression evaluator and
language to use from the language of the current module. This is
the module in which your program is stopped. You can override
this by using the Options I Language command to open the
Expression Language dialog box; in it you can set radio buttons to
Source, Pascal, C, or Assembler. If you choose Source, expressions
are evaluated in the manner of the module's language. (If TOW
can't determine the module's language, it uses the expression
rules for inline assembler.)
Usually, you let TOW choose which language to use. Sometimes,
however, you'll find it useful to set the language explicitly; for
example, when you are debugging an assembler module that is
called from one of the other languages. By explicitly setting
expression evaluation to use a particular language, you can access
your data in the way you refer to it with that language, even
though your current module uses a different language.
Sometimes it's convenient to treat expressions or variables as if
they had been written in a different language; for example, if
you're debugging a C++ program, assembly language conven-
tions might offer an easier way to change the value of a byte
stored in a string.
If your initial choice of language is correct when you enter TOW,
you should have no difficulty using other language conventions.
TOW still retains information about the original source language
and handles the conversions and data storage appropriately. If the
language seems ambiguous, TOW defaults to assembly language.
Even if you deliberately choose the wrong language when you
enter TOW, it will still be able to get some information about the
original source language from the symbol table and the original
source file. Under some circumstances, however, it may be
possible to cause TOW to store data incorrectly.

Code addresses, data addresses, and line numbers


Normally,·when you want to access a variable or the name of a
routine in your program, you simply type its name. However, you
can also type an expression that evaluates to a memory pointer, or

132 Turbo Debugger for Windows User's Guide


specify code addresses as source line numbers by preceding the
line number with a number sign(#), like #123 (C, C++, and
Assembler only). The next section describes how to access
symbols outside the current scope.
Of course, you can also specify a regular segment:offset address,
using the hexadecimal syntax for the source code language of
your program:

Language Format Example


c Oxnnnn Ox1234:0x0010
Assembler nnnnh 1234h:0010h
1234h:OB234h
In assembler, hex numbers starting with A to F must be
prefixed with a zero.

Accessing symbols outside the current scope


Where the debugger looks for a symbol is known as the scope of
that symbol. Accessing symbols outside of the current scope is an
advanced concept that you don't really need to understand in
order to use TDW in most situations.
Normally, TDW looks for a symbol in an expression the same way
a compiler would. For example, Pascal first looks in the current
procedure or function, then in an "outer" subprogram (if the
active scope is nested inside another), then in the implementation
section of the current unit (if the current scope resides in a unit),
and then for a global symbol.
If TDW doesn't find a symbol using these techniques, it searches
through all the other modules to find a static symbol that
matches. This lets you reference identifiers in other modules
without having to explicitly mention the module name.
If you want to force TDW to look elsewhere for a symbol, you can
exert total control over where to look for a symbol name by
specifying a module, a file within a module, or a routine to look
inside. You can access any symbol in your program that has a
defined value, even symbols that are private to a function and
have names that conflict with other symbols.

Chapter 9, Expressions 133


Scope override
syntax Depending on your current language setting, you use a different
symbol to override the scope of a symbol name. Because you can
change the language setting with Options I Language in order to
use features of the different scope override syntaxes, we show
you both sets of syntax.
•With C, C++, and Turbo Assembler, use the cross hatch(#)
symbol to override scope.
• With Pascal, use the period (.) to override scope.
You can enter qualified identifier expressions anywhere an
expression is valid, including
•the Evaluate/Modify dialog box
•the Watches window
• a Data I Inspector window
• the dialog box displayed by the Goto local menu command of
the Module window (when you want to go to an address in the
source code)

Overriding scope in C, Use a pound sign (#) to separate the components of the scope.
C++, and assembler
The following syntax describes scope overriding; brackets ([])
programs
indicate optional items:
Scope operators don't work [#module[#filename.ext]]#linenumber[#variablename]
with register variables.
or
[#module[#filename.ext]#] [functionname#]variablename
If you don't specify a module, the current module is assumed.
For example, in the Watches window, you could enter different
line numbers for the TDDEMO variable nlines so you could see
how its value changes in different routines in the current module.
To watch the variable both on line 51 and on line 72, you would
make the following entries in the Watches window:
#Sl#nwords
#72#nwords
Here are some examples of valid symbol expressions with scope
overrides. There is one example for each of the legal combinations
of elements that you can use to override a scope.

134 Turbo Debugger for Windows User's Guide


The first six examples show various ways of using line numbers
to generate addresses and override scopes:
#123
Line 123 in the current module
#123#myvarl
Symbol myvar1 accessible from line 123 of the current
module
#mymodule#123
Line 123 in module mymodule
#mymodule#123#myvarl
Symbol myvar1 accessible from line 123 in module mymodule
#mymodule#filel.cpp#123
Line 123 in source file filel.cpp, which is part of module
mymodule
#mymodule#filel.cpp#123#myvarl
Symbol myvar1 accessible from line 123 in source file
filel.cpp, which is part of mymodule
The next six examples show various ways of overriding the scope
of a variable by using a module, file, or function name:
#myvar2
Same as myvar2 without the #
myfunc#myvar2
Variable myvar2 accessible from routine myfunc
#mymodule#myvar2
Variable myvar2 accessible from module mymodule
#mymodule#myfunc#myvar2
Variable myvar2 accessible from routine myfunc in module
mymodule
#mymodule#file2.c#myvar2
Variable myvar2 accessible from file2.c, which is included in
mymodule
#mymodule#file2.c#myfunc
myfunc defined in file file2.c, which is included in mymodule
The following four examples show how to use scope override
syntax with C ++ classes, objects, member functions, and data
members:

Chapter 9, Expressions 135


AnObject#AMemberVar
Data member AMemberVar accessible in object AnObject
accessible in the current scope
AnObject#AMemberF
Member function AMemberF accessible in object AnObject
accessible in the current scope
#AModule#AnObject#AMemberVar
Data member AMemberVar accessible in object AnObject
accessible in module AModule
#AModule#AnObject#AClass::AMemberVar
Data member AMemberVar of class AClass accessible in
object AnObject accessible in module AModule
¢ If you're debugging a C++ program and want to examine a
function with an overloaded name, just enter the name of the
function in the appropriate input box. Turbo Debugger opens the
Pick a Symbol Name dialog box, which shows a list box of all the
functions of that name with their arguments, enabling you to
choose the one you want.

Scope override tips


The following tips might help you when overriding scope in C,
C++, and Turbo Assembler programs:

1. If you use a file name in a scope override statement, it must be


preceded by a module name.
2. If a file name has an extension, such as .ASM, .C, or .CPP, you
must specify the extension; Turbo Debugger doesn't try to
determine the extension itself.
3. If a function name is the first item in a scope override state-
ment, it must not have a# in front of it. If there's a#, Turbo
Debugger interprets the function name as a module name.
4. Any variable you access through scope override syntax must
have been initialized already. An automatic variable doesn't
have to be in scope, but its function must have run already.
5. If you're trying to access an automatic variable that's no longer
in scope, you must use its function name as part of the scope
override statement.
• The scope of a template depends on the current location in
the program. Watches and Inspector windows on template

136 Turbo Debugger for Windows User's Guide


expressions are dependent on the current object the
program is in.
•A nested class is in the scope of the class it's nested in. The
scope of a nested class isn't global to the program.

Overriding scope in Use a period(.) to separate the components of the scope.


Pascal programs
The following syntax describes scope overriding; brackets ([])
indicate optional items:
[unit.] [procedurename.]variablename

or
[unit.] [objecttype.] [objectinstance.] [method.]fieldname

If you don't specify a unit, the current unit is assumed.


Here are some examples of valid symbol expressions with scope
overrides. There is one example for each of the legal combinations
of elements that you can use to override a scope.
These examples show various ways of overriding the scope of a
variable by using a module or procedure name:
MyVar2
Variable MyVar2 in the current scope
MyProc.MyVar2
Variable MyVar2 accessible from routine MyProc
MyUnit.MyVar2
Variable MyVar2 accessible from unit MyUnit
MyUnit.MyProc.MyVar2
Variable MyVar2 accessible from routine MyProc in unit
My Unit
The following examples show how to use scope override syntax
with object types, object instances, fields, and methods:
Aninstance
Instance Anlnstance accessible in the current scope.
Aninstance.AField
Field Afield accessible in instance Anlnstance accessible in
the current scope
AnObjectType.AMethod
Method AMethod accessible in object type AnObjectType
accessible in the current scope

Chapter 9, Expressions 137


Aninstance.AMethod
Method AMethod accessible in instance Anlnstance accessible
in the current scope
AUnit.Aninstance.AField
Field Afield accessible in instance Anlnstance accessible in
unitAUnit
AUnit.AnObjectType.AMethod
Method AMethod accessible in object type AnObjectType
accessible in unit AUnit
AUnit.Aninstance.AMethod.ANestedProc.AVar
Local variable A Var accessible in nested procedure
ANestedProc accessible in method AMethod accessible in
instance Anlnstance accessible in unit AUnit

Scope override tips


The following tips might help you when overriding scope in
Pascal programs:

1. Any variable you access through scope override syntax must


have been initialized already. The procedure or function
containing a local variable doesn't have to be in scope, but it
must have run already.
2. If you are trying to access a local variable that's no longer in
scope, you must use its procedure or function name as part of
the scope override statement.
3. You can't use a line number or a file name as part of a Pascal
scope override statement. However, you can use Options I
Language to change the language to C so you can use line
number syntax.

Scope and DLLs Because TDW simultaneously loads the symbol tables of the
current module of your .EXE file and of any DLLs it accesses that
have source code and symbol tables, you might not have
immediate access to variables in your DLLs (or in your .EXE if
you're currently in a DLL).
TDW looks for a variable first in the symbol table of the current
module or DLL, and then in any other symbol tables in order of
loading. If a variable has the same name in multiple DLLs or in
your .EXE and one or more DLLs, TDW sees only the first
instance it finds. You can't use scope override syntax to access any

138 Turbo Debugger for Windows User's Guide


¢ such variables; instead, you must press F3 and use the Load
Modules and DLLs dialog box to load the appropriate module or
DLL.
TOW loads symbol tables for the following:

1. the current module of your .EXE file


2. any DLL you explicitly load using the Symbol Load command
in the Load Modules and DLLs dialog box (displayed with F3
or View I Module)
3. any DLL you step into from your program

Implied scope for


expression Whenever TOW evaluates an expression, it must decide where
evaluation the current scope is for any symbol names without an explicit
scope override. Determining scope is important because in many
languages you can have symbols inside functions or procedures
with the same name as global symbols, and TOW must know
which instance of a symbol you mean.
TOW usually uses the current cursor position as the context for
determining the scope. Thus, you can set the scope where an
expression will be evaluated by moving the cursor to a specific
line in a Module window.
One result is that if you've moved the cursor off the current line
where your program is stopped, you might get unexpected results
from evaluating expressions. If you want to be sure that expres-
sions are evaluated in your program's current scope, use the
Origin local menu command in the Module window to return to
the current location in the source code. You can also set the
expression scope by moving around inside the Code pane of a
CPU window, by moving the cursor to a routine in the Stack
window, or by moving the cursor to a routine name in a Variables
window.

Byte lists
Several commands ask you to enter a list of bytes, including the
Search and Change local menu commands in the Data pane of the
CPU window, and the Search local menu command of the File
window when it's displaying a file in hexadecimal format.

Chapter 9, Expressions 139


A byte list can be any mixture of scalar (non-floating-point) num-
bers and strings in the syntax of the current language, determined
by the Options I Language command. Both strings and scalars use
the same syntax as expressions. Scalars are converted into a
corresponding byte sequence. For example, a Longint value of
123456 becomes a 4-byte hex quantity 40 E2 01 00.

Language Byte list Hex data


Pascal 'ab'$04'c' 6162 04 63
Assembler 1234 "AB" 3412 4142
c "ab" Ox04 "c" 6162 0463

C expressions
TOW supports the complete C expression syntax. A C expression
consists of a mixture of symbols, operators, strings, variables, and
constants. Each of these components is described in one of the
following sections.

C symbols
A symbol is the name of a data object or routine in your program.
A symbol name must start with a letter (a-z, A-Z) or underscore
(_). Subsequent characters can be any of these characters as well
as the digits 0 through 9. You can omit the beginning underscore
from symbol names; if you enter a symbol name without an
underscore and TOW can't find that name, it searches for the
name again with an underscore at the beginning. Because the
compiler automatically puts an underscore at the start of your
symbol names, you don't have to remember to add one.

C register
pseudovariables mw lets you access the processor registers using the same
technique as one of Borland's C or C++ compilers, namely
pseudovariables. A pseudovariable is a variable name that
corresponds to a given processor register.

140 Turbo Debugger for Windows User's Guide


Pseudovariable Type Register
_AX unsigned int AX
- AL unsigned char AL
- AH unsigned char AH
- BX unsigned int BX
- BL unsigned char BL
- BH unsigned char BH
_ex unsigned int ex
CL unsigned char CL
_CH unsigned char CH
- DX unsigned int DX
- DL unsigned char DL
- DH unsigned char DH
_cs unsigned int cs
- DS unsigned char DS
- SS unsigned char SS
- ES unsigned char ES
_SP unsigned int SP
- BP unsigned char BP
- DI unsigned char DI
_SI unsigned char SI
_IP unsigned int IP

The following pseudovariables let you access the 80386 processor


registers:

Pseudovariable Type Register

- EAX unsigned long EAX


- EBX unsigned long EBX
- ECX unsigned long ECX
- EDX unsigned long EDX
_ESP unsigned long ESP
- EBP unsigned long EBP
_EDI unsigned long EDI
- ESI unsigned long ESI
- FS unsigned int FS
_GS unsigned int GS

Chapter 9, Expressions 141


C constants and
number formats Constants can be either floating point or integer.
An integer constant is specified in decimal, unless one of the C
conventions for overriding this is used:

Format Radix
digits decimal
Odigits octal
OXdigits hexadecimal
Oxdigits hexadecimal

Constants are normally of type int (16 bits). If you want to define
a long (32-bit) constant, you must add an l or L at the end of the
number. For example, 123456L.
A floating-point constant contains a decimal point and can use
decimal or scientific notation. For example,
1. 23 4 4. Se+ 11

Escape
sequences A string is a sequence of characters enclosed in double quotes("").
You can use the standard C backslash(\) as an escape character.

Sequence Value Character


\\ oxsc Backslash
\a OX07 Bell
\b OX08 Backspace
\f oxoc Formfeed
\n OXOA Newline
\r OXOD Carriage return
\t OX09 Horizontal tab
\v OXOB Vertical tab
\xnn nn Hex byte value
\nnn nnn Octal byte value

If you follow the backslash with any other character than those
listed here, that character is inserted into the string unchanged.

142 Turbo Debugger for Windows User's Guide


C operator
precedence TDW uses the same operators as C, with the same precedence.
The debugger has one operator that is part of the C++ set of
operators: the double colon (::). This operator has a higher priority
than any of the regular C operators. It is used to make a constant
far address out of the expression that precedes it and the expres-
sion that follows it; for example,
OX1234: :OXlOOO
ES:: BX

The primary expression operators


[] -> sizeof
have the highest priority, from left to right. The unary operators
* & ++
are of a lower priority than the primary operators but a greater
priority than the binary operators, grouped from right to left. The
priority of the binary operators, in descending order, is as follows
(operators on the same line have the same priority):
highest * I %
+
>> <<
< > <= >=
-- !=
&
/\

I
&&
lowest II
The single ternary operator, ?:, has a priority below that of the
binary operators.
The assignment operators are below the ternary operator in
priority. They are all of equal priority, and group from right to
left:
= += -= *= I= %= >>= <<= &= "= I=

Chapter 9, Expressions 143


Executing C
functions in your
program You can call functions from a C expression exactly as you do in
your source code. TOW actually executes your program code with
the function arguments that you supply. This can be a very useful
way of quickly testing the behavior of a function you've written.
You can repeatedly call it with different arguments and then
check that the returned value is correct each time.
The following function raises one integer number to a power (xY):
long power(int x, int y)
{
long temp = 1;
while (y--)
temp *= x;
return (temp);

The following table shows the result of calls to this function with
different function arguments:

C expression Result
power(3,2) * 2 18
25 + power(5,8) 390650
power(2) Error (missing argument)

C expressions with
side effects A side effect occurs when you evaluate a C expression that
changes the value of a data item in the process of being evaluated.
In some cases, you may want a side effect, using it to intentionally
modify the value of a program variable. At other times, you want
to be careful to avoid them, so it's important to understand when
a side effect can occur.
The assignment operators (=, +=, and so on) change the value of
the data item on the left side of the operator. The increment and
decrement(++ and - -) operators change the value of the data
item that they precede or follow, depending on whether they are
used as prefix or postfix operators.

144 Turbo Debugger for Windows User's Guide


A more subtle type of side effect can occur if you execute a func-
tion that's part of your program. For example, if you evaluate the
C expression
myfunc(l,2,3) + 7

your program may misbehave later if myfunc changed the value


of other variables in your program.

C reserved words
and type TDW lets you perform type conversions on (cast) pointers exactly
conversion as you would do in a C program. A type conversion consists of a C
data-type declaration between parentheses. It must come before
an expression that evaluates to a memory pointer.
Type conversions are useful if you want to examine the contents
of a memory location pointed to by a far address you generated
using the double colon (::) operator. For example,
(long far *)Ox3456::0

(char far *)_ES: :_BX

You can use a type conversion to access a program variable for


which there is no type information, which happens when you
compile a module without generating debugging-type informa-
tion. Rather than recompiling and relinking, if you know the data
type of a variable, you can simply put that in a type conversion
before the name of the variable.
For example, if your variable iptr is a pointer to an integer, you
can examine the integer that it points to by evaluating the C
expression
*(int *) iptr

You can also use the Type Cast command in the Inspector
window local menu for this purpose.
TDW provides two reserved words, lh2fp and gh2fp, for
dereferencing memory handles used in Windows applications.
See page 175 for an explanation of these two type conversions.

Chapter 9, Expressions 145


Use the following C reserved words to perform type conversions
forTDW:
char float near
double huge short
enum int struct
far long union
unsigned

Assembler expressions
TDW supports the complete assembler expression syntax. An
assembler expression consists of a mixture of symbols, operators,
strings, variables, and constants. Each of these components is
described in this section.

Assembler
symbols Symbols are user-defined names for data items and routines in
your program. An assembler symbol name starts with a letter (a-z,
A-Z) or one of these symbols: @ ? _ $. Subsequent characters in
the symbol can contain the digits 0 to 9, as well as these char-
acters. The period (.) can also be used as the first character of a
symbol name, but not within the name.
The special symbol $ refers to your current program location as
indicated by the CS:IP register pair.

Assembler
constants Constants can be either floating point or integer. A floating-point
constant contains a decimal point and may use decimal or scien-
tific notation. For example,
1.234 4.Se+ll
Integer constants are hexadecimal unless you use one of the
assembler conventions for overriding the radix:

146 Turbo Debugger for Windows User's Guide


Format Radix
digitsH Hexadecimal
digitsO Octal
digitsQ Octal
If you want to end a hex digitsD Decimal
number with a D or 8, you
must append an H to avoid digitsB Binary
ambiguity.
You must always start a hexadecimal number with one of the
digits 0 to 9. If you want to enter a number that starts with one of
the letters A to F, you must first precede it with a 0 (zero).

Assembler
operators TOW supports most of the assembler operators. The first line in
the list that follows shows the operators with the lowest priority,
and the last line those operators with the highest priority. Within
a line, all the operators have the same priority.
xxx PTR (BYTE PTR .. .)
. (structure member selector)
: (segment override)
OR XOR
AND
NOT
EQ NE LT LE GT GE
+ -
* I MOD SHR SHL
Unary+ Unary-
OFFSET SEG
() []

Variables can be changed using the = assignment operator. For


example,
a = [BYTE PTR DS:4]

Format control
When you supply an expression to be displayed, TOW displays it
in a format based on the type of data it is. TOW ignores a format
control that is wrong for a particular data type.

Chapter 9, Expressions 147


If you want to change the default display format for an expres-
sion, place a comma at the end of the expression and supply an
optional repeat count followed by an optional format letter. You
can only supply a repeat count for pointers or arrays.

Character Format
c Displays a character or string expression as raw
characters. Normally, nonprinting character values are
displayed as some type of escape or numeric format.
This option forces the characters to be displayed using
the full IBM display character set.
d Displays an integer as a decimal number.
f[#] Displays as floating-point format with the specified
number of digits. If you don't supply a number of
digits, as many as necessary are used.
m Displays a memory-referencing expression as hex
bytes.
md Displays a memory-referencing expression as decimal
bytes.
p Displays a raw pointer value, showing segment as a
register name if applicable. Also shows the object
pointed to. This is the default if no format control is
specified.
s Displays an array or a pointer to an array of characters
as a quoted character string.
xorh Displays an integer as a hexadecimal number.

148 Turbo Debugger for Windows User's Guide


c H A p T E R

10

Object-oriented debugging
To meet the needs of the object-oriented programming revolution,
TOW supports C++. Besides extensions that let you trace into
member functions and examine objects in the Evaluate/Modify
dialog box and the Watches window, TOW comes equipped with
a special set of windows and local menus specifically designed for
object types and classes.

The Hierarchy window


TOW provides a special window for examining class hierarchies.
You can bring up the Hierarchy window by choosing View I
Hierarchy.
Figure 10.l = = = = = = = = 3 = [ t ] [+]
evi ce --Point
The Hierarchy window ,lowGauge L ___ -Rectangle
,orzArrow f----- --Devi Ce*
rlorz Bar I____ - - TextWindow
Li nearGauge Range
Point L___:_---Oev1 ce
Range --Gl owGauge
Rectangle
3creen Parents of Device
Tex tWindow f----Range
VertArrow L-----Rectangl e
vert8ar c__---Po1nt
1
Screen

Chapter 70, Object-oriented debugging 149


Use Tab to move between The Hierarchy window displays information on classes rather
the two panes. than instances of classes. There are either two or three panes. If
the program is a C++ program using multiple inheritance, three
panes appear. Otherwise, only two panes appear.
•The left pane, the Class List pane, lists in alphabetical order the
classes used by the module being debugged.
• The top right pane, the Hierarchy Tree pane, shows all classes
in their hierarchies by using a line graphic that places the
original base class at the left margin of the pane and displays
derived classes beneath and to the right of the base class, with
lines indicating derived class relationships. Any class followed
by an asterisk inherits from multiple base classes and shows up
in the pane below.
•The bottom right pane, the Parent Tree pane, if it exists, shows
all base classes for classes with multiple inheritance.

The Class List


pane The left pane of the Hierarchy window provides an alphabetical
list of all classes used by the current module. It supports an
incremental matching feature to eliminate the need to scroll
through large lists of classes: When the highlight bar is in the left
pane, simply start typing the name of the class you're looking for.
At each key press, TOW highlights the first class matching all
keys pressed up to that point.
Press Enter to open a class Inspector window for the highlighted
class. Class Inspector windows are described on page 152.

The Class List pane Press Alt-F10 to display the local menu for the pane. You can use
local menu the control-key shortcuts if you've enabled hot keys with
TDWINST. This local menu contains two items: Inspect and Tree.

Inspect
Tree Inspect
Displays a class Inspector window for the highlighted type.

150 Turbo Debugger for Windows User's Guide


Tree
Moves to the right pane in which the hierarchy tree is displayed
and places the highlight bar on the class that was highlighted in
the left pane.

The Hierarchy
Tree pane The top right pane displays the hierarchy tree for al! dasses used
by the current module. Base class and derived class relationships
are indicated by lines, with derived classes to the right of and
below their base classes.
To locate a single class in a complex hierarchy tree, go back to the
left pane and use the incremental search feature; then choose the
Tree command from the local menu to move back into the
hierarchy tree. The matched class appears under the highlight bar.
When you press Enter, a class Inspector window appears for the
highlighted class.

The Hierarchy Tree The Hierarchy Tree pane local menu (press Alt-F10 in the pane) has
pane local menu(s) only one item for C programs or for C ++ programs without
multiple inheritance: Inspect. When you choose it, a Inspector
Inspect window appears for the highlighted class. However, a faster and
easier method is simply to press Enter when you want to inspect
the highlighted class.

Inspect If you have loaded a C++ program that uses classes with multiple
Parents Yes inheritance, the Hierarchy Tree pane local menu contains a
second command, Parents. Use this command to toggle between
showing and not showing the base classes of a class with multiple
inheritance in the Parent Tree pane. The default for Parents is Yes.

The Parent Tree


pane If you have loaded a C++ program that uses classes with multiple
inheritance, a third pane, the Parent Tree pane, appears below the
Hierarchy Tree pane in the Hierarchy window. If the class you are
examining has multiple ancestors and the Parent command in the
Hierarchy Tree pane local menu is set to Yes, a reverse tree
appears in the Parent Tree pane. This tree has the message Parents
of Class at the left margin of the pane and displays the base
classes beneath and to the right, with lines indicating base class
and derived class relationships.

Chapter 70, Object-oriented debugging 151


You can open a class Inspector window for any class that appears
in the Parent Tree pane, just as you can in the Hierarchy Tree
pane.

The Parent Tree pane The Parent Tree pane, if it exists, has a local menu of its own with
local menu a single command, Inspect. It works just the same as the Inspect
command in the Hierarchy Tree pane local menu: It opens an
J Inspect Inspector window for the highlighted class.

Class Inspector windows


TOW provides a special type of Inspector window to let you
inspect the details of a class: the class Inspector window. The win-
dow summarizes class information, but does not reference any
particular instance. You display this window by bringing up the
Hierarchy window (choose View I Hierarchy), selecting a class,
and pressing Ctr/-/.
Figure 10.2
A class Inspector window

The window is divided horizontally into two panes, with the top
pane listing the data members of the class and their types, and the
bottom pane listing the member function names and the function
return types. Use Tab to move between the two panes of the class
Inspector window.
If the highlighted data member is a pointer to a class, pressing
Enter opens another class Inspector window for the highlighted
class. (This action is identical to choosing Inspect in the local
menu for this pane.) In this way, complex nested structures of
classes can be inspected quickly with a minimum of keystrokes.
For brevity's sake, member function parameters are not shown in
the class Inspector window. To examine parameters, highlight the
member function and press Enter. A member function Inspector
window appears that displays the code address for the object's
implementation of the selected member function and the names
and types of all its arguments.

152 Turbo Debugger for Windows User's Guide


Pressing Enter from anywhere within the member function
Inspector window brings the Module window or the CPU
window to the foreground, with the cursor at the code that
implements the member function being inspected.
As with standard inspectors, Esc closes the current Inspector
window and Alt-F3 closes them all.

The ciass
Inspector window Pressing Alt-F10brings up the local menu for either pane. If
local menus control-key shortcuts are enabled (through TDWINST), you can
get to a local menu item by pressing Ctr/ and the first letter of the
item.
Inspect
Hierarchy
Show inherited Yes

The Data Member (top) The Data Member pane local menu contains these items:
pane

Inspect
If the highlighted field is a a pointer to a class, a class Inspector
window is opened for the highlighted field.

Hierarchy
Opens a Hierarchy window for the class being inspected. The
Hierarchy window is described on page 149.

Show Inherited
Yes is the default value of this toggle. When Show Inherited is set
to Yes, TOW shows all data members, whether they are defined
within the class of the inspected object or inherited from a base
class.
When the toggle is set to No, TOW displays only those data
members defined within the class being inspected.

Chapter 70, Object-oriented debugging 153


The Member Function The local menu commands for the bottom Member Function pane
(bottom) pane are Inspect, Hierarchy, and Show Inherited.

Inspect
A member function Inspector window is opened for the
highlighted item. If you press Ctr/-/ when the cursor is positioned
over the address shown in the member function Inspector win-
dow, the Module window is brought to the foreground with the
cursor at the code that implements what is being inspected.

Hierarchy
Opens a Hierarchy window for the class being inspected. The
Hierarchy window is described on page 149.

Show Inherited
Yes is the default value of this toggle. When it is set to Yes, all
member functions are shown, whether they are defined within the
class being inspected or inherited from a base class. When it is set
to No, only those member functions are displayed that are defined
within the class being inspected.

Object Inspector windows


Class Inspector windows provide information about classes, but
say nothing about the data contained in a particular object at a
particular time during program execution. TOW provides an ex-
tended form of the familiar record Inspector window specifically
to inspect objects.
Bring up this window by placing your cursor on an object in the
Module window, then pressing Ctr/-/.

154 Turbo Debugger for Windows User's Guide


Figure 10.3 [•]=Inspecting tW=3=[t] [+]=;i
An object Inspector window 5C6:01E8 ..
creen: :MaxX 500 OxlF4
creen: :MaxY 512 (Ox200)

ere en:· Convert @0000 · 0000


creen: :VertVtoA @0000:0000
creen: ·VertAtoV 00000:0000

Most TDW structure Inspector windows have two panes: a top


pane summarizing the structure's member names and their
current values, and a bottom pane displaying the type of the
member highlighted in the top pane. An object Inspector window
provides both of those panes, and also a third pane between them.
This third pane summarizes the object's member functions, with
the code address of each.

The object
Inspector window Each of the top two panes of the object Inspector window has its
local menus own local menu, displayed by pressing Alt-F10in that pane. Use
the control-key shortcuts to get to individual menu items if you've
enabled hot keys with TDWINST.

Range ...
Change ..• Similar to structure Inspector windows, the bottom pane serves
Methods Yes only to display the class of the highlighted data member and
Show inherited Yes
doesn't have a local menu.
Inspect
Descend The local menu commands for the top pane, which summarizes
New expression .•.
Type cast the data members for the selected item, are described here.
Hierarchy

Range This command displays the range of array items. If the inspected
item is not an array or a pointer, the item cannot be accessed.

Change By choosing this command, you can load a new value into the
highlighted data member.

Methods This command is a Yes/No toggle, with Yes as the default condi-
tion. When it's set to Yes, member functions are summarized in
the middle pane. When it's set to No, the middle pane doesn't
appear. This toggle is remembered by the next Inspector window
to be opened.

Chapter 70, Object-oriented debugging 155


Show Inherited This command is also a Yes/No toggle. When it's set to Yes, all
data members and all member functions are shown, whether they
are defined within the class being inspected or inherited from a
base class. When the command is set to No, only those data
members and member functions defined within the class being
inspected are displayed.

Inspect Choosing this command opens an Inspector window on the


highlighted data member. Pressing Enter over a highlighted data
member does the same thing.

Descend The highlighted item takes the place of the item in the current
Inspector window. No new Inspector window is opened.
However, you can't return to the previously inspected data
member, as you could if you had used the Inspect option.
¢ Use Descend to inspect a complex data structure when you don't
want to open a separate Inspector window for each item.

New Expression This command prompts you for a new data item or expression to
inspect. The new item replaces the current one in the window; it
doesn't open another window.

Type Cast Lets you specify a different data type for the item being inspected.
This command is useful if the Inspector window contains a
symbol for which there is no type information, as well as for
explicitly setting the type for pointers.

Hierarchy When you choose this command, a Hierarchy window opens. For
a full description of this window, see page 149.

The middle and


bottom panes The middle pane summarizes the member functions of an object.
The only difference between the Object Member function pane's
local menu and the local menu for the top pane is the absence of
the Change command. Unlike data members, member functions
cannot be changed during execution, so there is no need for this
command. The bottom pane displays the type of the item high-
lighted in the upper two windows.

156 Turbo Debugger for Windows User's Guide


c H A p T E R

ll

Using Windows debugging features


This chapter covers the features of TDW that give you access to
Windows information and allow you to do the following:
•Log messages received and sent by your application's windows
•List the global heap
• List the local heap
•View the complete list of modules (including dynamic link
libraries) loaded by Windows
•Debug dynamic link libraries (DLLs)
•See the contents of any protected-mode selector (in the CPU
window)

Windows features
The features that support debugging of Windows programs are
•A view window, the Windows Messages window, which shows
messages passed to windows in your program
•Three types of data you can display in the Log window:
• The data segments in your program's local heap
• The data segments in the global heap
• A complete list of modules making up your program,
including any dynamic link libraries (DLLs)

Chapter 77, Using Windows debugging features 157


• Expression typecasting from memory handles to far pointers
• Support for debugging of DLLs in the Load Module Source or
DLL Symbols window (choose View IModules)
•The Selector pane of the CPU window, which allows you to see
the contents of any protected-mode selector.

Logging window
messages To track messages being passed to your program's windows,
choose the View IWindows Messages command to open the
Windows Messages window. This window shows you the
messages that Windows is passing to one or more windows in
your program.
The Windows Messages window is composed of three panes, the
Window Selection pane (top left), the Message Class pane (top
right), and the Messages pane (bottom). The messages show up in
the Messages pane.
The appearance of this window and the way you add application
windows to it differ depending on whether you're working with
an ObjectWindows application or a standard Windows
application.

Selecting a window for If you're debugging a standard Windows application and you
a standard Windows select View IWindows Messages, you see the following window:
application
Figure 11.l
The Windows Messages
window for a standard
Windows application

Add •••
Before you can log messages, you must first indicate which
Remove window you're logging messages for. You do this in the top left
Delete all
pane, the Window Selection pane. This pane's local menu
(activated by pressing Alt-F1(J) lets you add a window selection,
delete a window selection, or delete all window selections.

158 Turbo Debugger for Windows User's Guide


Adding a window selection for a standard Windows
application
To add a window selection, you can either choose Add from the
Window Selection pane local menu or begin typing in the pane.
Either method brings up the Add Window dialog box.
Figure 11.2
The Add Window dialog box
for a standard Windows
application Cancel
Hel

Adding the first window proc You can enter either the name of the object that processes
to this box also sets the
message class to "Log all
messages for the window (select the Window Proc button) or a
messages." handle value (select the Handle button). Enter as many routine
names or handle values as necessary to track messages for your
windows.
It's easier to indicate the window by the name of the routine that
processes its messages (for example, WndProc) because you can
enter a routine name any time after loading your program.
If you prefer to use a handle variable name, you must first step
through the program past the line where the handle variable is
assigned a handle. (Use the Fl or FB key to single-step through the
program.) If you try to enter the variable name before stepping
past its assignment statement, TOW will not let you.

Selecting a window for If you're debugging an ObjectWindows application and you select
an ObjectWindows View I Windows Messages, by default you see the standard
application Windows Messages dialog box in Figure 11.1. This dialog box
works the same for ObjectWindows programs as for standard
Windows programs, except that you can't use a Windows proce-
dure name. Instead, you must use the handle to the window
object for the window whose messages you want to log or break
on.

Obtaining a window handle


Before you can use the handle of a window object, you must run
your program past the point where the handle is initialized. You
can use a number of techniques.

Chapter 11, Using Windows debugging features 159


• It's simplest just to run your application and exit back to TOW
with Ctrl-Alt-SysRq.
• Another possibility is to set a breakpoint in a message-handling
routine in your program (such as a routine that handles
WM_MOUSEMOVE messages), run the program, and then
perform the action in the window that triggers the breakpoint
(for example, moving the mouse).
•If you're having major problems with the window itself (such
as an unrecoverable application error-UAE-that comes up
when the window is first displayed), you'll have to go to
greater lengths to obtain the window handle.
Because the handle is initialized by the ObjectWindows
function CreateWindow and this function executes after you
initialize the window, you have to redeclare this function in the
window class and then set a breakpoint on it to get the handle.
For example, the following code redeclares this function for the
TDOOEMO window class ScribbleWindow:
void ScribbleWindow::SetupWindow()
{
TWindow::SetupWindow();

Next, position the cursor on the line after the initialization


statement and press F4 to run the program to the point where
the handle of the window, dialog box, or control is initialized.
In this example, you'd position the cursor on the closing brace
of the function SetupWindow.
Once the handle is initialized and you've returned to TOW, you
can obtain its value by choosing Data I Inspect and entering the
name of the associated window object (in TOOOEMO,
WinMain#MyApp.Main Window). Look for the data member
HWindow and copy it into the Clipboard (press Shift-F3). You can
then paste the contents of HWindow as a handle into the Add
dialog box of the Window Messages window's top left pane (press
Shift-F4 in the dialog box's text entry box).

Specifying a window with ObjectWindows support enabled


See the file TDWINST. TOW for If you run the TOW configuration program TOWINST, you can
information on setting
turn on support in TOW for ObjectWindows window messages.
options in TDWINST.
With this option on, you can use the names of windows objects as
they're declared in your application. Choosing View IWindows
Messages with the OWL option on displays the following screen:

160 Turbo Debugger for Windows User's Guide


Figure 11.3
The Windows Messages
window with ObjectWindows
support enabled

I Add •••
Remove
Before you can log messages, you must first indicate which
window. dialog box, or dialog control you're logging messages
I Delete all for. You do this in the top left pane, the Window Selection pane.
This pane's local menu (activated by pressing Alt-F10) lets you add
a window object, delete a window object, or delete all window
objects.

Adding a window with ObjectWindows support enabled


Before adding a window object, you must run your program past
the point where the window object is initialized. Typically, the
object is initialized in a statement like the one in the following
function definition from TDODEMO:
void CScribbleApplication::InitMainWindow()
{
MainWindow =new ScribbleWindow{NULL, Name);

Position the cursor on the line after the initialization statement


and press F4 to run the program to the point where the window,
dialog box, or control is initialized. In this example, you'd
position the cursor on the closing brace of the function.
Once the window object is initialized, you can add it to the
Window Selection pane. To add the object, either choose Add
from the Window Selection pane local menu or begin typing the
object's name in the pane. Either method brings up the Add
Window dialog box.
¢ If you're not in the routine where the object is declared, you have
to override scope to access it. For example, in TDODEMO,
Main Window is a member of My App (because MyApp is of type
CScribbleApplicatlon, which is derived from TAppllcatlon, which
has a data member called Main Window). However, since MyApp is
declared in function WinMain, unless you're in that function, you
can't access MyApp, either. Therefore, the scope override that's
guaranteed to work in this module is WinMain#MyApp.MainWindow.

Chapter 11, Using Windows debugging features 161


Figure 11.4
The Add Window dialog box
with Objectwindows support
enabled

Adding the first object to this You can enter either the name of the object that processes
pane also sets the message
class to "Log all messages.·
messages for the window, dialog box, or control (select the
Window Object button) or a handle value (select the LJ:andle
button). Enter as many object names or handle values as
necessary to track messages for your windows.

Deleting a window Deleting a window selection from the Window Selection pane
selection works the same for both types of applications. To delete, move the
cursor to the item, then either bring up the local menu and choose
Remove or press the Delete, Ctrl-Y, or Ctrl-R key.
To delete all selections, choose Delete All from the local menu.

Specifying a message The top right pane is the Message Class pane. Its local menu,
class and action identical to that of the Window Selection pane, allows you to add
a message class, remove a message class, or delete all classes you
Add ••• have added.
Remove
Delete all You must specify a window procedure or handle in the Window
Selection pane before you can add a message class in this pane.
If you don't indicate a specific message or class of messages to
watch, TOW watches all messages sent to the window procedure
or handle.

Adding a message class


To add a message class, choose Add from the Message Class pane
local menu. TOW displays the following dialog box:

162 Turbo Debugger for Windows User's Guide


Figure 11.5
The Set Message Filter dialog
box

The Set Message Filter dialog box prompts you both for a message
class to track and an action to be performed when a message in
that class is received.
TOW by default logs all messages starting with WM_. Because so
many messages come in, you'll probably want to narrow the focus
by selecting one of the classes in the Message Class list. You can
add only one class at a time, so if you need to track messages from
multiple classes, you have to use the Add option for each class
you want to set.
The following table describes the message classes:
Table 11.1
Windows message classes Message class Description
~~~~~~~~~~~~~~~~~~~~~~~~~~-

All Messages All window messages


Mouse Messages generated by a mouse event (for example,
WM_LBUTTONDOWN and WM_MOUSEMOVE)
Window Messages from the window manager (for example,
WM_PAINT and WM_CREATE)
Input Messages generated by a keyboard event or by the
user's accessing a System menu, scroll bar, or size
box (for example, WM_KEYOOWN)
System Messages generated by a system-wide change, (for
example, WM_FONTCHANGE and
WM_SPOOLERSTATUS)
Initialization Messages generated when an application creates a
dialog box or a window (for example,
WM_INITDIALOG and WM_INITMENU)
Clipboard Messages generated when one application tries to
access the Clipboard of a window in another appli-
cation (for example, WM_DRAWCLIPBOARD and
WM_SIZECLIPBOARD)

Chapter 77, Using Windows debugging features 163


Table 11.1: Windows message classes (continued)
DDE Dynamic Data Exchange messages, generated by
applications' communicating with one another's
windows (for example, WM_DDE_INITIATE and
WM_DDE_ACK)
Non-client Messages generated by Windows to maintain the
non-client area of an application window (for
example, WM_NCHITTEST and WM_NCCREATE)
Other Any messages that don't fall into any of the other
categories, such as owner draw control messages
and multiple document interface messages
Single Message Any single message you want to log or break on

To track a single message, choose Single Message and enter the


message name or the message number as a decimal number. If
you enter a message name, be sure to use all capital letters.
The default action is to put the messages in the log. The other
action you can perform, having the program break when it
receives a message, is equivalent to setting a breakpoint for a
message.
For example, if you want to track the WM_PAINT message and
have the program stop every time this message is sent to a
window you chose in the Window Selection pane, do the
following:

l. Select the top right pane, the Message Class pane.


2. Bring up the local menu, then choose Add.
3. From the dialog box, select Break from the Action radio
buttons and Single Message from the Message Class radio
buttons.
4. Enter WM_PAINT in the Message Name input box, then press
Enter.

Figure 11.1 on page 158 shows how the Windows Messages


window looks after you have made these selections and a
message has come in.

Deleting a message class


To delete a message class, move the cursor to the item, then either
bring up the local menu and choose Remove or press one of the
following keys: Delete, Ctrl-R, or Ctr/-Y.

164 Turbo Debugger for Windows User's Guide


To delete all classes, choose Delete All from the local menu or
press Ctrl-D.
The default class, Log all messages, appears after you have
deleted all classes. You cannot delete this class using Remove or
Delete All command.

Window message tips


If you're displaying messages for more than one window, do not
log all messages. Instead, log specific messages or a specific
message class for each window. If you log all messages, the large
number of messages being transferred between Windows and
TDW might cause your system to hang.
When setting a break on Mouse class messages, be aware that a
mouse down message must be followed by a mouse up message
before the keyboard becomes active again. This restriction means
that when you return to the application, you might have to press
the mouse button several times to get Windows to receive a mouse
up message. You'll know that Windows has received the message
when you see it in the lower pane of the Windows Messages
window.
If you enter a handle name but indicate that it's a procedure, TDW
accepts your input and doesn't complain. However, when you
run your program, TDW does not log any messages. If TDW isn't
logging messages after you've set a handle, reenter the handle and
be sure to select the Handle button.

Viewing messages Window messages show up in the lower pane of the Windows
Messages window. This pane can hold up to 200 messages.
Send to log window No
Erase log If you want to save the messages to a file, you have to open a log
file for the Log window (use View I Log File, then choose Open
Log File from the local menu). Then switch back to the Messages
pane and change the Send To Log Window entry on the local
menu to Yes.
If you want to clear the pane of all messages, choose Erase Log
from the local menu. Any messages written to the Log window
will not be affected by this command.

Chapter 11, Using Windows debugging features 165


Obtaining
memory and To list the contents of the global or local heap or the modules for
module lists your Windows program, first bring up the Log window with
View I Log, then access the local menu. The last command on the
Log window local menu is Display Windows Info. Choosing that
command displays the Windows Information dialog box, from
which you can pick the type of list you want to display and where
to start the list.
Figure 11.6
The Windows Information
dialog box

If you select the Global Heap option, you can choose to display
the list from top to bottom, from bottom to top, or from a location
indicated by a starting handle.
A starting handle is the name of a global memory handle set in
your application by a call to a Windows memory allocation
routine like GlobalAlloc. Picking a starting handle causes TDW to
display the object at that handle as well as the next four objects
that follow it in the heap.
Listing the contents of The global heap is the global memory area Windows makes
the global heap available to all applications. If you allocate resources like icons,
bit maps, dialog boxes, and fonts, or if you allocate memory using
the GlobalAlloc function, your application is using the global heap.
To see a list of the data objects in the global heap, select the Global
Heap radio button in the Windows Information dialog box, then
choose OK. The data objects will be listed in the Log window.
¢ Because this list is likely to exceed the number of lines the Log
window can write (the default is 50 lines), you should either write
the contents to a log file (use the Log window local menu) or
increase the number of lines the Log window can use (use
TDWINST). The maximum number of lines you can set is 200.

166 Turbo Debugger for Windows User's Guide


The following table shows two lines of sample global heap output
followed by an explanation of each field in the sample output:
Table 11.2
Format of a global heap list Sample global heap output
~~~~~~~~~~~~~~~~~~~~~~~~~~-

0EC5 00000040b PDB (OFlD)


053E (053D) 00002DC0b GDI DATA MOVEABLE LOCKED=OOOOl PGLOCKED=OOOl

Field Description
OECS Either a handle to the memory object, expressed
053E as a 4-digit hex value, or the word FREE,
indicating a free memory block.
(053D) A memory selector pointing to an entry in the
global descriptor table. The selector isn't displayed
if it's the same value as the memory handle.
00000040b A hexadecimal number representing the length of
000020COb the segment in bytes.
PDB The allocator of the segment, usually an
GDI application or library module. A PDB is a process
descriptor block, also known as a program
segment prefix (PSP).
(OFlD) A handle indicating the owner of a PDB.
DATA The type of memory object. The types are
DATA Data segment of an application or DLL
CODE Code segment of an application or DLL
PRIV Either a system object or global data for
an application or DLL
MOVEABLE A memory allocation attribute. An object can be
FIXED, MOVEABLE, or MOVEABLE
DISCARDABLE.
LOCKED=OOOOl For a moveable or moveable-discardable object,
the number of locks on the object that have been
set using either the GlobalLock or LockData function.
PGLOCKED=OOOl For 386 Enhanced mode, the number of page locks
on the object that have been set using the
GlobalPageLock function. With a page lock set on a
memory object, Windows can't swap to disk any of
the object's 4-kilobyte pages.

Chapter 77, Using Windows debugging features 167


Listing the contents of The local heap is a private memory area for the application. It is
the local heap not accessible to other Windows applications, including other
instances of the same application.
A program doesn't necessarily have a local heap. Windows
creates a local heap if the application uses the LocalAlloc function.
To see a list of the data objects in the local heap, select the Local
Heap radio button in the Windows Information dialog box, then
choose OK. The data objects will be listed in the Log window.
The list can easily exceed the default length of the log window.
See the caution in the previous global heap section (page 166)
about using a log file or increasing the number of lines that can be
written in the Log window.
The following table shows a typical line of local heap output
followed by an explanation of its format:
Table 11.3
Format of a local heap list Local heap output

OSCO: 0024 BUSY (lOAF)


Field Description
OSCO: The object's offset in the local data segment
0024 The length of the object in bytes
BUSY The disposition of the memory object, as follows:
FREE An unallocated block of memory
BUSY An allocated object
(lOAF) A local memory handle for the object

Obtaining a list of To see a list of the task and DLL modules that have been loaded
modules by Windows, select the Module List radio button in the Windows
Information dialog box, then choose OK. The modules will be
listed in the Log window.
The list can easily exceed the default length of the log window.
See the caution in the global heap section (page 166) about using a
log file or increasing the number of lines that can be written in the
Log window.

168 Turbo Debugger for Windows User's Guide


The following table shows three sample lines of a module list
followed by an explanation of the last line in the list:
Table 11.4
Format of a Windows module Sample module list output
list
0985 TASK TOW C:\TD\TDW.EXE
OE2D DLL WINDEBUG C:\WIN3\WINDEBUG.DLL
OEFD TASK GENERIC C:\TD\GENERIC.EXE
Field Description
OEFD A handle for the memory segment, expressed
as a 4-digit hex value.
TASK The module type. A module can be either a
task or a DLL.
GENERIC The module name.
C:\ TD\GENERIC.EXE The path to the module's executable file.

Debugging
dynamic link A DLL is a library of routines and resources that is linked to your
libraries (DLLs) Windows application at runtime instead of at compile time. This
runtime linking allows multiple applications to share a single
copy of routines, data, or device drivers, thus saving on memory
use. When an application that uses a DLL starts up, if the DLL is
not already loaded into memory, Windows loads it in so the
application can access the DLL's entry points.
TDW can load a DLL that When you load an application into TDW that has DLLs linked
doesn't have a symbol table,
into it, TDW determines which of these DLLs, if any, have symbol
but only into a CPU window.
tables (were compiled with the debugging option turned on) and
tracks these DLLs for you. If, during execution of your appli-
cation, TDW encounters a call to an entry point for one of these
DLLs, TDW loads the symbol table and source for that DLL and
positions the module line marker at the beginning of the DLL
routine called by your application. The DLL is then available in
the Module window just as your application source code was.
When the DLL routine exits, if possible, TDW reloads your
application's source code and positions the line marker on the
next statement after the call to the DLL entry point.
If you are tracing through the program using Fl or FB, it might not
be possible for TDW to return you to the calling routine in your
program because the DLL might return through a Windows
function call. In this case, your program just runs as though you
had pressed F9. This behavior is common in DLL startup code. To

Chapter 77, Using Windows debugging features 169


force a return to your application, before tracing in your
application to the DLL call, set a breakpoint in your application
on the line after the call to the DLL. When debugging DLL startup
code, set the breakpoint on the first line of your application.
Because so much of DLL debugging is automatic with TDW, you
never have to specify which DLLs to load. However, you might
want to perform other tasks, such as:
•Adding a DLL to the list of DLLs
•Setting breakpoints, watches, and so on, in a DLL
•Specifying which DLLs TDW is not supposed to load symbols
for
•Debugging DLL startup code
To perform any of these tasks, you have to access the Load
Modules or DLLs dialog box by using the View I Modules
command. (Pressing F3 will also bring up this dialog box.)
Figure 11.7
The Load Modules or DLLs
dialog box

Using the Load This dialog box enables you to do two things:
Modules or DLLs dialog
•Change to another source module of your application
box
•Perform operations on DLLs and .EXE files (such as loading in a
symbol file and source file)

Changing source modules


If you're debugging an application consisting of multiple source
modules linked into one .EXE file and you need access to a
module of the application other than the one currently in the
Module window, you can bring up the Load Modules or DLLs
dialog box and pick one of the modules in the list on the left, the
Source Modules list.

170 Turbo Debugger for Windows User's Guide


M, To pick a module, highlight it, and then either press Enter, click
twice with the mouse, or choose the Load button. TOW displays
the Module window with the new source module in it.

Working with DLLs and programs


When you're debugging an application that has one or more
OLLs associated with it (as does any Windows application) and
you bring up the Load Modules or OLLs dialog box, you see in
the OLLs & Programs list (the list on the right) a list of OLLs and
.EXE files (as well as all the .ORV and .FON files currently loaded
into Windows). This list includes all OLL and .EXE files Windows
currently has loaded, as well as all OLLs that get started when
your application starts up. It does not include any OLLs your
application starts by using a Loadlibrary call unless one of these
OLLs is already loaded by your program or by Windows.
The items at the top of this list, marked on the right with an oval,
are your application's .EXE file and the OLLs your application
calls. If you make no changes, TOW automatically attempts to
load in the symbol table and source for each marked OLL
whenever your application makes a call to that OLL. In addition,
TOW automatically attempts to load the symbol table and source
of any OLL your application starts with a Loadlibrary call, even
though the OLL might not appear on the list at first. (It will
appear there after TOW loads it.)
The buttons to the right of this list perform operations on the OLL
or application you have highlighted. The text entry box under-
neath the list lets you add a OLL to the list. You can use these
features as follows:
Table 11.5
DLLs & Programs list dialog Button Description
box controls Symbol load Load in the symbol table and source files
for the DLL or application, regardless of
the Load Symbols setting. This command
overrides the Load Symbols setting and
changes the contents of the Module
Window so you can set breakpoints,
window messages, and so on for the DLL
or application.

Chapter 77, Using Windows debugging features 171


Table 11.5: DLLs & Programs list dialog box controls (continued)
Load symbols (No/Yes) Choose whether to load the DLL symbol
table and source when the application
makes a call to the DLL. You might use this
option to prevent TDW from loading the
symbol table and source of a DLL that you
don't need to debug. The default setting is
Yes.
Choosing Yes puts an oval next to the DLL
name.
When you reload a program, Load
Symbols is set to Yes for all DLLs and
modules, even for DLLs or modules that
were previously set to No.
Debug startup (No/Yes) Choose whether to debug startup code for
the DLL. The default setting is No.
Choosing Yes puts double exclamation
marks (!!) next to the module or DLL.
These buttons are used for DLLs only. To
debug application startup code, start TDW
with the -1 command-line option.
DLLName Enter the name of a DLL that isn't on the
DLLs & Programs list so you can add it to
the list. You can use any file extension you
want. Adding a DLL to the list enables you
to use one of the previous three commands
on it. You can use a full path name if
necessary.
AddDLL Add the DLL in the text entry box to the
DLLs & Programs list. Any DLL you add
manually has both Load Symbols and
Debug Startup set to Yes.

Adding a DLL to the Before you can set debug options, debug OLL startup code, or
DLLs & Programs list prevent TOW from loading a OLL's symbol table and source, the
OLL must first be in the OLLs & Programs list. A OLL accessed by
your application might not be in this list because, just after your
application loads, TOW only knows about OLLs that are linked
into the startup code of your application. Your application can
also start a OLL explicitly by using the Windows Loadlibrary
function; TOW won't know about it until your application calls
Load library.

There are two different types of startup code mentioned in this


section: your application's startup code and OLL startup code.

172 Turbo Debugger for Windows User's Guide


Some OLLs are started in your application's startup code. When
your application starts a OLL, the OLL's startup code is then
executed. There are also two types of OLL startup code, explained
later on page 173.
If you want to add a OLL to the OLLs & Programs list, bring up
the Load Modules or OLLs dialog box (press F3 or choose View I
Modules), move to the OLL Name text entry box, enter the name
of the DLL (enter the fall path if necessary), then press the Add
OLL button to add it to the list.

Setting debug options If you want to set breakpoints or watches or some other debug
in a DLL option for a OLL, bring up the Load Modules or OLLs dialog box
(press F3 or choose View I Modules), highlight the OLL on the
OLLs & Programs list, then choose Symbol Load to bring up the
OLL in a Module window. Once you're in the Module window,
you can perform your operations on the OLL.

Controlling TDW's By default, TOW loads in the symbol table and source of every
loading of DLL symbol OLLthat your application accesses, but only if the OLL has a
tables TOW-compatible symbol table. A OLL has a symbol table
compatible with TOW if it was compiled with debugging infor-
mation turned on and the compiler was a Borland language
compiler.
Because it takes time to load in a OLL's symbol table and then
load in the original application's symbol table once the OLL
routine has finished, you might want to disable TOW's default
operation for OLLs you don't want to debug. To prevent TOW
from loading a OLL's symbol table, bring up the Load Modules or
OLLs dialog box (press F3 or choose View I Modules), find the OLL
on the OLLs & Programs list, highlight it, and then push the Load
Symbols No button.

Debugging DLL startup By default, TOW does not debug OLL startup code and only loads
code a OLL's symbol table when your application makes a call to a OLL
entry point. TOW then brings up the Module or CPU window
with the current line marker at the beginning of the OLL routine
called by the application.
TOW debugs OLL startup code if you tell it to. You can use TOW
to debug either of two types of OLL startup code:
What kind of startup code •The initialization code immediately following LibMain (the
are you debugging? default)

Chapter 77, Using Windows debugging features 173


•The assembly-language code linked into the DLL that does
initial startup and contains emulated math packages for the size
model the DLL is running in (selected by starting TDW with the
-1 command-line option)
After you specify startup debugging for one or more of the DLLs
in your application, TDW loads in the symbol table for each DLL
either when your application startup code starts the DLL or when
your application makes a Loadlibrary call.

Is your application already If you try to load your application and then set startup
loaded?
debugging, TDW might not behave as you expect, since some or
all of the DLLs might already have been loaded. Therefore, you
should set startup debugging either
•By setting the DLLs before you load your application
• By loading your application, indicating the DLLs for startup
debugging, and then restarting your application (Ctrl-F2 or Run I
Program Reset)
Doing startup code With all these preliminaries in mind, use the following steps to
debugging
specify startup debugging for one or more DLLs and to debug
those DLLs' startup code:

1. Bring up the Load Modules or DLLs dialog box (press F3 or


choose View I Modules).
2. If no program is loaded, skip to step 5. Otherwise, find a DLL
on the DLLs & Programs list and highlight it.
3. Select the Debug Startup Yes button.
4. Repeat steps 2 and 3 until you've set startup debugging for all
DLLs you're interested in.
5. If a DLL you want isn't on the list or there are no DLLs on the
list (because you haven't loaded your application yet), use the
DLL Name text entry box to enter each DLL name and add it
to the list using the Add DLL button.
6. When you've set all the DLLs for which you want to debug
startup code, choose either File I Load to load in your
application (if you haven't loaded it yet) or Run I Program
Reset (Ctrl-F2) to reload your application (if you loaded it
before setting startup debugging).
7. Before you run the application, you should set breakpoints to
guarantee that the DLLs will return to your application after

174 Turbo Debugger for Windows User's Guide


the startup code executes. With your application's source code
in the Module window,

a. Set a breakpoint on the first line of your application.


b. If you're debugging startup code for any DLLs loaded with
Loadlibrary calls, set a breakpoint on the first line of code
after each of these calls.

8. As your apphcation starts each DLL, TOW puts you either in


the Module window at the DLL's LibMain (the default) or in
the CPU window at the start of the assembly code listing for
the startup library (because you ran TDW using the -1 option).
9. When you've finished debugging startup code for a DLL, press
F9 to run through the end of the startup code and return to the
application. If you've specified any more DLLs for startup
code debugging, TDW displays startup code for those DLLs
when your application starts them.

Be sure to run to the end of a DLL's startup code before reloading the
current application or loading a new one. If you don't, the partially
executed DLL startup code might cause Windows to hang, forcing
you to reboot.

Converting
memory handles Windows uses memory handles instead of addresses for memory
to addresses objects because it performs its own memory management and can
change the physical location in memory of an object. If you need
the actual address referred to by a memory handle, you can use
the TDW built-in typecast symbols lh2fp (for a local handle) and
gh2fp (for a global handle) to dereference the handle.
You use these typecasting symbols in TDW just as you use the
regular C++ typecasting symbols for pointers. For example, you
could cast the local memory handle hLocalMemory using two
methods:
•You could use the Data I Inspect window to evaluate the
expression (lh2fp) hLocalMemory.

•You could use the Type Cast command in the Inspector local
window and enter lh2fp as the type.
In either case, the expression evaluates to the first character of the
memory block pointed to by hLocalMemory.

Chapter 11, Using Windows debugging features 175


You could also use either of these techniques to do a more compli-
cated cast-for example, a two-stage cast from a handle into a
character pointer into a pointer to the data in memory, as follows:
(Mystruct far *) (lh2fp)hLocalMemory

176 Turbo Debugger for Windows User's Guide


c H A p T E R

12

Assembler-level debugging
For more information on This chapter is for programmers who need to take a lower-level
assembler-level debugging,
look at their code. It gives a brief introduction to the CPU window
see the file DOC\
ASMDEBUG. TOW in the and the six panes of that window. You can also get online Help
language compiler directory information about any pane of this window and its local menu by
on your hard disk. positioning the cursor in the pane and pressing F1.

When source debugging isn't enough


When you're debugging a program, most of the time you refer to
data and code at the source level; you refer to symbol names
exactly as you typed them in your source code, and you proceed
through your program by executing pieces of source code.
Sometimes, however, you need information you can't get from the
source code Module window, such as
• looking at the contents of an area in memory referenced by a
protected-mode selector
• looking at the exact instructions that the compiler generated for
a line of source code, as well as the contents of the stack and
CPU registers
• tracing through Windows code to find where your program
stopped
To perform any of these functions, you have to use the CPU
window. In addition, it helps to be familiar with Windows' use of

Chapter 72, Assembler-level debugging 177


memory and to have knowledge of both the 80x86 family of pro-
cessors and the machine instructions the compiler generates for
your source code. Because many excellent books are available
about the internal workings of the CPU, we won't go into that in
detail here. You can quickly learn how the compiler turns your
source code into machine instructions by looking at the
instructions generated for each line of source code.

The CPU window


The CPU window shows you the entire state of the CPU. You can
•examine and change the bits and bytes that make up your pro-
gram's code and data
• access the contents of any area of memory referenced by a
selector
•use the built-in assembler in the Code pane to patch your pro-
gram temporarily by entering instructions exactly as you would
type assembler source statements
•access the underlying bytes of any data structure, display them

I
in a number of formats, and change them
Figure 12.l F[•]=REMOTE CPU 8038 3=[t] [~]=
WINMAIN: int PASCAL Wi nMai n (HANDLE hlnstance,& ax FF15 c=O
The CPU window cs: 0158•55 push bp • bx 08DE z=l
cs:0159 88EC mov bp,sp ex 0015 s=O
cs:0158 83EC06 sub sp,0006 dx 08DE o=O
cs:015E 56 push si si OSCO p=l
cs:015F 57 push di di 08DE a=O
#TDDEM0#44: InitWinCrt(); bp 1E2A i=l
cs:0160 E88IlF call InitWinCrt sp lElE d=O
#TDDEM0#45: nlines = O; - ds 1285
cs:0163 33F6 xor si ,si ,. es 1285
;;05 oat~ Loa~ed 111!~ ~ms 11eM3rife,
1 up ~~ ~m
1280 Invalid ip 0158
ds:OOOO 00 00 00 00 00 00 50 lE P&
ds:0008 00 00 C2 OA 2C lE 2C lE :rl, .. ,..
ds:OOlO 00 00 08 00 00 00 95 12 C-- Ot SS: 1E20 0001
ds:0018 B6 12 00 00 80 00 01 00 11t o SS: 1ElE•OOA2 I

Open a CPU window by choosing View I CPU from the menu bar.
Depending on what you're viewing in the current window, the
new CPU window comes up positioned at the appropriate code,
data, or stack location, thus providing a convenient method for
taking a low-level look at the code, data, or stack location your
cursor is currently on.

178 Turbo Debugger for Windows User's Guide


The following table shows where your cursor is positioned when
you choose the CPU command:

Current window CPU pane Position


Stack window Stack Current SS:SP
Module window Code Current CS:IP
Variable window Data/Code Address of item
Watches window Data/Code Address of item
Inspector window Data/Code Address of item
Breakpoint Code Breakpoint address
(if not global)

TDW also automatically puts you in the CPU window if TDW


regains control from your application and the current code being
executed is Windows code or DLL code that has no debugging
information.
The CPU window has six panes. To go from one pane to the next,
M. press Tab or Shift-Tab, or click the pane with your mouse. The line
at the top of the CPU window shows what processor type you
have (8086, 80286, 80386, or 80486).
•The top left pane (Code pane) shows the disassembled program
code intermixed with the source lines.
• The second top pane (Register pane) shows the contents of the
CPU registers.
•The top right pane (Flags pane) shows the state of the eight
CPU flags.
• The middle left pane (Selector pane-below the Code pane)
shows all Windows selectors and indicates the general contents
of each.
• The bottom left pane (Data pane-below the Selector pane)
shows a raw hex dump of any area of memory you choose.
• The bottom right pane (Stack pane) shows the contents of the
stack.
As with all windows and panes, pressing Alt-F10 pops up the
pane's local menu. If control-key shortcuts are enabled, pressing
the Ctr/ key with the highlighted letter of the desired local menu
command executes the command.
In the Code, Data, and Stack panes, you can press Ctr/ f- and
Ctr/~ to shift the starting display address of the pane by 1 byte up
or down. Pressing these keys is easier than using the Goto
command if you just want to adjust the display slightly.

Chapter 72, Assembler-level debugging 179


The Code pane
An arrow (11>) shows the This pane shows the disassembled instructions at an address that
current program location
(CS:IP).
you choose.
There are two ways of choosing an address:
•Use the local menu Goto, Origin, Follow, Caller, or Previous
command.
• Position on a code selector in the Selector pane, then choose
Examine to display the contents of the selector in the Code
pane.
The left part of each disassembled line shows the address of the
instruction. The address is displayed either as a hex segment and
offset, or with the segment value replaced with the CS register
name if the segment value is the same as the current CS register. If
the window is wide enough (zoomed or resized), the bytes that
make up the instruction are displayed. The disassembled instruc-
tion appears to the right.
If the highlighted instruction in the Code pane references a
memory location, the memory address and its current contents
are displayed on the top line of the CPU window. This feature lets
you see both where an instruction operand points in memory and
the value that is about to be read or written over.

The disassembler
The Code pane automatically disassembles and displays your
program instructions. If an address corresponds to either a global
symbol, static symbol, or a line number, the line before the dis-
assembled instruction displays the symbol if the Mixed display
mode is set to Yes. Also, if there is a line of source code that corre-
sponds to the symbol address, it is displayed after the symbol.
Global symbols appear simply as the symbol name. Static symbols
appear as the module name, followed by a cross hatch(#),
followed by the static symbol name. Line numbers appear as the
module name, followed by a cross hatch(#), followed by the
decimal line number.
When an immediate operand is displayed, you can infer its size
from the number of digits: A byte immediate has 2 digits, and a
word immediate has 4 digits.

180 Turbo Debugger for Windows User's Guide


The Register and Flags panes
The Register pane, which is the top pane to the right of the Code
pane, shows the contents of the CPU registers.
The top right pane is the Flags pane, which shows the state of the
eight CPU flags. The following table lists the different flags and
how they are shown in the Flags pane:

Letter in pane Flag name


c Carry
z Zero
s Sign
0 Overflow
p Parity
a Auxiliary carry
i Interrupt enable
d Direction

You can use the local menu of the Register pane to increment or
decrement a register by l, to set the register to 0, to change the
register, or to toggle between displaying the register as 16-bit or
32-bit values (requires an 80386 processor or greater).
The local menu of the Flags pane allow you to toggle the flag
between 0 and 1.

The Selector pane


This pane shows a list of protected-mode selectors and indicates
some information about each one.
A selector can be either valid or invalid. If valid, the selector
points to a location in the protected-mode descriptor table
corresponding to a memory address. If invalid, the selector is
unused.
For a valid selector, the pane shows the following:
• if the contents are data or code
• if the memory area the selector references is loaded (present in
memory) or unloaded (swapped out to disk)
• the length of the referenced memory segment in bytes

Chapter 72, Assembler-level debugging 181


If the selector references a data segment, there's additional
information on the access rights (Read/Write or Read only) and
the direction the segment expands in memory (Up or Down).

The Selector
pane local menu At the Selector pane, press Alt-F10to pop up the local menu or, if
control-key shortcuts are enabled, use the Ctr/ key with the
highlighted letter of the desired command to access the
command.
You can use the local menu of the Selector pane to go to a new
selector (the Selector command) or see the contents of the selector
currently highlighted in the Selector pane (the Examine
command). The contents display in either the Code pane or the
Data pane, depending on their nature.
Selector
Examine •••

Selector Prompts you to type a selector to display in the pane. You can use
full expression syntax to enter the selector. If you enter a numeric
value, TDW assumes it is decimal unless you use the syntax of the
current language to indicate that the value is hexadecimal.
For example, if the current language were C, you could type the
hexadecimal selector value 7F as Ox7F. For Pascal, you'd type it as
$7F. You could also type the decimal value 127 in order to go to
selector 7F.
Another method of entering the selector value is to display the
CPU window and check the segment register values. If a register
holds the selector you're interested in, you can enter the name of
the register preceded by an underscore (_). For example, you
could type the data segment register as _DS.

Examine Displays the contents of the memory area referenced by the


current selector and switches focus to the pane where the contents
are displayed. If the selector points to a code segment, the
contents are displayed in the Code pane. If the contents are data,
they're displayed in the Data pane.

182 Turbo Debugger for Windows User's Guide


The Data pane
This pane shows a raw display of an area of memory you've
selected. The leftmost part of each line shows the address of the
data displayed in that line. The address is displayed either as a
hex segment and offset, or with the segment value replaced with
one of the register names if the segment value is the same as that
register. The Data pane matches registers in the follc,ving order:
DS, ES, SS, CS.
Next, the raw display of one or more data items is displayed. The
format of this area depends on the display format selected with
the Display As local menu command. If you choose one of the
floating-point display formats (Comp, Float, Real, Double,
Extended), a single floating-point number is displayed on each
line. Byte format displays 8 bytes per line, Word format displays 4
words per line, and Long format displays 2 long words per line.
When the data is displayed as bytes, the rightmost part of each
line shows the display characters that correspond to the data
bytes displayed. TDW displays all byte values as their display
equivalents, so don't be surprised if you see funny symbols
displayed to the right of the hex dump area-these are just the
display equivalents of the hex byte values.
There are two ways of choosing an address:
•Use the local menu Goto, Follow, or Previous command.
• Position on a data selector in the Selector pane, then choose
Examine to display the contents of the selector in the Data pane.
The Data pane local menu lets you go to a new address, search for
a character string, change bytes at the current cursor location,
follow near or far pointer chains, restore a previous address,
change how data appears in the window, and move, change, read,
and write blocks of memory.

The Stack pane


An arrow (1>) shows the The Stack pane, in the lower right corner of the CPU window,
current stack pointer (SS:IP).
shows the contents of the stack.
The commands in the local menu let you change positions in the
stack and change values of words on the stack.

Chapter 72, Assembler-level debugging 183


The Dump window
The Dump window, opened by choosing View I Dump, shows you
a raw data dump of any area of memory. The Dump window
shows you a raw data dump of any area of memory. It works
much like the Data pane in the CPU window (see page 183),
except that, when zoomed to full size, the Dump Window show
twice as much data on a single line.
Figure 12.2 [•]..Oump 3-[t] ['}"ii
ds:OOOO CD 20 00 AO 00 9A FO FE= 6 OH •
The Dump window [ ds:0008 18 02 82 01 22 31 7C 01 ...mo•110 •
ds :0010 22 31 88 02 52 28 E2 10 'l'tieR+r• II
ds:0018 01 01 01 00 03 FF FF FF - • "

Typically, you use this window if you're in an Inspector window


and you want to look at the raw bytes that make up the object you
are inspecting. Use View I Dump to get a Dump window that's
positioned to the data in the Inspector window.

The Registers window


The Registers window shows you the contents of the CPU
registers and flags. It works like a combination of the Registers
and Flags panes in the CPU window (see page 181).
Figure 12.3 [•]=RegS=3=[H
ax 0000 c•O
The Registers window bx 0000 z=O
ex 0000 s=O
dx 0000 o=O
si 0000 p=O
di 0000 a=O
bp 0000 i•l
sp 3FFE d=O
ds 61AF
es 61AF
SS 668F
cs 618F
ip 084E

You can perform the same functions from the local menu of the
Registers window as you can from the local menus of the
Registers pane and the Flags pane.

184 Turbo Debugger for Windows User's Guide


c H A p T E R

13

Command reference
Now that you've read about all the commands, here's a quick
summary. This chapter lists and describes
•all the single-keystroke commands available on the function
and other keys
• all the menu bar commands and the commands for the local
menu of each window type
•keystrokes used in the two types of panes (those in which you
enter text and those from which you select an item)
• keystrokes for moving and resizing windows

Hot keys
A hot key is a key that performs its action no matter where you
are in the Turbo Debugger environment. The following table lists
all the hot keys:

Chapter 73, Command reference 185


Table 13.1: The function key and hot key commands

Key Menu command Function


F1 Brings up context-sensitive help
F2 Breakpoints I Toggle Sets breakpoint at cursor position
F3 View I Module Module pick list
F4 Run I Go to Cursor Runs to cursor position
F5 Window I Zoom Zooms/unzooms current window
F6 Window I Next Window Goes to next window
Fl Run I Trace Into Executes single source line or instruction
FB Run I Step Over Executes single source line or instruction, skipping calls
F9 RunlRun Runs program
F10 Invokes the menu bar, takes you out of menus
Alt-F1 Help I Previous Topic Brings up last help screen
Alt-F2 Breakpoints I At Sets breakpoint at an address
Alt-F3 Window I Close Closes current window or all Inspector windows
Alt-F4 Run I Back Trace Reverses program execution
Alt-F5 Window I User Screen Shows your program's screen
Alt-F6 Window I Undo Close Reopens the last-closed window
Alt-Fl Run I Instruction Trace Executes a single instruction
Alt-FB Run I Until Return Runs until return from function
Alt-F9 Run I Execute To Runs to a specified address
Alt-F10 Invokes the window's local menu
Alt-1-9 Switch to numbered window 1 through 9
Alt-Space =
Goes to the (System) menu
Alt-B Goes to the Breakpoints menu
Alt-D Goes to the Data menu
Alt-E Goes to the Edit menu.
Alt-F Goes to the File menu
Alt-H Goes to the Help menu
Alt-0 Goes to the Options menu
Alt-R Goes to the Run menu
Alt-V Goes to the View menu
Alt-W Goes to the Window menu
Alt-X File I Quit Quits Turbo Debugger and returns you to DOS
Alt= Options I Macros I Create Defines a keystroke macro
Alt- Options I Macros I Stop Ends a macro recording
Recording
Ctrl-F2 Run I Program Reset Stops debug session and resets the program to start again
Ctr/-F4 Data I Evaluate Evaluates an expression
Ctr/-F5 Window ISize/Move Initiates window moving or resizing
Ctrl-Fl Data IAdd Watch Adds a variable to the Watches window
Ctr/-+ Shifts 1 byte up the starting address in a Code, Data, or Stack
pane in a CPU window
Ctr/+- Shifts 1 byte down the starting address in a Code, Data, or Stack
pane in a CPU window

186 Turbo Debugger for Windows User's Guide


Table 13.1: The function key and hot key commands (continued)
Key Menu command Function
Shift-F1 Help I Index Goes to the index for online help
Shift-F3 Edit I Copy Copies item at cursor or highlighted item to Clipboard
Shift-F4 Edit I Paste Pastes item from Clipboard to window or dialog box prompt
Shift-Tab Moves cursor to previous window pane or dialog box item
Shift-t
Shift~ Moves cursor between the panes in a window (the pane in the
Shift i direction of the arrow becomes the active pane)
Shift J..
Esc Closes an Inspector window, exits menus and dialog boxes
Ins Starts text block or list selection (highlight); use arrow keys to
highlight
Tab Window INext Pane Moves cursor to next window pane or dialog box item

Commands from the menu bar


You invoke the menu bar by pressing the Ft 0 key; you can then go
directly to one of the individual menus by
• moving the cursor to the menu title and pressing Enter
•pressing the highlighted letter of the menu title
You can also open a menu directly (without first moving to the
menu bar) by pressing Alt in combination with the first letter of the
menu name you want.

The =(System)
menu Repaint Desktop Redisplays entire screen
Restore Standard Restores standard window layout
About Displays information about Turbo
Debugger

The File menu


Open Loads a new program to debug
Change Dir Changes to new disk or directory
Get Info Displays program information
Symbol Load Loads symbol table independent of
.EXE file
Quit Returns to DOS

Chapter 73, Command reference 187


The Edit menu
Copy Copies an item into the Clipboard
Paste Pastes an item from the Clipboard
into a window or dialog box prompt
Copy to Log Copies the highlighted item or the
item at the cursor to the Log
window

The View menu


Breakpoints Displays breakpoints
Stack Displays procedure-calling stack
Log Displays log of events and data
Watches Displays variables being watched
Variables Displays global and local variables
Module Displays program source module
File Displays disk file as ASCII or hex
CPU Displays CPU instructions, data,
stack
Dump Displays raw data dump
Registers Displays CPU registers and flags
Numeric Processor Displays coprocessor or emulator
Execution History Displays assembler code saved for
backtracking
Hierarchy Displays class list and hierarchy tree
Windows messages Displays list of window messages
for one or more windows in your
application program
Clipboard Displays the Clipboard window so
you can see the items you've copied
into the Clipboard.
Another
Module Makes another Module window
Dump Makes another Dump window
File Makes another File window

188 Turbo Debugger for Windows User's Guide


The Run menu
Run Runs your program without
stopping
Go To Cursor Runs to current cursor location
Trace Into Executes one source line or
instruction
Step Over Traces, skipping calls
Execute To Runs to specified addrf>ss
Until Return Runs until procedure returns
Animate Continuously steps your program
Back Trace Reverses program execution for one
source line or instruction
Instruction Trace Executes a single instruction
Arguments Sets program command-line
arguments
Program Reset Reloads current program

The Breakpoints
menu Toggle Toggles breakpoint at cursor
At Sets breakpoint at specified address
Changed Memory Global Sets global breakpoint on memory
area
Expression True Global Sets global breakpoint on
expression
Hardware Breakpoint Sets a hardware breakpoint
Delete All Removes all breakpoints

The Data menu


Inspect Inspects a data object
Evaluate/Modify Evaluates an expression
Add Watch Adds variable to Watches window
Function Return Inspects current routine's return
value

The Options
menu Language Sets expression language
Macros
Create Defines a keystroke macro
Stop Recording Ends the recording session

Chapter 13, Command reference 189


Remove Removes a keystroke macro
Delete All Removes all keystroke macros
Display Options Lets you set screen display options
(screen swapping, size, tabs)
Path for Source Directory list for source files
Save Options Saves options, screen layout, and
macros to disk
Restore Options Restores options from disk

The Window
menu Zoom Zooms window to full screen size
and back
Next Activates successive windows open
onscreen
Next Pane Goes to the next pane in a window
Size/Move Moves window or changes its size
lconize /Restore Reduces window to a small symbol
or restores it
Close Closes window
Undo Close Reopens the last window closed
Dump Pane to Log Writes current pane to Log window
User Screen Displays your program output
Numbered window list A numbered list of up to 9 open
windows to activate
Window Pick Displays a menu of open menus if
more than 9 are open onscreen

The Help Menu


Index Goes to the index for online help
Previous Topic Brings up last help screen
Help on Help Accesses online help on the help
system

The local menu commands


Each type of window and You invoke the local menu for the current window by pressing
each pane within a window
Alt-F10. If control-key shortcuts are enabled, you can go directly to
has a different local menu.
one of the individual menu items by pressing the Ctr/ key in
combination with the highlighted letter of the item you desire.

190 Turbo Debugger for Windows User's Guide


(Use the installation program TDWINST to enable control-key
shortcuts, if they've been disabled.)
The menus in this section are . The following sections describe the local menu for each window
arranged in alphabetical and pane.
order to make lookups easier.
Most panes have shortcuts to commonly used commands on their
local menu. In the following sections, these special keys are
highlighted in the menu commands. In many panes, the Enter key
is a shortcut to examining or changing the currentiy highiighted
item. The Del key often invokes the local menu command that
deletes the highlighted item. Some panes let you start typing
letters or numbers without first invoking a local menu command.
In these cases, the dialog box for one of the local menu items pops
up to accept your input.

Breakpoints
window The Breakpoints window has two panes: the List pane on the left
and the Detail pane on the right. Only the List pane has a local
menu.

Set Options Sets breakpoint actions, conditions, pass


count, and enable/ disable
Add Adds a new breakpoint
Remove Removes highlighted breakpoint
Delete All Deletes all breakpoints
Inspect Looks at code where breakpoint is set
Group Work with groups of breakpoints
Del is the shortcut for Remove in this window.

The CPU window


menus The CPU window has six panes, each with a local menu: the Code
pane, the Data pane, the Selector pane, the Stack pane, the
Register pane, and the Flags pane.

Code pane
Goto Displays code at new address
Origin Displays code at CS:IP
Follow Displays code at JMP or CALL target
Caller Displays code at calling procedure
Previous Displays code at last address
Search Searches for instruction or bytes

Chapter 13, Command reference 191


View Source Switches to Module window
Mixed Mixes source code with disassembly:
No/Yes/Both
NewCS:IP Sets CS:IP to execute at new address
Assemble Assembles instruction at cursor
1/0 Brings up I/0 menu
In Byte Reads a byte from an I/0 location
Out Byte Writes a byte to an I/O location
Read Word Reads a word from an I/O location
Write Word Writes a word to an I/O location
Typing any character is a shortcut for the Assemble local menu
command in this pane.

Selector pane
Selector Lets you enter a new selector to go to
Examine Displays contents of memory area
referenced by selector in code pane or
data pane, depending on type of contents

Data pane
Goto Displays data at new address
Search Searches for string or data bytes
Next Searches again for next occurrence
Change Changes data bytes at cursor address
Follow
Near Code Sets Code pane to the near address under
the cursor
Far Code Sets Code pane to the far address under
the cursor
Offset to Data Sets Data pane to the near address under
the cursor
Segment:Offset Sets Data pane to the far address under
to Data the cursor
Base Segment:O Sets Data pane to start of segment that
to Data contains the address under the cursor
Previous Displays data at last address
Display As
Byte Displays hex bytes
Word Displays hex words
Long Displays hex 32-bit long words
Comp Displays 8-byte Pascal comp integers
Float Displays short (4-byte) floating-point
numbers (float)

192 Turbo Debugger for Windows User's Guide


Real Displays 6-byte floating-point numbers
(Pascal real)
Double Displays 8-byte floating-point numbers
(double)
Extended Displays 10-byte floating-point numbers
(long double)
Block
Clear Sets memory block to zero
Move Moves memory block
Set Sets memory block to value
Read Reads from file to memory
Write Writes from memory to file
Typing any character is a shortcut for the Change local menu
command in this pane.

Flags pane
Toggle Sets or clears highlighted flag
Pressing Enter or Spacebaris a shortcut for the Toggle local menu
command in this pane.

Register pane
Increment Adds one to highlighted register
Decrement Subtracts one from highlighted register
Zero Clears highlighted register
Change Sets highlighted register to new value
Registers 32-bit Toggles 32-bit register display: No/Yes
Typing any character is a shortcut for the Change local menu
command in this pane.

Stack pane
Goto Displays stack at new address
Origin Displays data at SS:SP
Follow Displays code pointed to by current item
Previous Restores display to last address
Change Lets you edit information
Typing any character is a shortcut for the Change local menu
command in this pane.

Chapter 73, Command reference 193


Dump window
The Dump window is identical to the Data pane of the CPU
window. Its local menu is identical to the Data pane local menu.

The Execution
History window The Execution History window has two panes, each with a local
menus menu: the Instructions pane and the Keystroke Reording pane.

Instructions pane The Instructions pane shows instructions already executed that
you can examine or undo.

Inspect Takes you to the highlighted command


Reverse Execute Reverses program execution to the
instruction highlighted in the Instructions
pane
Full History Enables (Yes) or disables (No) reverse
execution

File window
The File window shows the contents of the disk file as hex bytes
or as an ASCII file.

Goto Displays line number or hex offset


Search Searches for string or data bytes
Next Searches again for next occurrence
Display As Sets file display mode: ASCII/Hex
File Switches to view new file
Typing any character is a shortcut for the Search local menu
command.

Log window
menu The Log window shows messages sent to the log and allows you
to list Windows memory and module information.

Open Log File Starts logging to a file


Close Log File Stops logging to a file

194 Turbo Debugger for Windows User's Guide


Logging Toggles logging: No/Yes
Add Comment Writes user comment to log
Erase Log Clears all log messages
Display Windows Info Displays the Windows Information
dialog box, from which you can
pick the type of list (global heap,
local heap, or module) you want to
display
Typing any character is a shortcut for the Add Comment local
menu command.

Module window
The Module window shows the source file for the program
module.

Inspect Shows contents of variable under cursor


Watch Adds variable under cursor to watch list
Module Changes to display different module
File Changes to display different file
Previous Displays last module and position
Line Displays source at line in module
Search Searches for text string
Next Searches for next occurrence of string
Origin Displays current program location
Goto Shows source or instructions at address
Typing any character is a shortcut for the Goto local menu
command.

Windows
Messages The Windows Messages window has three panes: the Window
window Selection pane, the Message Class pane, and the Messages pane.

Window Selection These are the local menu commands in this pane:
pane
Add Adds a window name or handle value
Remove Removes the selected window
Delete all Deletes all window selections
Typing any character is a shortcut for the Add local menu
command in this pane.

Chapter 13, Command reference 195


The De/key or the Ctrl-Ykey combination is a shortcut for the
Remove local menu command.

Message Class pane These are the local menu commands in this pane:

Add Adds a message class or single message


Remove Removes the selected message class or single
message
Delete all Deletes all message class or single message
selections
Typing any character is a shortcut for the Add local menu
command in this pane.
The Del key or the Ctrl-Y key combination is a shortcut for the
Remove local menu command.

Messages pane These are the local menu commands in this pane:

Send to log window Sends all messages received to the log


window so they can be saved in a log file
Erase log Erases all messages in the pane

Clipboard
window The Clipboard window shows you all the items you've copied
into the Clipboard. It has a single pane with the following local
menu commands:

Inspect Puts you in the window an item was


copied from so you can inspect the item
Remove Removes the highlighted item
Delete All Deletes all Clipboard items
Freeze Freezes the highlighted item at its current
value

196 Turbo Debugger for Windows User's Guide


Numeric
Processor window The Numeric Processor window has three panes: the Register
pane, the Status pane, and the Control pane.

Register pane These are the local menu commands in this pane:

Zero Clears the highlighted register


Empty Sets the highlighted register to empty
Change Sets the highlighted register to a value
Typing any character is a shortcut for the Change local menu
command in this pane.

Status pane This is the local menu command in this pane:

Toggle Cycles through valid flag values

Pressing Enter or Spacebaris a shortcut for the Toggle local menu


command in this pane.

Control pane This is the local menu command in this pane:

Toggle Cycles through valid flag values


Pressing Enter or Spacebaris a shortcut for the Toggle local menu
command in this pane.

Hierarchy window
The Hierarchy window has two panes, the Class pane and the
Hierarchy Tree pane.

Class pane
Inspect Shows contents of highlighted class
Tree Moves to the Hierarchy Tree pane

Chapter 73, Command reference 197


Hierarchy Tree pane
Inspect Shows contents of highlighted object or class
Parents Toggles whether Parent Tree pane is displayed
if you are running a program with multiple
inheritance

Parent Tree pane


Inspect Shows contents of highlighted object or type

Registers window
menu The Registers window is identical to the Register and Flags panes
of the CPU window. Its local menus are identical to the Register
pane local menu and the Flags pane local menu.

Stack window
The Stack window shows the currently active procedures.

Inspect Shows source code for highlighted procedure


Locals Shows local variables for highlighted
procedure
Pressing Enter is a shortcut for the Inspect local menu command.

Variables window
The Variables window has two panes, each with a local menu:
The Global Symbol pane and the Local Symbol pane.

Global Symbol pane


Inspect Shows contents of highlighted symbol
Change Changes value of highlighted symbol
Watch Opens Watches window and puts currently
selected global symbol in window
Pressing Enter is a shortcut for the Inspect local menu command in
this pane.

198 Turbo Debugger for Windows User's Guide


Local Symbol pane
Inspect Shows contents of highlighted symbol
Change Changes value of highlighted symbol
Watch Opens Watches window and puts currently
selected global symbol in window
Show Displays Show dialog box with following
choices:
Static Show only static variabies
Auto Show only variables local to current block
Both Show both types of variables (default)
Module Change current module

Pressing Enter is a shortcut for the Inspect local menu command in


this pane.

Watches window
The Watches window has a single pane that shows the names and
values of the variables you're watching.

Watch Adds a variable or expression to watch


Edit Lets you edit a watch variable or expression
Remove Deletes highlighted variable or expression
Delete All Deletes all watch variables and expressions
Inspect Shows contents of highlighted variable or
expression
Change Changes contents of highlighted variable; does
not affect expressions

The following keys are shortcuts to local menu commands in this


window:

any character Watch


Enter Edit
Del Remove

Chapter 73, Command reference 199


Inspector window
An Inspector window shows the contents of a data item.

Range Selects array members to inspect


Change Changes the value of highlighted item
Inspect Opens new Inspector window for highlighted
item
Descend Expands highlighted item into this Inspector
window
New Expression Inspects a new expression in this Inspector
window
Type Cast Typecasts highlighted item to new type

Class Inspector
window Class Inspector windows have two panes that show the contents
(data members and member functions) of a class. Their local
menus, the same for both panes, are quite different from the local
menu of regular Inspector windows.

Inspect Shows the contents of the highlighted class


Hierarchy Returns to the Hierarchy window
Show Inherited Toggles between showing contents of all
ancestor types of object and contents declared
in current type

Object Inspector
window
Object Inspector windows contain three panes, of which only the
first two have local menus. (The third displays only the class to
which the object belongs). Both local menus are the same, and
contain the following commands:

Range Selects data members to inspect


Change Changes value of highlighted item
Methods Toggles whether member functions are
summarized in middle pane

200 Turbo Debugger for Windows User's Guide


Show Inherited Toggles between showing contents all base
classes of object and contents declared in
current class
Inspect Opens new Inspector window for highlighted
item
Descend Expands highlighted item into this Inspector
window
New Expression Inspects a new expression in this Inspector
window
Type Cast Typecasts highlighted data item to new type
Hierarchy Returns to the Hierarchy window

Text panes
Text pane is the generic name for a pane that displays the contents
of a text file. The blinking cursor shows your current position in
the file. The following table lists all the commands:

Table 13.2
Text pane key commands Key Function
~~~~~~~~~~~~~~~~~~~~~~~~~~-

1ns Marks text block


i Moves up one line
J, Moves down one line
~ Moves right one column
~ Moves left one column
Ctr/~ Moves to next word
Ctr/~ Moves to previous word
Home Goes to start of line
End Goes to last character on line
PgUp Scrolls up one screen
PgDn Scrolls down one screen
Ctrl-Home Goes to top line of pane
Ctrl-End Goes to bottom line of pane
Ctrl-PgUp Goes to first line of file
Ctrl-PgDn Goes to last line of file

If you're not using the control-key shortcuts, you can also use the
WordStar-style control keys for moving around a text pane.

Chapter 73, Command reference 201


List panes
This is the generic name for a pane that lists information you can
scroll through. A highlight bar shows your current position in the
list. Here's a list of all the commands available to you.

Table 13.3
List pane key commands Key Function
~~~~~~~~~~~~~~~~~~~~~~~~~-

i Moves up one item


.!. Moves down one item
-? Scroll right
~ Scroll left
Home Goes to start of line
End Goes to last character on line
PgUp Scrolls up one screen
PgDn Scrolls down one screen
Ctrl-Home Goes to top line of list pane
Ctrl-End Goes to bottom line of list pane
Ctrl-PgUp Goes to first item in list
Ctrl-PgDn Goes to last item in list
Backspace Backs up one character in incremental match
Letter Makes incremental search (select by typing)
Ins Marks multiple list items for block copy

If you're not using the control-key shortcuts, you can also use the
WordStar-style control keys for moving around a list pane.

Commands in input and history list boxes


The following table shows the commands available when you're
inside an input or list box:

202 Turbo Debugger for Windows User's Guide


Table 13.4
Dialog box key commands Key Function
~~~~~~~~~~~~~~~~~~~~~~~~~~~-

i Moves up one list item


.!. Moves down one list item
~ Moves right one character
~ Moves left one character
Ctr/~ Moves to next word
Ctr/~ Moves to previous word
Home Goes to start of line
End Goes tc last character on line
PgUp Scrolls up one screen
PgDn Scrolls down one screen
Ctrl-Home Goes to top line of list pane
Ctrl-End Goes to bottom line of list pane
Ctrl-PgUp Goes to first item in list
Ctrl-PgDn Goes to last item in list
Backspace Deletes the character before the cursor
Enter Accepts your input and proceeds
Del Deletes the character at the cursor
Esc Cancels the dialog box and returns to menu
Ctrl-N Completes partially typed name in input box

Window movement commands


The following table shows the keys you can use to reposition and
resize a window:
Table 13.5
Window movement key Key Function
commands Ctrl-F5 Toggles window-positioning mode
i Moves window up one line
j. Moves window down one line
~ Moves window right one column
~ Moves window left one column
Shifti Resizes window; moves bottom up
Shift.!. Resizes window; moves bottom down
Shift~ Resizes window; moves right side away from left
Shift~ Resizes window; moves right side toward left
Home Moves to left side of screen
End Moves to right side of screen
PgUp Moves to top line of screen
PgOn Moves to bottom line of screen
Enter Accepts current position
Esc Cancels window-positioning command

Chapter 73, Command reference 203


Wildcard search templates
You can use wildcard search templates in two circumstances:
•when you enter a file name to load or examine
•when you enter a text search expression in a text pane
The ? (question mark) matches any single character in the search
expression. The * (asterisk) matches 0 or more characters in the
search expression.

Complete menu tree


Figure 13.l shows the complete structure of Turbo Debugger's
pull-down menus.

204 Turbo Debugger for Windows User's Guide


Figure 13.l: The Turbo Debugger menu tree

=
•l
(System)
lmll
L_____,
... .. 111111
,--J
l
Run
1:mma•l•llilB m111 Blll·H~..

Options
I
ll!llil!D IDlil JI

Repaint desktop Run F9 Language ... Source


Restore standard Go to cursor F4 Macros

·~
Trace into F7 Display options •••
About. .. Step over F8 Path for source •••
L .. _. --~- ~--------- ----- Exe:::..:te t::: •.• A1t.of9 Save opt~ o:-:s . ..
Until return
Animate ••.
Alt-F8
I Restore options •••
l Back trace Alt-F4
File Instruction trace Alt-F7 l
Create .•. Alt =
Open •.. Arguments ..• Stop recording Alt -
Change dir ... Program reset Ctrl-F2 Remove ...
Get info •.. Delete all
Symbol load ...
Quit Alt-X
l
Breakpoints Window
l
Toggle F2 Zoom F5
At .•. Alt-F2 Next F6
Changed memory global ... Next pane Tab
_[_ Expression true global ... Size/move Ctrl-F5
Edit Hardware breakpoint ... Iconi ze/restore
Delete all Close Al t-F3
Copy Shft-F3 Undo close Alt-F6
Paste Shft-F4
Copy to log User screen Al t-F5
Dump pane to 1og 1 (First open window)
(2-9 open windows)
Window pi ck •..

l
View
l
Data Help
l
Breakpoints Inspect. .. Index Sh ft-Fl
Stack Evaluate/modify ..• Ctrl-F4 Previous topic Alt-Fl
Log Add watch ..• Ctrl-F7 Help on help
Watches Function return
Variables
Module •.• F3
File .•.
CPU
Dump
Registers
Numeric processor
Execution hi story
Hierarchy
Windows messages
Clipboard
Another ..
Wi Module ...
Dump
File •.•

Chapter 73, Command reference 205


206 Turbo Debugger for Windows User's Guide
c H A p T E R

14

Debugging a standard C application


Debugging is like the other phases of designing and imple-
menting a program-part science and part art. There are specific
procedures that you can use to track down a problem, but at the
same time, a little intuition goes a long way toward making a long
job shorter.
The more programs you debug, the better you get at rapidly
locating the source of problems in your code. You learn
techniques that suit you well, and you unlearn methods that have
caused you problems.
In this chapter, we discuss some different approaches to debug-
ging, talk over the different types of bugs you may find in your
programs, and suggest some ways to test your program to make
sure that it works-and keeps on working.
Let's begin by looking at where to start when you have a program
that doesn't work correctly.

When things don't work


First and foremost, don't panic! Even the most expert pro-
grammer seldom writes a program that works the first time.
To avoid wasting a lot of time on fruitless searches, try to resist
the temptation to randomly guess where a bug might be. It is

Chapter 74, Debugging a standard C application 207


better to use a universally tried-and-true approach: divide and
conquer.
Make a series of assumptions, testing each one in turn. For
example, you can say, "The bug must be occurring before function
xyz is called," and then test your assumption by stopping your
program at the call to xyz to see if there's a problem. If you do
discover a problem at this point, you can make a new assumption
that the problem occurs even earlier in your program.
If, on the other hand, everything looks fine at function xyz, your
initial assumption was wrong. You must now modify that
assumption to "The bug is occurring sometime after function xyz
is called." By performing a series of tests like this, you can soon
find the area of code that is causing the problem.
That's all very well, you say, but how do I determine whether my
program is behaving correctly when I stop it to take a look? One
of the best ways of checking your program's behavior is to
examine the values of program variables and data structures. For
example, if you have a routine that clears an array, you can check
its operation by stopping the program after the function has
executed, and then examining each member of the array to make
sure that it's cleared.

Debugging style
Everyone has their own style of writing a program, and everyone
develops their own style of debugging. The debugging sugges-
tions we give here are just starting points that you can build on to
mold your own personal approach. ·
Many times, the intended use of a program influences the
approach you take to debug it. If a program is for your own use or
will only be used once or twice to perform a specific task, a full-
scale testing of all its components is probably a waste of time,
particularly if you can determine that it is working correctly by
inspecting its output. If a program is to be distributed to other
people or performs a task of which the accuracy is hard to
determine by inspection, your testing must be far more rigorous.

208 Turbo Debugger for Windows User's Guide


Run the whole
thing For a simple or throwaway program, the best approach is often
just to run it and see what happens. If your test case has
problems, run the program with the simplest possible input and
check the output. You can then move on to testing more compli-
cated input cases until the output is wrong. This testing
procedure will give you a good feeling for just how much or how
little of the program is working.

Incremental
testing When you want to be very sure that a program is healthy, you
must test the individual routines, as well as checking that the
program works as expected for some test input data. You can do
this in a couple of ways: You can test each routine as you write it
by making it part of a test program that calls it with test data. Or
you can use TOW to step through the execution of each routine
when the whole program is finished.

Types of bugs
Bugs fall into two broad categories: those peculiar to the language
you're working in and those that are common to any program-
ming language or environment.
By making mental notes as you debug your programs, you learn
both the language-specific constructs you have trouble with, and
also the more general programming errors you make. You can
then use this knowledge to avoid making the same mistakes in
the future, and to give you a good starting point for debugging
future programs.
Understanding that each bug is an instance of a general family of
bugs or misunderstandings will improve your ability to write
errorless code. After all, it's better to write bug-free code than to
be really good at finding bugs.

Chapter 14, Debugging a standard C application 209


General bugs
The following examples barely scratch the surface of the kinds of
problems you can encounter in your programs.

Hidden effects If you are careless about using global variables in functions, a call
to a function can leave unexpected contents in a variable or data
structure:
char workbuf[20];
strcpy(workbuf,"all done\n");
convert("xyz");
printf (workbuf);

convert(char *p)
{
strcpy(workbuf, p);
while (*p)

Here, the correct thing to do would be to have the function use its
own private work buffer.

Assuming initialized Don't assume that another routine has already set a variable for
data you:
char *workbuf;
addworkstring(char *s)
{
strcpy{workbuf, s); I* oops */

You should code a routine of this sort defensively by adding the


statement
if (workbuf == 0) workbuf = (char *)malloc(20);

Not cleaning up This sort of bug can crash your program by exhausting heap
space:

210 Turbo Debugger for Windows User's Guide


crunch_string(char *p)
{
char ·*work= (char *)malloc(strlen(p));
strcpy(work, p);

return (p); /* whoops--work still allocated */

Fencepost errors Thest> bugs are named after the old brain teaser that goes "If I
want to put up a 100-foot fence with posts every 10 feet, how
many fenceposts do I need?" A quick but wrong answer is ten
(what about the final post at the far end?). Here's a simple
example:
for (n = 1; n < 10; n++)
{
/* oops--only 9 times */

Here you can easily see the numbers 1 and 10, and you think that
your loop goes from one to ten. (Better make that < into a <=.)

C-specific bugs
Turbo C++ for Windows is very good at finding C-specific bugs
that other compilers don't warn you about. You can save yourself
some debugging time by turning on all the warnings that the
compiler is capable of generating. (See the Turbo C++ for
Windows manuals for information on setting these warnings.)
What follows is by no means an exhaustive list of ways you can
get in trouble with C. For some of these errors, Turbo C++ for
Windows issues a warning message. Remember to examine the
cause of any warning messages; they may be telling you about a
bug in the making.

Using uninitialized In C, an automatic variable declared inside a function is unde-


automatic variables fined until you assign a value to it:
do_ten_times()
{
int n;
while (n < 10)

n++;

Chapter 14, Debugging a standard C application 211


This function executes the while loop an unpredictable number of
times because n is not initialized to 0 before being used as a
counter.

Confusing = and == C lets you both assign a value (=) and test for equality <==) within
an expression; for example,
if (x = y)

This expression inadvertently loads y into x and performs the


statements in the if expression if the value of y is not 0. You
almost certainly meant to say
if (x == y)

Confusing operator C has so many operators that it is hard to remember which ones
precedence are applied first when an expression is evaluated. One combi-
nation that often causes grief is the mixture of shift operators with
addition or subtraction. For example,
x=3«1+1
evaluates to 12, not 7, as you might expect if you thought << took
effect before the +.

Bad pointer arithmetic When you use a pointer to step through an array, be careful how
you increment and decrement it. For example,
int *intp;
intp += sizeof(int);
does not increment intp to point to the next element of an integer
array. Instead, intp is advanced by two array elements because in
adding to or subtracting from a pointer, C takes into account the
size of the item the pointer is pointing to. All you have to do to
move the pointer to the next element is
intp++

212 Turbo Debugger for Windows User's Guide


Unexpected sign Be careful about assigning between integers of different sizes:
extension
int i = OXFFFE;
long l;
l = i;
if (1 & OX80000000) (
/* this DOES get executed */

One of C's strong ooints can cause vou trouble if vou are not
........ .... J ,J

aware of how it operates. C lets you assign freely between scalar


values (char, int, and so on). When you copy an integer scalar into
a larger scalar, the sign (positive or negative) is preserved in the
larger scalar by propagating the sign (highest) bit throughout the
high portion of the larger scalar. For example, an int value of -2
(Oxfffe) becomes a long value of -2 (Oxfffffffe).

Unexpected truncation This problem is the opposite of the previous one:


int i;
long l = OXlOOOO;
i = l;
while (i > 0)
/* this does NOT get executed */

Here, the assignment of I to i resulted in the top 16 bits of I being


truncated, leaving a value of zero in i.

Misplaced semicolons The following code fragment may appear to be fine at first glance:
for (x = O; x < 10; x++);
{
/* only executed once */

Why does the code between the braces execute only once? Closer
inspection reveals a semicolon (;) at the end of the for expression.
This hard-to-find bug causes the loop to execute ten times, but
does nothing. The subsequent block is then executed once. This is
a nasty problem because you can't find it with the usual technique
of examining the formatting and indenting of code blocks in your
program.

Chapter 74, Debugging a standard C application 213


Macros with side The following problem is enough to make you swear off #define
effects macros for life:
#define toupper (c) 'a'<= (c) && (c) <=' z' (c)-' a'-' A' (c)
char c, *p;
c = toupper(*p++);
Here, pis incremented two or three times, depending on whether
the character is uppercase. This type of problem is very hard to
find, because the side effect is hidden within the macro definition.

Repeated autovariable Another hard one to find:


names
myfunc ()
{
int n;
for (n = 5; n >= 0; n--)
{
int n = 10;

if (n == 0)

/* never gets executed */

Here, the automatic variable name n is reused in an inner block,


hiding access to the one declared in the outer block. You must be
careful about reusing variable names in this manner. You can get
into trouble more easily than you might think, especially if you
use a limited number of variable names for local loop counters
(for example, i, n, and so forth).

Misuse of autovariables This function means to return a pointer to the result:


int *divide_by_3(int n)
{
int i;
i = n I 3;
return (&i);

The trouble is that by the time the function returns, the automatic
variable is no longer valid and is likely to have been overwritten
by other stack data.

214 Turbo Debugger for Windows User's Guide


Undefined function If you don't end a function with the return keyword followed by
return value an expression, it returns an indeterminate value; for example,
char *first_capital_letter(char *p)
{
while (*p)

if ('A' <= *p && *p <= 'Z')


return (p);
pt+;

/* Oops--nothing returned here */

If there are no capital letters in the string, a garbage value is


returned. You should put a return (0) as the last line of this
function.

Misuse of break The break keyword exits from only a single level of do, for,
keyword switch, or while loops:
for ( ... )
{
while ( ... )
if ( ... )
break; /* we want to exit for loop */

Here, the break exits only from the while loop. This is one of the
few cases where it is excusable to use the goto statement.

Code has no effect Sometimes a typo results in source code that compiles, but doesn't
do what you want it to. It may not do anything at all.
a + b;

Here, the intended line of code was a += b.

Accuracy testing
Making a program work with valid input is only part of the job of
testing. The following sections discuss some important test cases

Chapter 14, Debugging a standard C application 215


that any program or routine should be subjected to before being
given a clean bill of health.

Testing boundary
conditions Once you think a routine works with a range of data values, you
should subject it to data at the limits of the range of valid input.
For example, if you have a routine to display a list from 1 to 20
items long, you should make sure it behaves correctly both when
there is exactly 1 item and exactly 20 items in the list. This can
flush out the one-too-few and one-too-many "fencepost" errors
(described on page 211).

Invalid data input


Once you are sure that a routine works with a full range of valid
input, check that it behaves correctly when it's given invalid
input. Check that erroneous input is rejected, even when it's very
close to valid data. For example, the previous routine that
accepted values from 1 to 20 should make sure that 0 and 21 are
rejected.

Empty data input


Empty data input is a frequently overlooked area, both in testing
and in designing a program. If you write a program to have
reasonable default behavior when some input is omitted, you
greatly enhance its ease of use.

Debugging as part of program design


When you first start designing your program, you can plan for the
debugging phase. One of the most basic tradeoffs in program
design involves the degree to which the different parts of your
program check that they are getting valid input and that their
output is reasonable.
If you do a lot of checking, you end up with a very resilient pro-
gram that can often tell you about an error condition but
continues to run after performing some reasonable recovery. You
also end up with a larger and slower program. This type of pro-
gram can be fairly easy to debug because the routines themselves
inform you of invalid data before the dangers can be propagated.

216 Turbo Debugger for Windows User's Guide


You can also implement a program whose routines do little or no
validation of input or output data. Your program will be smaller
and faster, but bad input data or a small bug can bring things to a
grinding halt. This type of program can be the most difficult to
debug, since a small problem can end up manifesting itself much
later during execution. This makes it hard to track down the
original error.
Most programs end up being a mixture of these two techniques.
You should treat input from external sources (such as the user or
a disk file) with greater suspicion than data from one internal
routine calling another.

The sample debugging session


This sample session uses some of the techniques we talked about
in the previous sections. The program you are debugging,
TDDEMOB, is a version of the demonstration program used in
Chapter 3 (TDDEMO.C), except this one has some deliberate bugs
in it. As with TDDEMO, TDDEMOB was compiled using the
Turbo C++ for Windows EasyWin feature to display its output
through Windows.
Make sure your working directory contains the two files needed
for the debugging demonstration, TDDEMOB.C and
TDDEMOB.EXE. (The B in these file names stands for "buggy.")

Looking for errors


Before we start the debugging session, let's run the buggy demo
program to see what's wrong with it. To start the program, type
TD DEMOB
You are prompted for lines of text. Enter two lines of text
one two three
four five six
A final empty line ends your input. TDDEMOB then prints out its
analysis of your input:
Arguments:
Enter a line (empty line to end) : one two three
Enter a line (empty line to end) : four five six
Enter a line (empty line to end) :

Chapter 74, Debugging a standard C application 217


Total number of letters = 7
Total number of lines = 6
Total word count = 2
Average number of words per line = 0.3333333
'E' occurs 1 times, 0 times at start of a word
'F' occurs 1 times, 1 times at start of a word
'N' occurs 1 times, 0 times at start of a word
'O' occurs 2 times, 1 times at start of a word
'R' occurs 1 times, 0 times at start of a word
'U' occurs 1 times, 0 times at start of a word
There is 1 word 3 characters long
There is 1 word 4 characters long
Notice that there are erroneous numbers for the total number of
words, letters, and word count. Later on, the letter and word
frequency tables seem to be based on an erroneous letter and
word count. This situation is all-too-typical-the program must
have more than one bug. This happens frequently in the early
stages of debugging a program.

Deciding your
plan of attack Your first task is to decide which problem to attack first. A good
rule of thumb is to start with the problem that appears to be
happening first. In this program, each input line is broken down
into words, then analyzed, and finally, after all the lines have been
entered, the tables are displayed. Since the word and letter counts
are off as well as the tables, it's a good bet that something is
wrong during the initial breaking down and counting phase.
Now is the time to start debugging, after you've thought about the
problem for a moment and decided on a rough plan of attack.
Here, the strategy is to examine the routine makeintowords, to see if
it is correctly chopping the line into null-terminated words, and
then see if analyzewords is correctly counting the analyzed line.

Starting Turbo
Debugger To start the sample debugging session, make sure the Turbo C++
edit window with TDDEMOB is current, then use the Run I
Debugger command.
TOW loads the buggy demo program and displays the startup
screen. If you want to exit from the tutorial session and return to
Turbo C++, press Alt-X at any time. If you get hopelessly lost, you
can always reload the demonstration program and start from the

218 Turbo Debugger for Windows User's Guide


beginning again by pressing Ctr/-F2. (Note that reloading doesn't
clear breakpoints or watches.)
Since the first thing you want to do is to check that makeintowords
is working correctly, run the program up to that routine and then
check it. There are two approaches you can use: Either step
through makeintowords as it executes, making sure that it does the
right thing, or stop the program after makeintowords has done its
stuff and see if it did the right thing
Since makeintowords has a clearly defined task and it's easy to
determine whether it's working correctly by inspecting the output
buffer it produces, let's opt for the second approach. To do this,
move down to line 42 and press F4 to run to this line. When the
program screen appears, type
one two three
and press the Enter key.

Inspecting
You are now stopped at the source line after the call to
makeintowords. Look at the contents of buffer to see if the right
thing happened. Move the cursor up a line, place it under the
word buffer, and press Alt-F10 I (for Inspector) to open an Inspector
window to show the contents of buffer. Use the arrow keys to
scroll through the elements in the array. Notice that makeintowords
has indeed put a single null character (0) at the end of each word
as it is meant to. This means that you should execute more of the
program and see if analyzewords is doing the right thing. First,
remove the Inspector window by pressing Esc. Then, press F7
twice to execute to the start of analyzewords.

Breakpoints
Check that analyzewords has been called with the correct pointer to
the buffer by moving the cursor under bufp and pressing Alt-F10 I.
You can see that bufp indeed points to the null-terminated string
'one'. Press Escto remove the Inspector window. Since there
seems to be a problem with counting characters and words, let's
put a breakpoint at the places where a character and a word are
counted:

l. Move to line 93 and press F2 to set a breakpoint.


2. Move to line 97 and set another breakpoint.

Chapter 74, Debugging a standard C application 219


3. Finally, set a breakpoint on line 99 so you can look at the
character count this function returns.

Setting multiple breakpoints like this is a typical way to learn


about whether things are happening in the right order in a
program, and lets you check on important data values each time
the program stops at a breakpoint.

The Watches
window Run the program by pressing F9. The program stops when it
reaches the breakpoint on line 93. Now you want to look at the
value of charcount. Since you'll want to check it each time you hit
a breakpoint, this is an ideal time to use the Watch command to
place it in the Watches window. Move the cursor under charcount
and press Alt-F10 W. The Watches window at the bottom of the
screen now displays the current value of 0. To make sure that the
character is being counted properly, execute a single line by pres-
sing F7. The Watches window now shows that charcount is 1.

The
Evaluate/Modify Run the program again by pressing F9. You are now back at line
dialog box 93 for another character. Press F9 again twice to read the last letter
on the word and the terminating null. charcount now correctly
shows 3, and the wordcounts array is about to be updated to count
a word. Everything is fine so far. Press F9 again to start processing
the next word in the buffer. AHA! Something is wrong.
You expected the program to stop again on line 93 as it processed
the next word, but it didn't. It went straight to the statement that
returns from the function. The only way to end up on line 99 is if
the while loop that started on line 83 no longer has a true test
value. This means that *bufp != 0 must evaluate to false (that is, 0).
To check this, move back to line 83 and mark the entire expression
*bufp != 0 by putting the cursor under the*, pressing Ins, and
moving the cursor to the final '0' before the ' ) '. Now evaluate
this expression by opening the Data I Evaluate Modify dialog box
and either pressing Enter or choosing the Eval button to accept the
marked expression. The value is indeed 0. Press Esc to return to
the Module window.

220 Turbo Debugger for Windows User's Guide


Eureka!
Now here comes the analytical leap that enables you to "solve"
the bug. The reason bufp points to a 0 is because that is where the
inner while loop starting on line 86 left it at the end of a word. To
continue to the next word, you must increment bufp past the 0
that ended the previous word. To do this, you need to add a
"bufp++" statement before line 97. You could recompile your pro-
gram ~vith this statement added, but Turbo Debugger lets you
"splice" in expressions by using a fancy sort of breakpoint.
To do this, first reload the program by pressing Ctrl-F2 so you can
test with a clean slate. Now remove all the breakpoints you set in
the previous session by typing Alt-B D. Go back to line 97 and set a
breakpoint again by pressing F2. Now, open a Breakpoints
window by pressing Alt-VB. Do the following to set this break-
point to execute the expression bufp++ each time it is encountered:

1. With the Breakpoints window open, press Ctrl-S to open the


Breakpoint Options dialog box.
2. Press the Change button to display the Conditions and Actions
dialog box.
3. Set the Action radio buttons to Execute.
4. Press Tab to get to the Action Expression prompt.
5. Enter bufp++.
6. Press Enter twice to return to the Breakpoints window.
Displayed in the right pane of this window is the new action
Execute "bufp++".
7. Press Alt-F3 to return to the Module window.

Now run the program. Enter the usual two input lines.
one two three
four five six

Press Enter at the third prompt, and when the program terminates,
look at your output on the User screen.
You'll notice that things have improved considerably. The total
number of words and lines seem to be wrong, but the tables are
correct. Close the application window to get back to the Module
window.

Chapter 74, Debugging a standard C application 221


The next thing you'll do is stop at the beginning of the
printstatistics routine and see if it is given the correct values to
print. First reload the program by pressing Ctrl-F2 to reset. Then go
to line 104 and press F4 to execute to there.
Enter the usual two input lines,
one two three
four five six
then press Enter on the third prompt.
Now that you're back in the Module window on line 104, move
the cursor to the nlines argument and press Ctr/-/ to look at its
value. Note that the value is 6, the wrong value. It should be 2.
Next, go back to where nlines is called from in main and look at its
value there. Move the cursor to line 36, place it under nlines, and
press Ctrl-1 to look at the value. The value of nlines in main is 2,
which is correct. If you go down to line 46, you will notice that the
two arguments nwords and nlines have been reversed. There is no
way that the compiler could have known that you meant to have
them the other way around.
If you correct these two bugs, the program will run correctly. The
file TDDEMO.EXE is a corrected version you can run if you're
curious.

222 Turbo Debugge1 for Windows User's Guide


c H A p T E R

15

Debugging an ObjectWindows
application
The sample Windows programs in this chapter were written
using the ObjectWindows application framework that makes
Windows programming so much easier.
The programs are TDODEMO and TDODEMOB (the B stands for
buggy). TDODEMOB has several bugs in it that you'll discover by
working through this chapter.
If there are no .EXE files for Before continuing, it might be helpful if you start TDODEMO
TDODEMO and TDODEMOB, from Windows and play with it a bit to get an idea of how it
you'll have to open their
project files and compile works. You can either use the Program Manager File IRun
them with debug information command to start TDODEMO.EXE or add it to a program group
included. as an icon.

About the program


TDODEMO is an ObjectWindows program that lets you use a
mouse to scribble in various colors on the screen. When you click
the left mouse button and drag the mouse, the program draws on
the screen. You can clear the window by clicking the right-hand
mouse button. TDODEMO has a menu bar that lets you pick any
of four pen colors: Red, Green, Blue, or Black.
You draw by pressing the mouse button, moving the mouse, and
releasing the mouse button. The program accomplishes this task

Chapter 75, Debugging an ObjectWindows application 223


easily by using the ObjectWindows library and dynamic virtual
member functions. A dynamic virtual member function is a virtual
member function with a numeric identifier (called a dispatch index)
attached to it.
Because Turbo C++ for Windows defines Windows message
names as numeric constants, you can use a Windows message
name as the dispatch of a dynamic virtual member function.
ObjectWindows can then call the member function whenever the
window for which the member function is declared receives a
message that matches the member function's dispatch index. If
there is no member function with an identifier matching the
Windows message, ObjectWindows calls the default window
function.
For example, in order to create a function that responds to
WM_MOUSEMOVE messages, you can declare a function within
a window object that looks like this:
virtual void WMMouseMove(RTMessage Msg) = [WM_FIRST+WM_MOUSEMOVE];
As you can see, immediately after the function declaration, you
use an equal(=) sign to attach an expression in brackets([]) to the
function, in this case WM_FIRST+WM_MOUSEMOVE. You add
ObjectWindows constant WM_FIRST to the message constant
WM_MOUSEMOVE to indicate that the message constant
represents a WM-type message.
The type RTMessage contains the Windows procedure
parameters wParam and lParam. These parameters often hold
additional information about the message, such as where the
cursor is positioned.
The next few sections explain how the TOODEMOB program
works. They purposely gloss over the bugs so you cap. discover
them later. It might be helpful to start Turbo C++ for Windows
and open TDODEMOB.CPP so you can follow along in the code.

The Color Scribble


window type The Color Scribble window class is defined as follows:
definition

224 Turbo Debugger for Windows User's Guide


class ScribbleWindow public TWindow

public:
HDC HandleDC; II Display context for drawing.
BOOL ButtonDown; II left-button-down flag
HPEN ThePen; II Pen that is used for drawing in color
ScribbleWindow(PTWindowsObject AParent, LPSTR ATitle);
~ScribbleWindow();
void GetWindowClass(WNDCLASS &AWndClass);

virtual void WMLButtonDown(RTMessage Msg)=[WM_FIRST+WM_LBUTTONDOWN];


virtual void WMLButtonUp(RTMessage Msg)=[WM_FIRST+WM_LBUTTONUP];
virtual void WMMouseMove(RTMessage Msg)=[WM_FIRST+WM_MOUSEMOVE];
virtual void WMRButtonDown(RTMessage Msg)=[WM_FIRST+WM_RBUTTONDOWN];
virtual void SelectRedPen(RTMessage Msg)=[CM_FIRST+CM_RED];
virtual void SelectGreenPen(RTMessage Msg)=[CM_FIRST+CM_GREEN];
virtual void SelectBluePen(RTMessage Msg)=[CM_FIRST+CM_BLUE];
virtual void SelectBlackPen(RTMessage Msg)=[CM_FIRST+CM_BLACK];
virtual void SetupWindow();
};

The ScrlbbleWindow class defines a window object that responds


to the following user input:
•Mouse movement
•Left mouse button press and release
•Right mouse button press
•Pen color and position
There are three data members, HandleDC, ButtonDown, and ThePen
that hold a device context, the state of the mouse button, and the
current pen the user draws with, respectively.

ScribbleWindow The ScrlbbleWindow constructor attaches the menu to the program


and initializes the ButtonDown data member to FALSE and ThePen
to CM_BLACK.

GetWindowClass The GetWindowClass member function calls the standard


TWindow GetWindowClass function to set up the window so it
behaves like any other TWlndow, and then initializes the program's
custom icon.

Chapter 15, Debugging an ObjectWindows application 225


WMLButtonDown When the user presses the left mouse button in the Color Scribble
window and is about to draw, the window receives a
WM_LBUTTONDOWN message, which causes ObjectWindows to
call WMLButtonDown (since it has an identifier of
WM_FIRST +WM_LBUTTONDOWN). WMLButtonDown moves
the pen to the current position of the mouse and sets ButtonDown
to indicate that the button is down, and then selects ThePen into the
current device context. There are additional Windows calls this
function should be making that will be discussed later.

WMLButtonUp When the user finishes scribbling and releases the mouse button,
the window receives a WM_LBUTTONUP message, which in turn
causes ObjectWindows to call WMLButtonUp. The program marks
the ButtonDown variable FALSE and releases the device context
associated with the window.

WMRButtonDown When the user presses the right button to clear the screen,
ObjectWindows calls the function WMRButtonDown, which calls
the Windows function UpdateWindow. Calling this function is
supposed to clear the window.

WMMouseMove Once the user starts moving the mouse over the window, the
window begins receiving WM_MOUSEMOVE messages, which
cause ObjectWindows to call the function WMMouseMove. If the
user has pressed the left inouse button, the program draws a line
each time the mouse is moved. If the user hasn't pressed a mouse
button, nothing at all happens.

The pen-color routines There are four functions that set the pen color by deleting the
current pen and creating a new one of the correct color. These
functions differ only in the color each one sets.

Creating the
application To create an application that uses the Color Scribble window, it's
necessary to derive a class based on the ObjectWindows class
TApplication. The purposes of this class, CScribbleApplication, are
• to redeclare the lnitMainWindow function so the application can
create a main window with the properties of ScribbleWindow

226 Turbo Debugger for Windows User's Guide


Main Window, used to set up •to provide a type for the object MyApp, which is used to set up
window message the window and run the program
breakpoints later in this
chapter, is a member of Now that you know how the program works, you can begin to
MyApp.
debug it.

Debugging the program


If you haven't done so already, start Turbo C++ for Windows and
load the project file, TOODEMOB.PRJ, then load
TOODEMOB.CPP. Next, choose Run IDebugger to run TDW and
load the demo program, then press F9 to run the demo program
under TOW.
"Exception 73" is the You can move the mouse around and even choose menu selections,
message TOW displays when but when you press the left mouse button to start drawing, the
your program causes an
unrecoverable application program fails and returns to TDW, which displays an "Exception
error (UAE). 13" error message.

Finding the first


bug When you press Esc to clear the message box, TDW leaves you in
the CPU window. This window is displayed because your program
was executing Windows code when the failure occurred. Since you
didn't return to the Module window, you don't have a convenient
marker to tell you where you were in your program when it made
the call to Windows that caused the UAE.
Before continuing, press Alt-F3 to close the CPU window (you'll be
working primarily in the Module window).

Finding the function Since the program failed when you pressed the left mouse button,
that called Windows it's likely that the problem is in the WMLButtonDown function.
However, there's another technique you can use to see where your
program was, a stack trace.
To do a stack trace, display the Stack window (choose View I
Stack), then scroll down the list of hexadecimal instructions until
you come to a line indicating a routine in your program (you'll see
the name of the routine in ASCII characters). That line is the one
that called the Windows kernel.
As you can see in the Stack window, the routine you need to look
at is, indeed, WMLButtonDown. To go to this routine in the Module

Chapter 75, Debugging an ObjectWindows application 227


window, first click in that window. Next, press Ctr/-$, type
WMLButtonDown, and press Enterto find this routine. If you see the
message "Search expression not found," go to the top of the file
and press Ctrl-N to search again (in TDW, you can search only from
the current cursor position to the end of the file). You might have
to press Ctrl-N several times before you get to the function itself.

Debugging WMLButtonDown takes a variable of type RTMessage as a


WMLButtonDown parameter and extracts from this message the location of the
mouse. It then calls the Windows functions MoveTo and
SelectObject to position the pen in the window and select it as the
current drawing tool.
Since you saw the name of this routine in the Stack window, the
bad call to Windows has to be one of these two Windows calls. To
see which it is, you can run the program to the beginning of this
function and then single-step through it to see which call causes
theUAE.
With the cursor on the first line of WMLButtonDown, reload
TDODEMOB by pressing Ctrl-F2, then press F4 to run the program
to that point. When you see the Color Scribble window, press the
left mouse button to get the program to return to TDW. (You might
have to press a key to get Windows to release mouse messages.)
This time, there is no UAE (at least not yet), because all that has
executed so far is the Windows call to TOODEMOB's
WMLButtonDown function. TDW returns you to the first line of
that function.
Begin pressing Fl to single-step through the program. When you
press Fl on the call to MoveTo, you see the error box displaying
"Exception 13." The call to MoveTo must be the problem.

Debugging MoveTo The parameters of MoveTo are the handle of the pen and the X and
Y coordinates of the current cursor location. The coordinates come
from the Msg parameter, which gets them from Windows. Unless
the program picks up the wrong part of this message (it doesn't),
these two parameters should be OK.
The culprit must be HandleDC, the pen's device context handle.
At this point, since you've had two UAEs, the safest course of
action is to exit TDW and close Windows before continuing.

228 Turbo Debugger for Windows User's Guide


Fixing the bug If HandleDC was the cause of the UAE, the handle either was set
improperly or was never set in the first place. In fact, the handle
wasn't set. The program should have set the handle by initializing
a display context with the following Windows function call:
HandleDC = GetDC(HWindow);

The following code shows WMLButtonDown with the context


initialization statement added:
void ScribbleWindow: :WMLButtonDown(RTMessage Msg)
{
if ( !ButtonDown I
{
ButtonDown = TRUE; II Mark mouse button as being
II pressed so when mouse movement
II occurs, a line will be drawn.
HandleDC = GetDC(HWindow); II Create display context for drawing.
MoveTo(HandleDC, Msg.LP.Lo, Msg.LP.Hi);
II Move drawing point to location
II where mouse was pressed.
SelectObject(HandleDC, ThePen);
II Select pen into display context.

Testing the fix Open Windows and Turbo C++ for Windows and reload the
TDODEMO project and source file. Add the context initialization
statement to ScribbleWindow::WMLButtonDown, then compile the
project with debug information included (choose Compile I Build
All).
Just in case there are more bugs, run the program program under
TOW again (choose Run I Debugger, then press F9 when the
Module window comes up).
Now if you draw with the pen, you see the drawing appear in the
default color, black. Try different colors by selecting pen colors
from the menu. Red, green, and blue all work fine; however, when
you try to change the pen color back to black, the pen won't change
color. It looks like you've found another bug.

Chapter 75, Debugging an ObjectWindows application 229


Finding the pen
color bug The most likely culprit for this bug is the ScrlbbleWindow function
that creates a black pen, SelectBlackPen. Exit Color Scribble, then
press Ctrl-F2 to reset the program. Set a breakpoint at the opening
brace of ScribbleWlndow::SelectBlackPen, then run the program
and choose Pen I Black. (You might have to press a key to get
Windows to release mouse messages.) TOW should have stopped
execution at the breakpoint. Since it didn't, something else must be
wrong.
It appears that SelectBlackPen is never being called. Because this
routine relies on the dynamically dispatched virtual table (DDVT)
to get called, it's possible that there's something wrong with the
identifier for the function.

Setting a window When a user chooses a menu item, Windows sends a


message breakpoint WM_COMMAND message to the window that owns the menu.
The wParam parameter of the message contains the identifier of the
menu item that was selected. When an ObjectWindows window
receives a WM_COMMAND message, it scans through the
dispatch indexes of the window object looking for the value
CM_FIRST+wParam. SelectBlackPen has an index of
CM_FIRST+CM_BLACK, where CM_BLACK has the value 104.
In order to find out what the wParam parameter of the Pen I Black
command message is, you need to tell TOW to stop execution
when it receives a WM_COMMAND message. You can then run
the program, make the menu selection, and then check the wParam
part of WM_COMMAND to see if it matches the constant
CM_BLACK.
Before you can set the breakpoint, you have to get back to TOW.
Close the Color Scribble application window, then, when you're
back in the Module window, use Ctrl-F2 to reload TDODEMOB.
When the module window comes up, the next step is to set a
window message breakpoint using one of two methods, depending
on whether you have ObjectWindows message support enabled or
disabled.
See the file TDWINST. TDW for By default, there is no special support for ObjectWindows window
information on TDWINST.
message breakpoints. You can't use a window object you've
declared in your program to set a window message breakpoint;
you have to use the window handle instead. If you want to use the

230 Turbo Debugger for Windows User's Gulde


window object (which is easier, but might slow down debugging
when you have a window message breakpoint set), you have to
run TDWINST, choose Options I Source Debugging, and check the
OWL Window Messages checkbox.

Setting a window message breakpoint with a handle


If you don't have ObjectWindows support enabled, you must set
the window message breakpoint by using the wmdow handie.
Because most of the window setup is done in ObjectWindows, you
have to go to some lengths to get access to the handle.
Initial setup of the window is done in the lnitMainWindow
function, but the handle isn't set until later. To return control back
to TDW, you could set a breakpoint in one of the mouse-handling
functions (such as WMLButtonDown), run the program, then use
the mouse and cause the program to hit the breakpoint. (If your
breakpoint is in WMLButtonDown, you could press the left mouse
button.)
Another technique is to redeclare the ObjectWindows function that
initializes the handle, SetupWindow, so you can get control
immediately after the handle is initialized. This function is
redeclared in TDODEMOB as a virtual function and is defined as
follows:
void ScribbleWindow::SetupWindow()
{
TWindow::SetupWindow();

To use it, position the cursor on the closing brace of the


SetupWindow function, then press F4 to run the program to that
point.

Whichever method you use, when TDW regains control, do the


following to set a window message breakpoint on the message
WM_COMMAND:

1. Choose Data I Inspect and inspect the window object


Main Window. Because it is now out of scope, you have to use
the following scope override syntax:
WinMain#MyApp.MainWindow

Chapter 75, Debugging an ObjectWindows application 231


Main Window is a member of My App because MyApp is of type
CScribbleApplication, which is derived from the class
TApplication, of which Main Window is a data member.
2. Zoom the Inspector window so you can see the data members
in the top pane. HWindow is the data member that holds the
window's handle.
3. Position the cursor on HWindow, then press Shift-F3 to copy it
into the Clipboard.
4. Choose View I Windows Messages to bring up the Windows
Messages dialog box.
5. Press Ctrl-A in the top left pane to display the Add dialog box.
Select the Handle button, then position the cursor in the text
entry box.
6. Press Shift-F4 to display the Clipboard. Put the cursor on
HWindow, select the Contents button (to copy the contents of
HWindow, the handle value), then choose OK to paste the
handle into the text entry box.
7. In the text entry box, append Ox to the front of the handle value
to indicate that it's a hexadecimal number, then press Enter.
8. Move to the top right pane and type WM_COMMAND. You'll see the
Set Message Filter dialog box appear as you begin typing.
9. Set the Action for this message to Break, then press Enterto set a
breakpoint on this message.

The program will now return control to TOW whenever you make
a menu selection, because doing so generates a WM_COMMAND
message.

Setting a window message breakpoint with a window object


If you've used TDWINST to enable ObjectWindows window
message breakpoint support, you can use the window object
Main Window to set the window message breakpoint.

1. Move the cursor to the closing brace of the InitMain Window


function and press F4 to run the program to that point.
2. When you see the Module window again, choose View I
Windows Messages to display the OWL Windows Messages
dialog box.
3. In the top left pane, type MainWindow and press Enter.

232 Turbo Debugger for Windows User's Guide


4. In the top right pane, type WM_COMMAND, choose the Action button
Break, then press Enter to set a breakpoint on this message.

The program will now return control to TOW whenever you make
a menu selection, because doing so generates a WM_COMMAND
message.

Inspecting wParam You can now resume execution of the program by pressing F9.
Choose Pen I Black Pen from the menu. Once you have selected a
black pen, TOW stops execution and displays the CPU Window,
indicating that the program was executing Windows kernel code at
the time the break occurred. Close the CPU window by pressing
Alt-F3.
If necessary, bring up the Windows Messages window again.
Zoom the window to full size so you can see the entire message in
the lower pane. You can see that the window received a
WM_COMMAND message with 204 (OxCC) in the wParam
parameter. But the constant CM_BLACK is 104, not 204. The reason
the virtual function was not getting called was that the application
was looking for an identifier of CM_FIRST+204, but its value was
actually CM_FIRST+104.
The value 204 was specified in the menu definition in the
TDODEMO.RC file. This error could have been avoided by using
the same identifiers for the menu as are in the header file and
putting an #INCLUDE statement for that header file at the start of
the .RC file. Instead, integers were used in this menu definition,
which left the responsibility for cross-checking the values to the
programmer.
If you edit TDODEMOB.H and change CM_BLACK to 204,
selecting a black pen should work correctly. When you've made
this change, the constant declarations in TDODEMOB.H will be as
follows:
#define PenWidth
#define MenuID 100
#define IconID 100
#define CM RED 101
#define CM GREEN 102
#define CM BLUE 103
#define CM_BLACK 204

Chapter 75, Debugging an ObjectWindows application 233


Testing the fix Run Color Scribble and exit it, then exit TOW. When you are back
in Turbo C++ for Windows, load the header file TDODEMOB.H,
change the CM_BLACK constant definition, then recompile the
project and run the program under TOW.
Now when you draw in the window, you might notice another
problem. If, as you're drawing, you move the mouse off the
window, then back onto the window at another location, you'll see
that the program has drawn a straight line connecting the point
where you left the window and the point where you came back on.
What the program should do is just stop drawing when you leave
the window and start drawing when you come back. You've
discovered yet another bug.

Finding the off-


screen drawing A place to start looking for this bug is in the window messages the
bug window receives. Get out of the Color Scribble program and load
TDODEMOB.CPP into TDW's Module window.

Logging the window Depending on whether or not you have ObjectWindows window
messages message support set, use one of the two methods described
starting on page 231 to initialize the window. Then indicate in the
Windows Messages window's top left pane (either by window
object or handle) which window to track messages for.
Next, move the cursor to the top right pane and add
WM_LBUTTONUP as a message breakpoint, to allow TOW to
regain control after you finish drawing.
You also want to look at all the messages that come back, but
setting WM_LBUTTONUP erased the Log All Messages setting. To
restore this setting, press Ctrl-A to display the Set Message Filter
dialog box, then select the Log All Messages class.

Discovering the bug Resume execution of TDODEMOB by pressing F9. Begin drawing,
then move the mouse off the client area, move it around a bit, and
then move it back on again at another place and release the left
mouse button so control returns to TOW.
Before looking at the Window Messages window, make sure to
zoom it to full size (press F5) so you can see more messages. When

234 Turbo Debugger for Windows User's Guide


you look in the lower pane of the Windows Messages window, you
see a lot of WM_NCHITEST and WM_SETCURSOR messages.
Scroll to the WM_LBUTTONDOWN message, which is where you
started drawing. After this message, you see a series of
WM_NCHITTEST, WM_SETCURSOR, and WM_MOUSEMOVE
messages, followed a series of WM_NCHITTEST,
WM_SETCURSOR, and WM_NCMOUSEMOVE messages,
followed by another series of WM MOUSEMOVE messages, and a
final WM_LBUTTONUP message.
A WM_MOUSEMOVE message happens only in the program's
client area. WM_NCMOUSEMOVE messages occur when the
mouse is moved off the program's client area.
Now it becomes clear what the bug is. The program draws from
the location of the last WM_MOUSEMOVE message to the location
of the current WM_MOUSEMOVE message. When the mouse exits
the client area, the program doesn't receive any
WM_MOUSEMOVE messages. Therefore, when the mouse returns
to the client area, the last location is where it left the screen, and
the program obediently draws a line from that location to the
current location.

Fixing the bug One possible solution would be to determine when the mouse is
off the client area, so the program can ignore the last mouse
position and begin drawing again when the mouse reenters the
client area. That would require some fancy logic to determine
when the mouse was leaving the client area of the window and
when it moves back over the client area. Fortunately, there is an
easier way.
The Windows function SetCapture does exactly what's needed.
This function tells Windows to send all mouse-related messages to
the specified window until the program calls ReleaseCapture, thus
causing the window to receive WM_MOUSEMOVE messages
when the mouse is off the client area instead of
WM_NCMOUSEMOVE messages.
If you put SetCapture in ScribbleWindow::WMLButtonDown and
ReleaseCapture in WMLButtonUp, WMMouseMove will actually
draw outside the window when the mouse is scribbling outside the
window. However, Windows will clip all the lines drawn outside
the client area, thus producing the desired effect.

Chapter 75, Debugging an ObjectWindows application 235


These changes are shown in the following code listing:
void ScribbleWindow::WMLButtonDown(RTMessage Msg)
{
if ( !ButtonDown )
{
ButtonDown ; TRUE; II Mark mouse button as being
II pressed so when mouse movement
II occurs, a line will be drawn.
SetCapture(HWindow); II Tell Windows to send all mouse
II messages to window. WMLButtonUp
II function will release the capture.
HandleDC; GetDC(HWindow);
II Create display context for drawing.
MoveTo(HandleDC, Msg.LP.Lo, Msg.LP.Hi);
II Move drawing point to location
II where mouse was pressed.
SelectObject(HandleDC, ThePen);
II Select pen into display context.

void ScribbleWindow::WMLButtonUp(RTMessage)
{
if ( ButtonDown )
{
ReleaseCapture();
ReleaseDC(HWindow, HandleDC);
ButtonDown ; FALSE;

Testing the fix Exit Color Scribble, then exit TDW. When you're back in Turbo
C++ for Windows, enter the changes to the two routines, then
recompile the program and run it. Now when you draw on the
window, everything works fine, but when you try to erase the
screen by using the right-hand mouse button, nothing happens.
You've found another bug.

Finding the
erase-screen bug Since WMRButtonDown is the function that handles the right-hand
mouse button, the bug probably has something to do with that
routine. Either WMRButtonDown isn't getting called, or there's a
bug in it.

236 Turbo Debugger for Windows User's Guide


Exit Color Scribble, then load TOOOEMOB into TOW. To execute
to WMRButtonDown, the function where the bug probably is, press
Alt-F9and type ScribbleWindow: :WMRButtonDown. Scribble a little in the
window, then press the right-hand mouse button. TOW stops the
program at the beginning of WMRButtonDown, so you know this
routine is getting called.
Using the F7key, step into WMRButtonDown and stop at the call to
UpdateWindow. (Don't press F7yet on this line) The only
parameter is HWindow. You can assume that HWindow has been set
correctly because other functions are using it successfully. Since
there's nothing obviously wrong, one thing you can do is test to see
if the WM_PAINT message that should be sent to the window by
the call to UpdateWindow is actually being received by the
window.
By now you probably know how to set a message breakpoint on
WM_PAINT. If not, review the description of how to set a message
breakpoint on page 231. In addition to setting a message
breakpoint on WM_PAINT, set the program to log WM_PAINT
messages. (In the Set Message Filter dialog box, add WM_PAINT
again, but this time select the Log button.)
After setting the message breakpoint, press F7 to execute the
UpdateWindow call. Since the program doesn't break and return,
WM_PAINT is never getting sent to the window.
You can verify that no WM_PAINT messages were received by
pressing the right-hand mouse button to return control to TOW at
WMRButtonDown, then checking the lower pane of the View I
Windows Messages dialog box. There are no WM_PAINT
messages there. For some reason, calling UpdateWindow isn't
working as expected.

Analyzing the cause of This bug requires a little understanding of how Windows handles
the bug the UpdateWindow function. When a program calls this function,
Windows checks to see if any part of the window is invalid and
needs repainting. If so, Windows sends a WM_PAINT message to
the window. If not, there's no reason to waste system resources
with an unnecessary message, so Windows does nothing. But how
does Windows know that the window needs updating?
An application notifies Windows that at least part of the Window
is invalid by calling either lnvalidateRect or lnvalidateRgn. These
two functions put an update area in the window and notify

Chapter 75, Debugging an ObjectWindows application 237


Windows that it should update the window with a WM_PAINT
message.
You could just replace the call to UpdateWlndow with a call to
lnvalidateRect. However, Windows assigns a low priority to the
WM_PAINT message it sends in response to either of these
function calls, so if you want to ensure that the window gets
updated immediately, you should retain the call to UpdateWindow.

Fixing the bug Adding a call to lnvalldateRect in WMRButtonDown will fix the
problem. lnvalidateRect takes three parameters, a window handle
that identifies the window, a pointer to a rectangle that marks the
rectangle to be added to the update rectangle, and a Boolean
parameter that specifies if the rectangle should be erased. You can
pass in NULL for the pointer to the rectangle, telling Windows that
the entire window should be added to the update rectangle. The
following code listing shows how WMRButtonDown should look
with the new function call added:
void ScribbleWindow::WMRButtonDown(RTMessage)
{
InvalidateRect(HWindow, NULL, TRUE);
UpdateWindow(HWindow);

Testing the fix Run Color Scribble and exit it, then exit TOW. When you are back
in Turbo C++ for Windows, enter the changes to
WMRButtonDown, then recompile the program and run it. Now
when you draw on the window, then press the right-hand mouse
button to erase it, the window does get erased. You've found all the
bugs, and the program now works perfectly.

238 Turbo Debugger for Windows User's Guide


A p p E N D x

Summary of command-line options


When you start up TDW from the Windows Program Manager
File I Run command, you can at the same time configure it using
certain options. Here's the general format to use:
tdw [options] [program_name [program_args]]
Items enclosed in brackets are optional. Following an option with
a hyphen disables that option if it was already enabled in the
configuration file.
Table Al
TDW command-line options Option What it means
-cfilename Startup configuration file
-do Other display
-ds Swap user screen contents
-h,-? Display help screen listing all the command-line
options
_, Assembler startup code debugging for
applications and DLLs (the letter in this option is
a lowercase L)
-p Enable mouse
-SC No case-checking of symbols
-sddir[;dir ... ] Source file directory
-tdirectory Set starting directory for loading configuration
and executable files

Appendix A Summary of command-line options 239


240 Turbo Debugger for Windows User's Guide
A p p E N D x

Error and information messages


TOW displays error messages and dialog boxes at the current
cursor location. This chapter describes the dialog boxes and error
and information messages TOW generates.
We tell you how to respond to both dialog box and error
messages. All the dialog box messages and error messages
(including the startup fatal error messages) are listed in
alphabetical order, with a description provided for each one.

Dialog box messages


TOW displays a dialog box when you must supply additional
information to complete a command. The title of the dialog box
describes the information that's needed. The contents may show a
history list (previous responses) that you have given.
You can respond to a dialog box in one of two ways:
• Enter a response and accept it by pressing Enter.
• Press Esc to cancel the dialog box and return to the menu
command that preceded the dialog box.
Some dialog boxes only present a choice between two items (like
Yes/No). You can use Tab to select the choice you want and then
press Enter, or press Yor N directly. Cancel the command by press-
ing Esc.

Appendix B, Error and information messages 241


For a more complete discussion of the keystroke commands to use
when a dialog box is active, refer to Chapter 2.
Here's an alphabetical list of all the messages generated by dialog
boxes:
Already recording, do you want to abort?
You are already recording a keystroke macro. You can't start
recording another keystroke macro until you finish the current
one. Press Y to stop recording the macro; N to continue
recording the macro.
Device error - Retry?
An error has occurred while writing to a character device,
such as the printer. This could be caused by the printer being
unplugged, offline, or out of paper. Correct the condition and
then press Y to retry or N to cancel the operation.
Disk error on drive _ - Retry?
A hardware error has occurred while accessing the indicated
drive. This may mean you don't have a floppy disk in the
drive or, in the case of a hard disk, it may indicate an
unreadable or unwriteable portion of the disk. You can press Y
to see if a retry will help; otherwise, press N to cancel the
operation.
Edit watch expression
Modify or replace the watch expression. The dialog box is
initialized to the currently highlighted watch expression.
Enter address, count, byte value
Enter the address of the block of memory you want to set to a
particular byte value, then a comma, then the number of bytes
you want to set, then another comma followed by the value to
fill the block with.
Enter address to position to
Enter the address you want to view in your program. You can
enter a function name, a line number, an absolute address, or a
memory pointer expression. See Chapter 9 for more on
entering addresses.
Enter animate delay {10ths of sec)
Specify how fast you want the Animate command to proceed.
The higher the number, the longer between successive steps
during animation.

242 Turbo Debugger for Windows User's Guide


Enter code address to execute to
Enter the address in your program where you want execution
to stop. See Chapter 9 for more information on entering
addresses.
Enter command-line arguments
Enter the command-line arguments for the program you're
debugging.
Enter comment to add to end of log
Enter an arbitrary line of text to add to the messages displayed
by the Log window. You can enter any text you want; it will
be placed in the log exactly as you type it.
Enter destination address for marked block
Enter the segment:offset or segment that you want to move the
marked block to.
Enter expression for conditional breakpoint
Enter an expression that must be true (nonzero) in order for
the breakpoint to be triggered. This expression will be
evaluated each time the breakpoint is encountered as your
program executes. Be careful about any side effects it may
have.
Enter expression to watch
Enter a variable name or expression whose value you want to
watch in the Watches window. If you want, you can enter an
expression that does not refer to a memory location, such as
x * y + 4). If the dialog box is initialized from a text pane, you
can accept the entry by pressing Enter, or change it and enter
something else entirely.
Enter inspect start Index, range
Enter the index of the first item in the array you want to view,
followed by the number of items you want to view. Separate
the two scalars by a space or a comma (,).
Enter instruction to assemble
Enter an assembler instruction to replace the one at the current
address in the Code pane. The file ASMDEBUG.TDW has a
condensed listing of all assembler keywords and discusses
assembly language in more detail.
Enter log file name
Enter the name of the file you want to write the log to. Until
you issue a Close Log File command, all lines sent to the log
will be written to the file, as well as displayed in the window.

Appendix 8, Effor and information messages 243


The default file name has the extension .LOG and is the same
file name as the program you are debugging. You can accept
this name by pressing Enter, or type a new name instead.
Enter memory address, count
Enter a memory address, followed by an optional comma and
the number of items you want to clear. You can use a symbol
name or a complete expression for the address.
Enter name of file to view
You can use DOS-style wildcards to get a list of file choices, or
you can type a specific file name to load.
Enter new bytes
Enter a byte list that will replace the bytes at the position in
the file marked by the cursor. See Chapter 9 for a complete
description of byte lists.
Enter new coprocessor register value
Enter a new value for the currently highlighted numeric
coprocessor register. You can enter a full expression to
generate the new value. The expression will be converted to
the correct floating-point format before being loaded into the
register.
Enter new data bytes
Enter a byte list to replace the bytes at the position in the
segment marked by the cursor. See Chapter 9 for a complete
description of byte lists.
Enter new directory
Enter the new drive or directory name that you want to
become the current drive and directory.
Enter new file offset
You are viewing a disk file as hexadecimal data bytes. Enter
the offset from the start of the file where you want to view the
data bytes. The file will be positioned at the line that contains
the offset you specified.
Enter new line number
Enter the line number you want to see in the current module.
If you enter a line number that is past the end of the file, you'll
see the last line in the file. Line numbers start at 1 for the first
line in the file. The current line number that the cursor is on is
shown as the first line of the Module window.

244 Turbo Debugger for Windows User's Guide


Enter new relocation segment value
Enter an expression in the current language. This value will be
used to set the base segment address of a symbol table that
you loaded with the File I Symbol Load command. The
expression that you enter should evaluate to the segment
number of the start of the code for which the symbol table
applies.
Enter new selector
Enter the selector value that you want to become current. You
can enter an actual sector hex value, or you can enter a
segment register value, such as CS, DS, or ES.
Enter new value
Enter a new value for the currently highlighted CPU register.
You can enter a full expression to form the new value.
Enter port number
Enter the 1/0 port number you want to read from; valid port
numbers are from 0 to 65,535.
Enter port number, value to output
Enter the 1/0 port number you want to write to, and the value
to write; separate the two expressions with a comma. Valid
port numbers are from 0 to 65,535.
Enter program name to load
Enter the name of a program to debug. You can use DOS
wildcards to get a list of file choices, or you can type a specific
file name to load. If you do not supply an extension to the file
name, .EXE will be appended.
Enter read file name
Enter a file name or a wildcard specification for the file you
want to read into memory. If you supply a wildcard specifi-
cation or accept the default*.*, a list of matching files will be
displayed for you to select from.
Enter search bytes
Enter a byte list to search for starting at the position in
memory marked by the cursor. See Chapter 9 for a complete
description of byte lists.
Enter search instruction or bytes
Enter an instruction, as you would for the Assemble local
menu command, or enter a byte list as you would for a Search
command in a Data pane.

Appendix 8, Error and information messages 245


Enter search string
Enter a character string to search for. You can use a simple
wildcard matching facility to specify an inexact search string;
for example, use * to match zero or more of any characters,
and ? to match any single character.
Enter source address, destination, count
Enter the address of the block you want to move, the number
of bytes to move, and the address you want to move them to.
Separate the three expressions with commas.
Enter source directory path
Enter a list of directories, separated by spaces or semicolons
(;).These directories will be searched, in the order that they
appear in this list, for your source files.
Enter symbol table name
Enter the name of a symbol table to load from disk. Usually
these files have an extension of .TDS. You must explicitly
supply the filename extension.
Enter value to fill marked block
Enter a byte value to be filled into the marked block.
Enter variable to inspect
Enter the name of a variable or expression whose contents you
want to examine. If the dialog box is initialized from a text
pane, you can accept the entry by pressing Enter or change it
and enter something else.
Enter write file name
Enter the name of the file you want to write the block of
memory to.
Overwrite ?
You have specified a file name to write to that already exists.
You can choose to overwrite the file, replacing its previous
contents, or you can cancel the command and leave the
previous file intact.
Overwrite existing macro on selected key
You have pressed a key to record a macro, and that key
already has a macro assigned to it. If you want to overwrite
the existing macro, press Y; otherwise, press Nto cancel the
command.

246 Turbo Debugger for Windows User's Guide


Pick a method name
You have specified a routine name that can refer to more than
one method in an object. Pick the correct one from the list
presented.
Pick a module
Select a module name to view in the Module window. You are
presented with a list of all the modules in your program. If
you want to view a file that is not a program module, use
View I File.
Pick a name
Pick a name from the list of displayed symbols. You can start
to type a name, and you will be positioned to the first symbol,
starting with what you have typed so far.
Pick a source file
Select a source file from the list displayed; only the source files
that make up the current module are shown.
Pick a window
Pick a window from the list of active window titles.
Pick macro to delete
Pick the key or key combination for the macro you want to
delete. The key will be returned to its original pre-macro
functionality.
Press key to assign macro to
Press the key that you want to assign the macro to. Then, press
the keys to do the command sequence that you want to assign
to the macro key. The command sequence will actually be per-
formed as you type it. To end the macro recording sequence,
press the key you assigned the macro to, or press Alt-.
Program already terminated, Reload?
You have attempted to run or step your program after it has
already terminated. If you choose Y, your program will be
reloaded. If you choose N, your program will not be reloaded,
and your run or step command will not be executed.
Reload program so arguments take effect?
You have just changed the command-line arguments for the
program you' re debugging. If you type Y, yqur program will
be reloaded and set back to the start. You usually want to do
this after changing the arguments because programs written in
many Borland languages only look at their arguments once--
just as the program is loaded. Any subsequent changes to the

Appendix B, Error and information messages 247


program arguments won't be noticed until the program is
restarted.

Error messages
TOW uses error messages to tell you about things you haven't
quite expected. Sometimes the command you have issued cannot
be processed. At other times the message warns that things didn't
go exactly as you wanted.
You can easily tell an error message from a prompt if you turn on
Error Message Beeps in TOINST.

Fatal errors
All fatal errors cause TOW to quit and return to Windows. Some
fatal errors are the result of trying to start TOW from the
command line. A few others occur if something fatal happens
while you are using the debugger. In either case, after having
solved the problem, your only remedy is to restart TOW.
Bad or missing configuration file
The configuration file is either corrupted or not a TOW
configuration file.
Invalid switch:
You supplied an invalid option switch on the command line.
Appendix A has an abbreviated list of all command-line
switches, and Chapter 4 discusses each one in detail.
Not enough memory
TOW ran out of working memory while loading.
Old configuration file
You have attempted to start TOW with a configuration file for
a previous version. You must create new configuration files for
this version of TOW.
Unsupported video adapter
TOW can't determine which display adapter you are using.
TOW supports EGA, VGA, Hercules, and Super-VGA.

248 Turbo Debugger for Windows User's Guide


Other error
messages ')' expected
While evaluating an expression, a right parenthesis was found
to be missing. This happens if a correctly formed expression
starts with a left parenthesis and does not end with a matching
right one. For example,
3 * (7 + 4

should have been


3 * (7 + 4)

':'expected
While evaluating a C expression, a question mark (?)
separating the first two expressions of the ternary?: operator
was encountered; however, no matching : (colon) to separate
the second and third expressions was found. For example,
x<0?46
should have been
x<0?4:6

']' expected
While evaluating an expression, a left bracket ([) starting an
array index expression was encountered without a matching
right bracket (]) to end the index expression. For example,
table[4

should have been


table[4]

This error can also occur when entering an assembler


instruction using the built-in assembler. In this case, a left
bracket was encountered that introduced a base or index
register memory access, and there was no corresponding right
bracket. For example,
mov ax,4[si

should have been


mov ax,4[si]

Appendix 8, Error and information messages 249


Already logging to a file
You issued an Open Log File command after having already
issued the same command without an intervening Close Log
File command. If you want to log to a different file, first close
the current log by issuing the Close Log File command.
Ambiguous symbol name
You have entered a symbol name in an expression that does
not uniquely identify a member function, and you have
chosen not to pick the correct symbol from a list. You must
pick the proper symbol from the list presented before your
expression can be evaluated.
Bad or missing configuration file name
You have specified a nonexistent file name with the -c
command-line option.
Cannot access an inactive scope
You entered an expression or pointed to a variable in a
Module window that is not in an active function. Variables in
inactive functions do not have a defined value, so you can't
use them in expressions or look at their values.
Cannot be changed
You tried to change a symbol that can't be changed. The only
symbols that can be changed directly are scalars (int, long, and
so forth) and pointers. If you want to change a structure or
array, you must change individual elements one at a time.
Can't have more than one segment override
You attempted to assemble an instruction where both
operands have a segment override. Only one operand can
have a segment override. For example,
mov es: [bx], ds: 1

should have been one of the following:


mov es: [bx], 1

or
mov ax, [1]
mov es: [bx], ax

Can't set a breakpoint at this location


You tried to set a breakpoint in ROM, nonexistent memory, or
in segment 0. The only way to view a program executing in

250 Turbo Debugger for Windows User's Guide


ROM is to use the Run I Trace Into command to watch it one
instruction at a time.
Can't set any more hardware breakpoints
You can't set another hardware breakpoint without first
deleting one you have already set. Different hardware
debuggers support different numbers and types of hardware
breakpoints.
Can't set hardware condition on this breakpoint
You've attempted to set a hardware condition on a breakpoint
that isn't a global breakpoint. Hardware conditions can only
be set on global breakpoints.
Can't set that sort of hardware breakpoint
The hardware device driver that you have installed in your
CONFIG.SYS file can't do a hardware breakpoint with the
combination of cycle type, address match, and data match that
you have specified.
Constructors and destructors cannot be called
This error message appears only if you are debugging a
program that uses objects. You probably tried to evaluate a
member function that's either a constructor or a destructor.
This is not allowed.
Count value too large
In the Data pane of the CPU window, you've entered too large
a block length to one of the local menu Block commands. The
block length can't exceed FFFFFh.
Ctrl-Alt-SysRq interrupt. System crash possible. Continue?
You attempted either to exit TOW or to reload your appli-
cation program while the program was suspended as a result
of your having pressed Ctrl-Alt-SysRq. Because Windows kernel
code was executing at the time you suspended the application,
exiting TOW or reloading the application will have
unpredictable results (most likely hanging the system and
forcing a reboot).
If possible, set a breakpoint in your code that will cause your
program to exit to TOW, and then run your program again.
When your program encounters the breakpoint and exits to
TOW, you can terminate TOW or reload your program.
Destination too far away
You attempted to assemble a conditional jump instruction
where the target address is too far from the current address.

Appendix B, Error and information messages 251


The target for a conditional jump instruction must be within
-128 and 127 bytes of the instruction itself.
Divide by zero
You entered an expression using the divide(/, div) or modulus
operators (mod, %) that had on its right side an expression that
evaluated to zero. Since the divide and modulus operators do
not have defined values in this case, an error message is
issued.
DLL already in list
In the View I Modules dialog box, you tried to add a OLL to the
OLLs & Programs list, but the OLL was already in the list.
Error opening file_
TOW couldn't open the file that you want to look at in the File
window. The file might not exist or might be in another
directory.
Error opening log file_
The file name you supplied for the Open Log File local menu
command can't be opened. Either there is not enough room to
create the file, or the disk, directory path, or file name you
specified is invalid. Either make room for the file by deleting
some files from your disk, or supply a correct disk, path, and
file name.
Error reading block into memory
The block you specified could not be read from the file into
memory. You probably specified a byte count that exceeded
the number of bytes in the file.
Error saving configuration
TOW could not write your configuration to disk. Make sure
that there is some free space on your disk.
Error writing block to disk
The block that you specified could not be written to the file
that you specified. You probably specified a count that
exceeded the amount of free file space available on the disk.
Error writing log file_
An error occurred while writing to the log file collecting the
output from the log window. Your disk is probably full.

252 Turbo Debugger for Windows User's Guide


Error writing to file
TOW could not write your changes back to the file. The file
might be marked as read-only, or a hard error may have
occurred while writing to disk.
Expression too complex
The expression you supplied is too complicated; you must
supply an expression that has fewer operators and operands.
You can ha~.re up to 64 operators and operands in an expres-
sion. Examples of operands are constants and variable names.
Examples of operators are plus(+), assignment(=), and
structure member selection(->).
Expression with side effects not permitted
You have entered an expression that modifies a memory
location when it gets evaluated. You can't enter this type of
expression whenever TOW might need to repeatedly evaluate
an expression, such as when it is in an Inspector window or
Watches window.
Extra input after expression
You entered an expression that was valid, but there was more
text after the valid expression. This sometimes indicates that
you omitted an operator in your expression. For example,
3 * 4 +5 2
should have been
3 *4+s I 2
Another example,
add ax,4 5
should have been
add ax,45
You could also have entered a number in the wrong syntax for
the language you are using, for example, OxFOOO instead of
OFOOOh when you are in assembler mode.
Help file_ not found
You asked for help but the disk file that contains the help
screens could not be found. Make sure that the help file is in
the same directory as the debugger program.

Appendix 8, Error and information messages 253


Immediate operand out of range
You entered an instruction that had a byte-sized operand com-
bined with an immediate operand that is too large to fit in a
byte. For example,
add BYTE PTR[bx],300
should have been
add WORD PTR[bx],300
Initialization not complete
You have attempted to access a variable in your program
before the data segment has been set up properly by the
compiler's initialization code. You must let the compiler
initialization code execute to the start of your source code
before you can access most program variables.
The expression you entered contains a function call that does
not have a correctly formed argument list. An argument list
starts with a left parenthesis, has zero or more comma-
separated expressions for arguments, and ends with a right
parenthesis.
Invalid character constant
The expression you entered contains a badly formed character
constant. A character constant consists of a single quote
character (') followed by a single character, ending with
another single quote character. For example,
'A= 'a'
should have been
'A' = 'a'
Invalid format string
You have entered a format control string after an expression,
but it is not a valid format control string. See Chapter 9 for a
description of format strings.
Invalid function parameter(s)
You have attempted to call a routine in an expression, but you
have not supplied the proper parameters to the call.
Invalid instruction
You entered an instruction to assemble that had a valid
instruction mnemonic, but the operand you supplied is not

254 Turbo Debugger for Windows User's Guide


allowed. This usually happens if you attempt to assemble a
POP CS instruction.
Invalid Instruction mnemonic
When entering an instruction to be assembled, you failed to
supply an instruction mnemonic. An instruction consists of an
instruction mnemonic followed by optional arguments. For
example,
AX,123
should have been
MOV ax,123
Invalid number entered
In a File window or a Module window, you typed an invalid
number to go to (using the Goto command). Numbers must be
greater than zero and in decimal format.
Invalid operand(s)
The instruction you're trying to assemble has one or more
operands that aren't allowed. For example, a MOV instruction
cannot have two operands that reference memory, and some
instructions only work on word-sized operands. For example,
POP al

should have been


POP ax

Invalid operator/data combination


You've entered an expression where an operator has been
given an operand that can't have the selected operation
performed on it. For example, you attempt to multiply a
constant by the address of a function in your program.
Invalid pass count entered
You have entered a breakpoint pass count that is not between
1and65,535. You can't set a pass count of 0. While your code
is running, a pass count of 1 means that the breakpoint is
eligible to be triggered the first time it is encountered.
Invalid register
You entered an invalid floating-point register as part of an
instruction being assembled. A floating-point register consists
of the letters ST, optionally followed by a number between 0
and 7 within parentheses; for example, ST or ST(4).

Appendix B, Effor and information messages 255


Invalid register combination In address expression
When entering an instruction to assemble, you supplied an
operand that did not contain one of the permitted
combinations of base and index registers. An address
expression can contain a base register, an index register, or one
of each. The base registers are BX and BP, and the index
registers are SI and DI. Here are the valid address register
combinations:
BX BX+SI
BP BP+SI
DI BX+DI
SI BP+DI
Invalid register in address expression
You entered an instruction to assemble that tried to use an
invalid register as part of a memory address expression
between brackets([]). You can only use the BX, BP, SI, and DI
registers in address expressions.
Invalid symbol In operand
When entering an instruction to assemble, you started an
operand with a character that can never be used to start an
operand: for example, the colon (:).
Invalid type cast
A correct C cast starts with a left parenthesis, contains a possibly
complex data type declaration (excluding the variable name), and
ends with a right parenthesis. For example,
(x *)p

should have been


(struct x *)p
Invalid value entered
When prompted to enter a memory address, you supplied a
floating-point value instead of an integer value.
Keyword not a symbol
The expression you entered contains a keyword where a
variable name was expected. You can only use keywords as
part of typecast operations, with the exception of the slzeof
special operator. For example,
floatval = char charval

256 Turbo Debugger for Windows User's Guide


should have been
floatval = char (charval)
Left side not a record, structure, or union
You entered an expression that used one of the C structure
member selectors (. or->). This symbol, however, was not
preceded by a structure name, nor was it preceded by a
pointer to a structure.
No coprocessor or emulator installed
You tried to create a Numeric Processor window using the
View I Numeric Processor command, but there is no numeric
processor chip installed on your system, and the program
you're debugging either doesn't use the software emulator or
the emulator has not been initialized.
No hardware debugging available
You have tried to set a breakpoint that requires hardware
debugging support, but you don't have a hardware debugging
device driver installed. You can also get this error if your
hardware debugging device driver does not find the hardware
it needs.
No help for this context
You pressed Ft to get help, but TOW could not find a relevant
help screen. Please report this to Borland technical support.
No modules have line number information
You have used the View I Module command, but TOW can't
find any modules with enough debug information in them to
let you look at any source modules. This message usually
happens when you're debugging a program without a symbol
table. See the "Program has no symbol table" error message
entry on page 260 for more information on symbol tables.
No previous search expression
You attempted to perform a Next command from the local
menu of a text pane, but you had not previously issued a
Search command to specify what to search for. You can only
use Next after issuing a Search command in a pane.
No program loaded
You attempted to issue a command that requires a program to
be loaded. There are many commands that can only be issued
when a program is loaded. For example, none of the com-
mands in the Run menu can be performed without having a

Appendix B, Error and information messages 257


program loaded. Use the File IOpen command to load a pro-
gram before issuing these commands.
No type information for this symbol
You entered an expression that contains a program variable
name without debug information attached to it. This can
happen when the variable is in a module compiled without the
correct debug information being generated. You can supply
type information by preceding the variable nar..:e with a
typecast expression to indicate its data type.
Not a function name
You entered an expression that contains a call to a routine, but
the name preceding the left parenthesis introducing the call is
not the name of a routine. Any time a parenthesis immediately
follows a name, the expression parser presumes that you
intend it to be a call to a routine.
Not a record, structure, or union member
You entered an expression that used one of the C structure
member selectors (. or->). This symbol, however, was not
preceded by a structure name, nor was it preceded by a
pointer to a structure.
Not enough memory for selected operation
You issued a command that needed to create a window, but
there is not enough memory left for the new window. You
must first remove or reduce the size of some of your windows
before you can reissue the command.
Not enough memory to load program
Your program's symbol table has been successfully loaded into
memory, but there is not enough memory left to load your
program.
Not enough memory to load symbol table
There is not enough room to load your program's symbol table
into memory. The symbol table contains the information that
TOW uses when showing you your source code and program
variables. If you have any resident utilities consuming
memory, you might want to remove them and then restart
TOW. You can also try making the symbol table smaller by
having the compiler only generate debug information for
those modules you are interested in debugging.
When this message is issued, you must free enough memory
to load both your program and its symbol table. If you're

258 Turbo Debugger for Windows User's Guide


debugging a TSR program that's already loaded, then you
must start Turbo Debugger using the -sm command-line
option to reserve memory for the program's symbol table.
Only one operand size allowed
You entered an instruction to assemble that had more than one
size indicator. Once you have set the size of an operand, you
can't change it. For example,
mov WORD PTR BYTE PTR[bx],1
should have been
mov BYTE PTR[bx],1
Operand must be memory location
You entered an expression that contained a subexpression that
should have referenced a memory location but did not. Some
things that must reference memory include the assignment
operator and the increment and decrement(++ and - -)
operators.
Operand size unknown
You entered an instruction to assemble, but did not specify the
size of the operand. Some instructions that can act on bytes or
words require you to specify which size to use if it cannot be
deduced from the operands. For example,
add [bx],1
should have been
add BYTE PTR[bx],1
Path not found
You entered a drive and directory combination that does not
exist. Check that you have specified the correct drive and that
the directory path is spelled correctly.
Path or file not found
You specified a nonexistent or invalid file name or path when
prompted for a file name to load. If you do not know the exact
nalt\e of the file you want to load, you can pick the file name
from a list by pressing Enter when the dialog box first appears.
The names in the list that end with a backslash (\) are
directories, letting you move up and down the directory tree
through the lists.

Appendix 8, Error and information messages 259


Program has Invalid symbol table
The symbol table attached to the end of your program has
become corrupted. Re-create an .EXE file and reload it.
Program has no objects or classes
You've attempted to open a View I Hierarchy window on a
program that isn't object-oriented.
Program has no symbol table
The program you want to debug has been successfully loaded,
but it doesn't contain any debug symbol information. You'll
still be able to step through the program using a CPU window
to examine raw data, but you won't be able to refer to any
code or data by name.
Program linked with wrong linker version
You are attempting to debug a program with out-of-date
debug information. Relink your program using the latest
version of the 9linker or recompile it with the latest version of
the compiler.
See page 57 for a description of how to compile your program
with debugging information.
Program not found
The program name you specified does not exist. Either supply
the correct name or pick the program name from the file list.
Register cannot be used with this operator
You have entered an instruction to assemble that attempts to
use a base or index register as a negative displacement. You
can only use base and index registers as positive offsets. For
example,
INC WORD PTR[12-BX]
should have been
INC WORD PTR[l2+BX]
Register or displacement expected
You have entered an instruction to assemble that has a badly
formed expression between brackets ([]).You can only put
register names or constant displacement values between the
brackets that form a base-indexed operand.
Run out of space for keystroke macros
The macro you are recording has run out of space. You can
record up to 256 keystrokes for all macros.

260 Turbo Debugger for Windows User's Guide


Search expression not found
The text or bytes that you specified could not be found. The
search starts at the current location in the file, as indicated by
the cursor, and proceeds forward. If you want to search the
entire file, press Ctrl-PgUp before issuing the search command.
Source file not found
TOW can't find the source file for the module you want to
examine Beforp issuing this message. it has looked in several
places:
•where the compiler found it
•in the directories specified by the -sd command-line option
and the Options I Path for Source command
• in the current directory
•in the directory where TOW found the program you're de-
bugging
You should add the directory that contains the source file to
the directory search list by choosing Options I Path for Source.
Symbol not found
You entered an expression that contains an invalid variable
name. You might have mistyped the variable name, or it might
be in some procedure or function other than the active one or
out of scope in a different module.
Symbol table file not found
The symbol table file that you have specified does not exist.
You can specify either a .TOS or .EXE file for the symbol file.
Syntax error
You entered an expression in the wrong format. This is a
general error message when a more specific message is not
applicable.
Too many files match wildcard mask
You specified a wildcard file mask that included more than
100 files. Only the first 100 file names will be displayed.
Unexpected end of line
While evaluating an expression, the end of your expression
was encountered before a valid expression was recognized.
For example,
99 - 22 *

Appendix B, Error and information messages 261


should have been
99 - 22 *4
And this example,
SUB AX,
should have been
SUB AX,4
Unknown character
You have entered an expression that contains a character that
can never be used in an expression, such as a reverse single
quote(').
Unknown record, structure, or union name
You have entered an expression that contains a typecast with
an unknown record or enum. name. (Note that assembler
structures have their own name space different from
variables.)
Uoknown symbol
You entered an expression that contained an invalid local
variable name. Either the module name is invalid, or the local
symbol name or line number is incorrect.
Unterminated string
You entered a string that did not end with a closirig quote(").
To enter a string with quote characters, you must precede each
quote with a backslash (\) character.
Value must be between nn and nn
You have entered an invalid numeric value for an editor
setting (such as the tab width) or printer setting (such as the
number of lines per page). The error message will tell you the
allowed range of numbers.
Variable not available
Your program's code has been optimized, and the variable
you're looking for can no longer be accessed.
Video mode not available
You have attempted to switch to 43/50-line mode, but your
display adapter does not support this mode; you can only use
43/50-line mode on an EGA or VGA.

262 Turbo Debugger for Windows User's Gulde


N D E x

..,..,,,,, mcrr1ory Sec rrlcmory, addresses


in Variables window 71 running to specified 127
in Watches window 93 problems with 79
:: (double colon) operator 143, 145 scope override for, C and C++ 134
-? option (help) 61 symbol tables, base segment 245
= (System) menu 187 Alt-key shortcuts See hot keys
activating 19 Always option
80x87 coprocessors See numeric coprocessors breakpoints condition 112
80x86 processors display swapping 65
debugging, breakpoints 112 ancestor and descendant relationships 151
type, in CPU window 179 ancestor classes 156
80386 processor Animate command 80, 242
debugging, Windows applications 13 Another command 30
hardware debugging registers 13 arguments 3, See also parameters
registers 141 calling function 27
command-line options 59, 247
A changing 86
setting 81, 86
accuracy testing 215
Arguments command 86
action
arrays
breakpoints 104
changing 250
sets of and breakpoints 115
indexes 243
active window 31
inspecting 22, 31, See also Inspector windows
returning to 20
C tutorial 51
activity indicators 40
subranges of 97, 99, 101
adapters See graphics adapters; video adapters
quoted character strings and 148
Add command
watching 92, See also Watches window
breakpoints 106, 116
arrow keys See also keys
window messages
history lists and 24
message classes 162
Inspector windows and 52
window object 161
menu commands and 19
window selection 159
radio buttons and 21
Add Comment command (log) 121, 122
resizing windows with 35
Add Watch command 91
ASCII
Add Window dialog box
files 201
ObjectWindows application 162
display option for 130
standard Windows application 159
searching 129
addresses 133
text, viewing files as 128, 129
instructions, disassembled 180
ASMDEBUG.TDW file 10

Index 263
assembler See also inline assembler bottom line See reference line
built-in 178, See also Code pane boundary errors 211
problems with 249 testing for 216
code29 Break option (breakpoints) 113
tracking 30 Breakpoint Detail pane 106
data, formatting 183 Breakpoint List pane 106
inline, keywords breakpoints 26, 103-113, See also Breakpoints
problems with 256 window
instructions See also instructions actions 104, 113
back tracing and unexpected side effects 83 setsof 115
breakpoints and 107 At command 105
executing single 78, 79 Boolean 112
execution history and 83 Changed Memory 117
multiple, treated as single 79 Changed Memory Global command 105
recording 83 condition sets 114
watching 28, See also CPU window conditional 118
memory dumps 183, 184 conditions for triggering 103, 112
mode, starting TDW in 62 adding actions 111
registers See CPU, registers customizing 111, 116
stack See Stack window defined 103
symbols 180 Delete All command 105
Assembler option (language convention) 132 disabling/ enabling 110
assembly code, debugging 10 Expression True Global command 105
assignment operators See also operators Get Info message about 76
language-specific 72, 94 global 110, 116
Turbo C++ for Windows 143 memory variables and 117
expressions with side effects and 90, 144 where occurred in program 77
At command (breakpoints) 105, 116 groups
Add command 108
B defined 107
delete 109
Back Trace command 80
disable 109, 113
backward trace 17, 83, See also Back Trace
enable 109, 113
command; reversing program execution
Group ID text box 110
assembler instructions 83
List dialog box 108
interrupts and 82
hardware 112, 118
binary operators See also operators
hardware-assisted
Turbo C++ for Windows 143
device drivers and 117, 251
bits 178
problems with 251, 257
blinking cursor 34
Hardware Breakpoint command 105
blocks
inspecting 107
memory See memory, blocks
local variables 118
moving246
location 103
reading from, problems with 252
logging values 119
writing to files, problems with 252
pass counts 104, 118, See also pass counts
books, reference 7
setting 115
Borland, contacting 5
reloading programs and 85
Both option (integer display) 66

264 Turbo Debugger for Windows User's Guide


removing 104, 107 pen color 233
running programs to 50 screen clearing 238
saving 110 SelectBlackPen function 233
scope 118 WMLButtonDown function 229, 235
setting 104 WMRButtonDown function 238
in module files 118 incremental testing 209
problems with 250, 251 returning information on 75
tutorial 49 built-in assembler 178
simple 116 built-in syntax checker 16
templates and 119 bullets ( •)
Toggle command 105 Result box and 89
using 221 Watches window and 92
with demo programs 219 buttons 21, 38, See also dialog boxes
viewing 106 Help 21
window messages radio See radio buttons
Get Info message about 76 byte lists
setting 164 entering 129, 139
TDODEM0230 language syntax 140
Breakpoints command 105 bytes 178, 180
Breakpoints menu 104, 189 formatting 183
Breakpoints window 26, 105-107 hexadecimal, viewing files as 128
local menu 106, 191 memory blocks
opening 105 setting, responding to prompt 242
panes 106 raw data 244
bugs 15-16,207,209-211 examining 94
accuracy testing 215 searching for 261
boundary errors 211 watching 28
testing for 216
C-specific 211-215
finding 16, 81, 207-208
c
C++
backward trace and 80
arrays 53
demo programs
code, tracing into 48
TDODEMOB 223-238
compound data types 53
execution history and 82
data, types 51
history lists and 120
demo programs 48
interrupting programs and 83
EasyWin module 43
in subroutines 210
expressions, entering in dialog boxes 54
TOODEMO
functions 48, 49
SelectBlackPen function 230
returning from 48
stack trace 227
tracing into 48
WMLButtonDown function 234
variables
WMMouseMove function 227
inspecting 51
WMRButtonDown function 236
return values 53
fixing
watching 50
TOODEMOB
C++ expressions, problems with 250
line drawing 229
C ++ programs
off-screen drawing 235
class instances, formatting 89

Index 265
class member functions 74 raw 148
debugging, this parameter and 89 value of 95
multiple inheritance 151 check boxes 21, See also dialog boxes
stepping through 79 Breakpoint Disabled 110
tracing into 78 Save Configuration 67
-c option (load configuration file) 61 Class List pane 150
problems with 250 local menu 150
C programming language See Turbo C Class pane, local menu 197
calculator 91 classes, nested, scope of 137
calculator, using Watches window as 131 clearing a window, TDODEMO program 237
capturing WM_MOUSEMOVE messages 235 Clipboard 36
case sensitivity, overriding 62 local menu commands 39
casting See type conversion tips for using 40
central processing unit See CPU watching expressions 39
CGA See graphics adapters; video adapters Clipboard window
Change command local menu 196
Data Member pane local menu 155 clipping items from windows 36
Global pane local menu 72 close box 33
Inspector window local menu 101 Close command 31, 36, 101
Static pane local menu 72 Close Log File command 122
Watches window local menu 94 code See also specific language application
Change dialog box breakpoints and 107, 110, 118
global symbols and 72 checking onscreen 30
local symbols and 72 current segment See programs, current
Changed Memory Global command location
(breakpoints) 105 debugging See debugging
Changed Memory option (breakpoints) 112 disassembled, problems with 71
character constants 254 editing 123-124
character devices, problems with 242 exit, returned to Windows 77
character strings inspecting 82, See also Inspector windows
null-terminated 95, 99 splicing in (breakpoints) 113
quoted 129 stepping through 79, See also Step Over
arrays as 148 command
problems with 262 tracing into 78, See also Trace Into command
searching for execution history and 81
File window, in 129 viewing 178
Module window, in 126 execution history and 29
responding to prompt 246 in multiple files 126, 130
searching for next watching See also Watches window
File window, in 130 in slow motion 80
Module window, in 127 Code pane
Turbo C++ for Windows 142 current program location 180
characters disassembler and 180
display (ASCII vs. hex) 130 immediate operands and 180
escape (Turbo C++ for Windows) 142 instruction addresses 180
invalid 262 local menu 191
problems with scalar variables and 95 color graphics adapters See graphics adapters

266 Turbo Debugger for Windows User's Guide


color monitors See monitors constants
.COM files, debugging 11 Inspector windows and 94
command-line options See also specific switch problems with 254
arguments 247 Turbo Assembler 146
changing 86 Turbo C++ for Windows 142
setting 81, 86 constructors 90
disabling 60 problems with 251
entering 59 context-sensitivity 21, 22
setting in TCW 59 help40-42
summary of 239 continuous trace 80
syntax 58 control-key shortcuts See hot keys; keys
help with 61 Control pane, local menu 197
TDW utilities 11 conversion See type conversion
commands 22, See also specific menu command coprocessors See 80x87 coprocessors; numeric
assigning as macros 64 coprocessors
choosing 19 copying and pasting 36
active windows and 31 CPU See also CPU window
dialog boxes and 241 flags
escaping out of 20 state of 181
hot keys and menu 20 viewing 29, 184
local menu 24 memory, displaying 181
summary of 185-205 memory dump 183
onscreen 41, 42 registers 140
comments 80386 processor 141
adding to history lists 121 compound data types and 91
adding to log 243 optimization with 52
compiler directives, files and 123 viewing 29, 184
compiling demo programs, TDODEMO 229 state, examining 28, 178
complex data objects 92 CPU command 94, 178
complex data types 87 CPU window 28
compound data objects 91 cursor in 179
inspecting 93 disassembled code and 71
condition sets (breakpoints) 114 opening 178
conditional breakpoints See breakpoints automatic 28
conditions See also breakpoints panes28
controlling (breakpoints) 118 processor type in 179
CONFIG.SYS See configuration files program execution and 78-83
configuration files 63 Create command 64
changing default name 67 CScribbleApplication object (TOODEMO) 226
directory paths 62 Ctrl-Alt-SysRq (program interrupt key) 83
loading 61 Program Reset command, and 84, 234
overriding 61, 63 TDDEBUG.386, need for 12
problems with 248, 250 current activity, help with 40
saving current code segment See programs, current
options to 66 location
problems with 252 cursor 34
TDCONFIG.TDW 36, 61, 63 CPU window 179

Index 267
running programs to 78 Data pane
tutorial 48 local menu 192
cursor-movement keys See keys memory addresses in 183
customer assistance 5 Debug Information command 57
customizing TOW 63, 64 debugging 15-19, 177, See also programs,
debugging
D assembly code 10
.COM files 11
data 88-91, See also Data pane
continuous trace 80
accessing 132 control 69-86, 133
bashing, global breakpoints and 116
memory use and 75
formatting 89
returning to TOW 78, 84
input216, 217
defined 15
inspecting 8 7-102, See also Inspector demo programs See demo programs
windows
dynamic link libraries 169
in recursive functions 74
startup code 173
manipulating 29
features 1, 18
modifying 54 functions 144
objects
recursive 74
complex 92 message logs and 27
compound 91, 93
multi-language programs 10
inspecting 88, 184 multiple components 53
pointing at 91
object-oriented programs See object-oriented
watching 92
programs, debugging
raw ObjectWindows programs 223
displaying 183 required files 2
examining 94 restrictions 16
inspecting 184 routines 123, 210
viewing 28, 184, 244 recursive 71
structures, inspecting 22, 156 sessions 69
testing, invalid input and 216 preparing programs for 57-67, 216
truncated 89
starting 85
types 87
simple programs 209
complex 87 source files and 2
converting See type conversion
steps 15
inspecting 31, 94-100
strategies 218
problems with 71, 89, 147
terminology 3
tracking 117
tips
variables and 258
DLL Startup buttons 172
values 216 Load Symbols reset 172
setting breakpoints for 117 window messages 165
viewing 178
tools 17
in recursive routines 71
tutorial 43
incorrect values shown 77
Helpwith45
watching See Watches window TOODEMOB 227-238
Data Member pane 152 variables 210
local menu 153, 155
uninitialized 210
Data menu 88-91, 189

268 Turbo Debugger for Windows User's Guide


Windows programs Conditions and Actions (breakpoints) 111
features list 157 Display Options 65
user interface 157 Edit Breakpoint Groups 108
decimal numbers 66 escaping out of 241
integers displayed as 148 Evaluate/Modify 89, 131, 220
Decimal option (integer display) 66 Expression Language 132
default settings Hardware Breakpoint Options 112
overriding 63 icons 19
restoring 67 Load Program 85
Delete All command messages 241-248
Breakpoints window local menu 107 moving around in 21
Macros menu 65 responding to 241
Watches window local menu 93 Save Options 67
window messages search 126, 129
message classes 164 Watch 72
Windows Messages window directories
window proc 162 paths
Delete All command (breakpoints) 105 for source 3
demo programs 43 multiple 62
C++48 problems with 259
compiling and linking setting 62, 66, 246
TDODEM0229 starting directory, changing 63
Help with 45 disassembled instructions 180
reloading 44 disassembler 180
source file 43 disk drives, accessing, problems with 242
starting 218 disks
TDDEM044 distribution 9
TDODEM0223 files on See files, disk
IDODEMOB 227-238 writing to, problems with 253
Turbo C++ for Windows 217 display
derived class relationships 150 formats
Descend command expressions 147
Data Member pane local menu 156 integers 66
Inspector window local menu 101 modes
descendant relationships 150, 151 defaults, setting 65
destructors 90 problems with 262
problems with 251 options, saving 36
device drivers output 65
breakpoints and 117 problems with 36
problems with 257 swapping 65
dialog boxes 20-21 Display As command
Add Group 108 Data pane local menu 183
bottom line in 42 File window local menu 130
Breakpoint Options 106, 109 Display Options command 65
Change 72 Display Options dialog box 65
closing 67 Display Swapping radio buttons 65
commands and 241 Display Windows Info command 122, 166, 195

Index 269
distribution disks 9 errors
copying 9 boundary See boundary errors
DLL See dynamic link libraries Exception 13 77
-do option (run on secondary display) 61 fatal 248
DOS messages 248-262
versions 75 escape sequences, Turbo C++ for Windows 142
wildcards, choosing files and 127 Evaluate input box 89
double colon(::) operator 143, 145 Evaluate/Modify command 88-91, 131
drawing, cursor off-screen, with TDODEMOB Evaluate/Modify dialog box 89, 131
235 using220
drives See disk drives Exception 13 error message 77, 227
-ds option (swap screens) 61 exception codes 77
Dump Pane to Log command 121 13 77
Dump window 28, 184 executable program files See files
local menu 194 Execute option (breakpoints) 113
duplicate windows, opening 30 Execute To command 79
Dynamic Link Libraries execution history 81
expressions, accessing 138 backward trace and 82
scope considerations 138 deleting 82
dynamic link libraries losing 83
debugging 169 recovering 83
startup code 173 Execution History command 82
reverse execution, and 80 Execution History window 29
dynamic virtual member functions 223 opening 82
exit code, returned to Windows 77
E exiting, TOW 67
exiting, TOW, tutorial 44
EasyWin module 43
expanded memory specification See EMS
Edit command, Watches window local menu 93
Expression Language dialog box 132
Edit menu 188
Expression True Global command (breakpoints)
editing
105
expressions 93
Expression True option (breakpoints) 112
history lists 24
expressions 131-148
EGA See also graphics adapters; video adapters
Clipboard, watching in 39
line display 66
complex 88
EMS
editing 93
execution history and 82
entering, problems with
information about 75
character constants 254
end of lines, problems with 261
inactive scope 250
Enhanced Graphics Adapters See EGA
invalid characters 262
Enter Program Name to Load dialog box 85
invalid variables 261, 262
Erase Log command
memory areas 259
Log window local menu 122
no record name for field 257, 258
Windows Messages window 165
not routine name 258
Erase Log File command 122
operators 252, 253, 255
erasing a window, TDODEMO program 237
too complex 253
evaluating 88-91, 220

270 Turbo Debugger for Windows User's Guide


implied scope 139 required for debugging 2
language conventions 132 FILELIST.DOC 9
problems with HELPME!.TDW 10
end of line 261 include 123
no right bracket 249 INSTALL.EXE 9
no right parenthesis 249 list boxes and 26
scope 139 loading See files, opening
side effects 253 log 243
formatting 147 problems with 250, 252
problems with 254 MANUAL.TDW 10
inspecting 31, 88, 102, 246, See also Inspector modifying, byte lists and 139
windows moving to specific line number in 126, 129
language options 132 multiple, viewing 126, 130
pointing at 91 opening 85, 127, 244
return values 92, 131 problems with 252
scope override nonexistent drive and directory 259
CandC++ 134 nonexistent or invalid name 259
Pascal 137 wildcard masks and 261
syntax overriding 132
Turbo Assembler 146-147 overwriting 246
Turbo C ++ for Windows 140-146 program module
undefined 93 loading a new module 126
updating 93 setting breakpoints in other 118
watching 91, 243, See also Watches window viewing 123
format specifiers and 89 README 10
with side effects (C programs) 90, 144 searching for 204
searching through
F File window, in 129
Module window, in 126
fatal errors 248
source See source files
features, version 3.0 1
TDCONFIG.TDW 36, 61, 63
File command
TDDEBUG.386 12
File window local menu 130
TDDEMO.C43
Module window local menu 126
TDDEMO.EXE 222
View menu 127
TDDEMOB.C 217
File menu 187
TOODEMO.CPP 223
File window 28
TOODEMOB.CPP 223
local menu 128, 194
text 128, 201
opening 126
tracking 30
FILELIST.DOC file 9
UTILS.TDW 11
files See also File menu; File window
viewing 28, 124, 130
ASMDEBUG.TDW 10
as ASCII text 128
compiler directives and 123
as hex data 128, 130
configuration See configuration files
offset address 244
demo program 43
multiple 126, 130
disk 28, 123, 127
source code 124
history lists and 121
writing to, problems with 253
executable program 123, 245

Index 271
filled arrow 48 disassembler and 180
Flags pane 181 global variables See also variables
floating point changing 72
constants debugging, in subroutines 210
Turbo Assembler 146 inspecting 71, See also Inspector windows
Turbo C++ for Windows 142 same name as local 71
numbers viewing 27, 70
formatting 148, 183 instack27
problems with 29 Watches window, adding to 72
registers 244 GlobalAlloc function 166
problems with 255 GlobalLock function 167
format specifiers 89, 148 GlobalPageLock function 167
problems with Go to Cursor command 78
invalid string 254 Goto command
Full History command 83 File window local menu 129
function keys 42, See also hot keys; keys Module window local menu 127
summary of 185-187 graphics adapters See also hardware
Function Return command 91 EGA66
functions problems with 262
calling 91 supported 248
debugging 144 VGA66
inspecting See Inspector windows Group command (breakpoints) 107
recursive, local data and 74
return values and current 91 H
returning from 79
-h option (help) 61
stepping through 80
handle
variables and inactive 250
memory
Windows See Windows, functions
functions, member, dynamic virtual 223 casting to far pointer 175
listing global memory, and 166
window
G accessing in ObjectWindows programs 231
Get Info command 75 HWindow in MainWindow 232
GetWindowClass function (TDODEMO) messages
Scribble Window 225 and 159, 162
gh2fp (type-cast symbol) 175 hardware
global breakpoints See also breakpoints, global adapters See graphics adapters; video
where occurred in program 77 adapters
global memory, Windows breakpoints 118
information about 75 memory variables and 117
listing 166 debugging 13
global menus 19, See also menus problems with 251, 257
local vs. 23 setting breakpoints 105
reference 187-190 TDDEBUG.386 file required for 12
Global pane 70 primary and secondary displays 61
local menu 71 requirements 2
Global Symbol pane local menu 198 Hardware Breakpoint command 105
global symbols 198 Hardware option (breakpoints) 112

272 Turbo Debugger for Windows User's Guide


HDWDEBUG.TD 112 editing 24
heap logging to 121
allocation 210 moving around in 202
global, Windows 166 hot keys 20, See also keys
local, Windows 168 Alt= (Create Macros) 64
Help Alt-B (Breakpoints) 104
demo programs 45 Alt-F4 (Back Trace) 80
help 40-42 Alt-F3 (Close) 36
accessing 41 Alt-F9 (Execute To) 79
problems with 253, 257 Alt-F7 (Instruction Trace) 80
additional topics for 41 Alt-F6 (Undo Close) 36
command-line options 61 Alt-FS (User screen) 30
TDW utilities 11 Ctrl-F2 (Program Reset) 81
context-sensitive 40-42 Ctrl-FS (Size/Move) 35
current activity 40 Ctrl-I (Inspect) 22
dialog boxes 21 Ctrl-N (text entry) 25
Help button 21 dialog boxes 21
Help Index 41 F2 (Breakpoints) 49
Help menu 41, 190 F4 (Go to Cursor) 78
Help on Help command 41 F3 (Module window) 28
Help screen F6 (Next Window) 34
activating 41 F9 (Run) 78
highlighted keywords in 41 F8 (Step Over) 79
HELPME!.TDW 10 F7 (Trace Into) 78
HELPME!.TDW file 10 F8 (Until Return) 79
Hex display option (files) 130 FS (Zoom) 35
Hex option (integer display) 66 help with 42
hexadecimal bytes 129 local menus 23, 42
viewing macros as 26, 64
data as 183 summary of 185-187
files as 128, 130 Tab/Shift-Tab (Next Pane) 34
hexadecimal constants, Turbo Assembler 146 HWindow data member
hexadecimal numbers 66 window handle in MainWindow 232
integers displayed as 148
hierarchies, class 149
Hierarchy command
IBM display character set 148
Data Member pane local menu 153, 156
Iconize/Restore command 35
Member Functions pane local menu 154
icons
View menu 149
dialog boxes 19
Hierarchy Tree pane 150, 151
menu 19
local menu 151, 198
reducing windows to 33, 35
Hierarchy window 149, 197
zoom33
opening 149
identifiers, referencing in other modules 133
panes 150-152
include files 123
highlight bar in windows 34
incremental matching 25
history lists 24-25, See also execution history
Index command 41
breakpoints 120
indicators, activity 40

Index 273
inline assembler See also assembler closing 31
arrays, inspecting 99 compound data objects and 88, 102
constants 146 functions 9 7
data, inspecting 98-100 global symbols and 71
expressions 146-147 language-specific programs and 94
INCLUDE compiler directive 123 local menus 100-102
instructions See also instructions class 200
keywords, problems with 256 object 200
operators, precedence 147 local symbols and 72
pointers, inspecting 98 member functions 152
scalars, inspecting 98 objects 156
structures, inspecting 100 opening 26
symbols 146 additional 31
unions, inspecting 100 panes
input See I/O class 152
input boxes 21, See also dialog boxes object 155
Action Expression 113 pointers 95, 98
Address (breakpoints) 106, 110 problems with
Condition Expression 112 character values in 95
entering text in 24, 25 multiple lines and 96, 99
Evaluate 89 pointers to arrays 96
Group ID (breakpoints) 110 reducing number onscreen 102
history lists and 24-25 scalars 95, 98
moving around in 202 structures 96, 100
NewValue89 unions 96, 100
Pass Count 115 using
Result 89 C tutorial 51
Save To 67 in demo programs 219
Tab Size, TDW 66 variables in 71
Inspect command 51 viewing contents as raw data bytes 94
Breakpoints window local menu 107 INSTALL.EXE 9
Class List pane local menu 150 installation 12
Data Member pane local menu 152, 153, 156 TDDEBUG.386 12
Data menu 31, 88 TDW9
Global pane local menu 71 instruction opcodes, illegal 77
Hierarchy Tree pane local menu 151 Instruction Trace command 80
Inspector window local menu 101 execution history and 82
Instructions pane local menu 82 instructions See also Instructions pane
Member Functions pane local menu 154 assembling 178
• I
Module window local menu 125 problems with 254, 255, 256
Parent Tree pane local menu 152 base and index registers 256, 260
Stack window local menu 74 instruction mnemonics 255
Static pane local menu 72 invalid registers 256
Watches window local menu 93 size indicators 259
Inspector windows 17, 22, 31, 94-102 target addresses 251
arrays 97, 99 back tracing into 83
classes 154 breakpoints and 116

274 Turbo Debugger for Windows User's Guide


built-in assembler and 178 Help window 41
divide, information about 77 menu commands 20
execution history and 82-83 text boxes 202
inspecting 82, See also Inspector windows text files 201
machine 178 keystrokes
executing 78, 79, 80 assigning as macros 64
multiple assembly treated as single 79 displayed 29
referencing memory 180 recording 260
viewing history of 82 problems with 242
watching See also CPU window; Watches restoring to previous 65
window keywords, inline assembler
Instructions pane, local menu 82, 194 problems with 256
Integer Format radio buttons 66 keywords in Help window 41
integers
constants L
Turbo Assembler 146
-1 option (assembler mode) 62, 173
Turbo C++ for Windows 142
labels, running programs to 79
formatting 66
tutorial 49
viewing
Language command 132
decimal 148
language-specific applications
hexadecimal 148
assignment operators and 72
watching 92, See also Watches window
conventions 132
international sort order 2
expressions and 131
interrupting programs
Inspector windows and 94
using Ctrl-Alt-SysRq 83
scope override and 134
using message breakpoints, in TDODEMO
using 16, 131
230
Layout option (save configuration) 67
interrupts
layouts, restoring 36
back tracing into 82
lh2fp (type-cast symbol) 175
program See also Ctrl-Alt-SysRq
Line command 126
tracing into 80
line numbers 244
Windows program, messages about 77
Code pane 180
InvalidateRect function, in TDODEMO 237
displaying current 48
InvalidateRgn function 237
generating scope override 134
I/0
moving to specific 126, 129
ports
problems with, source files and current 125
reading from 245
lines
writing to 245
end of, problems with 261
video 65
lines, multiple, problems with 96, 99
linked lists 102
K list boxes 21, See also dialog boxes
keys See also arrow keys; function keys; hot Conditions and Actions (breakpoints) 111
keys incremental matching in 25
assigning as macros 64 moving around in 202
cursor-movement 34, 203 list panes, Pick a Module 123
CPU window 179 lists
dialog boxes 21, 203 choosing items from 34

Index 275
global memory 166 Local Symbol pane local menu 199
local heap 168 local variables See also variables
modules, Windows 168 breakpoints and 118
Load Modules or DLLs dialog box 170 changing 72
LoadLibrary function 172 global values and 71
local and static variables inspecting 72, See also Inspector windows
selecting for Variables window 73 problems with 262
watching 73 viewing 27
local heap 168 in stack 27
local memory, Windows, listing 168 specific instances of 71, 74
local menus 22-24, See also menus LocalAlloc function 168
accessing 23 Locals command 71, 74
Breakpoints window 106-10 7, 191 location, breakpoints 103
Class List pane 150 LockData function 167
Class pane 19 7 Log command (breakpoints) 120
Code pane 191 log files 243
Control pane 197 opening, problems with 250, 252
Data Member pane 153, 155 writing to, problems with 252
Data pane 192 Log option (breakpoints) 113
Dump window 194 Log To File command 252
File window 194 Log window 27, 120-122
Global pane 71 adding comments to 243
Global Symbol pane 198 local menu 121, 194
Hierarchy Tree pane 151, 198 opening 120
Inspector windows 100-102, 200 window messages, sending to 165
Instructions pane 82, 194 Logging command 122
Local Symbol pane 199
Log window 121, 194 M
Member Function pane 154
machine instructions 178
Message Class pane 196
executing 78, 79, 80
Messages pane 196
macros 26
Modulewindow 125-127, 195
recording
Object Member function pane 156
keystrokes as 64
Parent Tree pane 152, 198
problems with 246, 260
Register pane
removing 65
CPU window 193
restoring to previous 65
Numeric Processor window 197
saving 67
Registers window 198
Macros command 64
Selector pane 192
Macros option (save configuration) 67
Stack pane 193
MainWindow object, inspecting 231
Stack window 74, 198
MANUAL.TDW 10
Static pane 72
math coprocessor See numeric coprocessors
Status pane 197
Member Function pane 152
Varibles window 198
local menu 154
viewing hot keys in 42
memory
Watches window 93, 199
addresses 131
Window Selection pane 195
disassembler and 180

276 Turbo Debugger for Windows User's Guide


displaying 181 program termination and 84
dump 183 tutorial 45
entering 244 View 26, 188
problems with 256 Window 33, 47, 190
allocation message breakpoints
inspecting 75 Get Info message about 76
problems with 210, 258 Message Class pane
blocks 242 local menu 196
problems with 252 message classes 163
dump28, 184 Windows Messages window
problems with 183 adding to 162
global Windows deleting from 164
information about 75 message log 27, See also log files
listing 166 messages See also error messages
handle dialog boxes 241-248
casting to far pointer 175 program termination 76
listing global memory 166 window
local, Windows, listing 168 debugging tips 165
locations, problems with 253, 259 setting breakpoints, TOODEMO 230
read-only 250 Windows
references, formatting 148 logging
running out of 258 to a file 165
watching 112 to the TOW window 158
Windows global, selectors (accessing) 181 setting breakpoints 164
menu bar 19, 45 Messages pane, local menu 196
activating 19 Methods command 155
commands 187 Microsoft Windows See Windows
menu trees 204-205 Mixed command 180
menus 19-20 modes See display modes
=(System) 19, 187 Module command 257
activating 19 Module window local menu 126
Breakpoints 104, 189 View menu 124
commands See commands Module window 28, 124-127
Data 88-91, 189 filled arrow and 48
Edit 188 local menu 125, 195
exiting 20 opening 124
File 187 duplicate 126
global 19 source files and 124
local vs. 23 modules 3, 123, See also Module window
reference 187-190 compiling 57
Help 41, 190 current
hot keys and 20 changing 170
local See local menus overriding 132
Options 64-67, 189 loading 124, 247
pop-up 19 new 126
pull-down 19 problems with 127
Run 69, 78-80, 189 referencing identifiers in other 133

Index 277
scope override and 93 problems with 253
CandC++ 134 Turbo Assembler 147
Pascal 137 Turbo C++ for Windows 142
setting breakpoints in other 118 hexadecimal 66
tracing into 80 scalar 139
tracking 30 numeric coprocessors See also 80x87
viewing 28, 124-127 .coprocessors
duplicate 126 current state, viewing 29
problems with 257, 261 registers, entering new values for 244
source code in 244 numeric exit code 77
Windows, listing 168 Numeric Processor window 29
modulus operator, problems with 252 opening, problems with 257
monitors See also hardware; screens panes 197
display swapping 61
monochrome 61 0
mouse
Object Member function pane
choosing menu commands 19-20
local menu 156
moving around in dialog boxes 21
object modules 123
setting breakpoints 49, 104
object-oriented programs
support
classes, inspecting 154
disabling/ enabling 62
compatibility with Turbo Debugger 149
online help 41
debugging 17, 156
windows and 32-33
nested object structures 152
multi-language programs 10
multiple inheritance 151 this parameter and 93
expressions, problems with 250
member functions
N problems with viewing 251
nested classes, scope of 137 member functions, inspecting 152
New Expression command objects
Data Member pane local menu 156 formatting 89
Inspector window local menu 102 hierarchy tree 150
new features for version 3.0 1 inspecting 156
New Value input box 89 scope override 137
Next command See also Search command objects, data See data, objects
File window local menu 130 ObjectWindows
Module window local menu 127 applications, debugging 223
problems with 257 TApplication object 226
Next Pane command 34 online help See also help
Next Window command 34 dialog boxes 21
nonprinting characters 95 OOP See object-oriented programs
return value 148 opcodes, illegal instruction 77
null-terminated character string 95, 99 Open command 85
numbering system, windows 33 Open Log File command 121
numbers 91 operands 91, 253
decimal 66 instruction, memory pointers and 180
floating-point See floating point, numbers problems with 259
formatting 148 invalid 255

278 Turbo Debugger for Windows User's Guide


out of range 254 Register 181
segment overrides and 250 Registers window 29
size 180 Selector 181
problems with 259 Stack 183
operators 253 text See text panes
assignment 72, 94, See assignment operators Variables window 27, 70
binary 143 Windows Messages window 195
C programs and 90 parameters 3, See also arguments
invalid 255 logging (breakpoints) 119
modulus, problems with 252 this 89, 93
precedence viewing, program-calling 73
Turbo Assembler 147 Parent Tree pane 151
Turbo C++ for Windows 143 local menu 152, 198
options 64, See also Options menu Parents command 151
command-line See command-line options parsing, TDW vs. Turbo C++ 10
display swapping 65 Pascal option (language convention) 132
program execution 78 pass counts 104, 115
restoring defaults 67 problems with 255
saving 66 pasting and copying 36
Options menu 64-67, 189 Path for Source command 3, 66
Options option (save configuration) 67 paths, directory See directories
Origin command 75 Pick a Module list pane 123
Module window local menu 127, 139 pointers 148
output See also 1/0 compound data objects 91
display onscreen 65 memory 132, 180
stack, current location 183
p pointing at data objects 91
pop-up menus 19
-p option (mouse support) 62
ports, 1/0 245
panes precedence, operators See operators
blinking cursor in 34 Previous command 41
Breakpoints window 26, 106 Module window local menu 126
Code 180, See Code pane
primary display 61, See also screens, swapping
CPU window 28
printers, problems with 242
cycling through 179 processors See 80x86 processors; CPU
Data 183, See Data pane program execution, interrupting 83
Execution History window 29, 82 Program Reset command 81, 85
Flags 181 Ctrl-Alt-SysRq, and 84
Hierarchy window 150-152 TDODEMOB demo program 234
highlight bar in 34 programs 216
Inspector windows 31
accuracy testing 215
class 152
compiling 18
object 155 current location 48, 146
list boxes 202
CPU window 180
local menus and 22 Inspector windows 71
moving between window 34
Module window 74
Numeric Processor window 29, 197
problems with 81, 125
recording current contents of 121

Index 279
returning to 75, 127, 139 running 29, 69, 86, See also programs,
scope 139 execution
overriding mechanism and 92 to breakpoints 50
verifying 30 command-line options and 86
watching 72, 80, 123, See also Watches to cursor 48, 78
window at full speed 78
current state 70 to labels 49, 79
inspecting 70-77, See also Inspector returning information on 75
windows in slow motion 80
debugging 16, 17, 57-60, 207-208, See also Windows, from 60
debugging scope See scope
current scope and 139 source code See code
dynamic link libraries 169 source files and 124
planning for 67, 216 stepping through
returning information on 75-77 problems with 76
starting TDW 58 tutorial 48
with no debug information 80, 260 stopping 84, See also breakpoints
with out-of-date debug information 260 stopping (breakpoints) 118
demo See demo programs watching See Watches window
execution See also programs, running Windows
controlling 69-86 debugging 157
menu options 78 not loaded, problems with debugging 76
reversing 80, 82 stopping, messages about 76
problems with 83 unexecuted, problems with examining values
terminating See programs, stopping 77
fatal errors and 248 protected mode, selectors, accessing 181
full output screen 30 pseudovariables (Turbo C++ for Windows) 140
incremental testing 209 pull-down menus 19
inspecting 22, See also Inspector windows
language options, overriding 132 Q
loading 245, See also files, opening
Quit command, TDW 67
dynamic link libraries 169
new85
problems with 257, 260 R
symbol tables and 258 radio buttons 21, See also dialog boxes
message logs and 27 Action 113
modifying See programs, altering Changed Memory 117
multi-language 10 changing settings 21
opening See programs, loading Condition 112
patching, temporarily 178 Display Swapping 65
recompiling 18 Expression Language 132
recovering 83 Integer Format 66
reloading 81, 85 Log 119
Windows and Ctrl-Alt-SysRq 84 Screen Lines 66
restarting a debugging session 85 Range command
returning from 48 Data Member pane local menu 155
returning to 75, 126 Inspector window local menu 101

280 Turbo Debugger for Windows User's Guide


read-only memory See ROM tracking 92
README file 10 variables See variables
READY indicator 25 return values (breakpoints) 119
RECORDING indicator 64 Reverse Execute command 82
records, problems with 258, 262 reversing program execution 80, 82, See also
recursive functions 74 backward trace
recursive procedures 71 problems with 83
reference books 7 Windows code 80
reference line, dialog boxes 42 ROM, programs executing in 250
Register pane 181 routines
CPU window, local menu 193 accessing 132
Numeric Processor window, local menu 197 problems with 247
registers 94, See also Registers window calling
80386 hardware debugging 13 problems with
CPU See CPU, registers invalid name 258
floating-point 244 invalid parameters 254
problems with 260 debugging 123, 210
invalid 255, 256 inspecting 74
segment 84, 148 variable with same name as 71
valid address combinations 256 names, finding 27
values, accessing 29 recursive, local data and 71
Registers window 29, 184 stepping over 17
local menu 198 testing 216
panes29 viewing in stack 27, 73
ReleaseCapture function 235 Run command 78
reloading programs 81 execution history and 82
Windows and Ctrl-Alt-SysRq 84 Run menu 69, 78-80, 189
Remove command program termination and 84
Breakpoints window local menu 107 running
Macros menu 65 programs See also programs, running
Watches window local menu 93 TDW60
Windows Messages window
message classes 164
window selection 162
s
sample programs See demo programs
Repaint Desktop command 36
Save Configuration check box 67
repeat counts 147
Save Options command 36, 66
resize box 33
Save Options dialog box 67
restarting a debugging session 85
Save To input box 67
Restore Options command 36, 67
-sc option (ignore case), Turbo Debugger 62
Restore Standard command 36
scalar numbers 139, 243
Result input box 89
scalar variables 95
return values 131
scientific notation 142, 146
changing 94, 101
scope 92, 133-139
expressions 243
breakpoint expressions 118
inspecting 91, See also Inspector windows
current 132, 139
nonprinting characters 148
accessing symbols outside 133
problems with 77, 256
DLLs, and 138

Index 281
implied, evaluating expressions and 139 Selector command
nested classes 137 Selector pane local menu 182
overriding 134-138 Selector pane 181
tips local menu 182, 192
C, C++, Turbo Assembler 136 memory segments in 181
Pascal 138 Send to Log Window command (Windows
problems with, inactive 250 Messages window) 165
templates 136 Set Message Filter dialog box 163
this parameter 89 Set Options command (breakpoints) 106
Screen Lines radio buttons 66 SetCapture function 235
screens See also hardware; monitors SetupWindow function, redeclaring 231
display modes See display, modes shortcuts See hot keys
layouts, restoring 36 Show command 73
lines per, setting 66 Show Inherited command
problems with Data Member pane local menu 153, 156
graphics display 36 Member Functions pane local menu 154
writing to 65 side effects
startup, TDDEMO 44 changing variable values with 90
swapping 65 splicing code (breakpoints) 113
User See User screen Size/Move command 35
ScribbleWindow type (TDODEMO) 225 Smart option (display swapping) 65
scroll bars 32 software, requirements 2
scrolling 31 sort order, international 2
dialog boxes 203 source code See code
Help screens 41 source files 3, See also files
Inspector windows 52 language conventions and 132
menus20 loading 124, 247
text boxes 202 problems with 261
text panes 201 search paths for 2
-sd option {set source directories) 62 Source option {language convention) 132
Search command See also Next command stack 84, 178, See also Stack pane; Stack
File window local menu 129 window
history lists and 24 current state 27, 73-74
Module window local menu 126 pointer, current location 183
search paths, source files, for 2 Stack command 71, 73
search templates 204 Stack pane
secondary display 61, See also display, current stack pointer 183
swapping local menu 193
segment stack trace 227
overrides, problems with 250 Stack window 27, 73-74
pointers to register 148 local menu 74, 198
registers, program termination and 84 opening 71, 73
select by typing 25 stack trace 227
SelectBlackPen function (TDODEMO) Standalone Debugging command 57
bugs starting directory, changing 63
finding 230 starting TDW 58
fixing 233 in assembler mode 62

282 Turbo Debugger for Windows User's Gulde


command-line options and 239 base segment address 245
startup code creating 57, 260
dynamic link libraries 173 dynamic link libraries, and 169
program, debugging 62 invalid 260
types of 172 loading 246
startup screens, TODEMO 44 problems with 258, 261
Static pane 71 symbols 71, 131
local menu 72 accessing 133-139, 247
static symbols, disassembler and 180 disassembler and 180
status line 41, 42 global 198
Status pane, local menu 197 problems with 250, 261, 262
Step Over command 79 invalid 256
execution history and 82 type information and 258
stepping over routines 17 scope 133
stepping through Turbo C ++ for Windows 140
functions 80 syntax
programs checkers, built-in 16
problems with 76 errors 16, 261
Stop Recording command 64 System Information box 75
strings 148 System menu See= (System) menu
byte lists and 139
character T
null-terminated 95, 99
-t option (starting directory) 63
quoted 129
Tab Size input box 66
problems with 262
Table Load command 245
searching for
tabs, setting 66
File window, in 129
problems with 262
Module window, in 126
TApplication, object 226
responding to prompt 246
Task List, Windows, TOW and 60
searching for next
T0386 virtual debugger
File window, in 130
setting breakpoints 112
Module window, in 127
TDCONFIG.TOW 36, 63
Turbo C++ for Windows 142
loading 61
format control See format specifiers
overriding 63
text, searching for 24
TODEBUG.386 file 12
truncated 89, 92
TODEM043
structures
source files 44
changing 250
TODEMO.EXE 222
inspecting complicated data 88, 102
TDODEMO
problems with 258, 262
CScribbleApplication object 226
Super VGA support 2
GetWindowClass function, ScribbleWindow
support, technical 5
225
switches See command-line options
InvalidateRect function 237
switching Windows applications, TOW and 60
InvalidateRgn function 237
symbol names, problems with 250
MainWindow object 231
Symbol pane 27
ScribbleWindow type 225
symbol tables 132

Index 283
SelectBlackPen function Trace Into command 78
bug, finding 230 continuous. tracing 80
bug, fixing 233 execution history and 82
SetupWindow function 231 programs executing in ROM and 251
stack trace 227 tracepoints 103, See breakpoints
UpdateWindow function 237 tracing 17, See also Trace Into command
WMLButtonDown function backward See backward trace
bug, finding 234 continuous (animation) 80, 242
bug, fixing 229, 235 execution history and 81
ScribbleWindow 226 into interrupts 80
WMLButtonUp function 226 into functions 48
WMMouseMove function 226 program termination, and, information about
bug, finding 227 76
WMRButtonDown function 226 this parameter and 89, 93
bug, finding 236 Tree command 151
bug, fixing 238 Turbo C++, versions compatible with TOW 2
.TDS files, creating 11 Turbo C++ for Windows
TOW arrays 212
logging window messages 158 inspecting 97
window object, adding 161 problems with 96
window selection automatic variables (autovariables) 214
adding 159 scope 214
deleting 162 uninitialized 211
technical support 5 bugs specific to 211-215
templates character strings 142
breakpoint behavior 119 compiler 211
scopeof 136 constants 142
ternary operators 143 data
text 66 inspecting 95-98
entering types, converting 145
active windows and 31 demo programs, debugging 217
in input boxes 24, 25 dynamic virtual member functions 223
incremental matching 25 escape sequences 142
in log 243 expressions 140-146, 212
searching for 204, 261 with side effects 90, 144
strings, searching for 24 #define macros and 214
text files 128, 201 functions 144
text modes See display, modes inspecting 97
text panes 201, 243, 246 problems with 90
moving around in 201 returning from 214
this parameter 89 integer assignment 213
watching 93 keywords 145
tiled windows 46 keywords, problems with 256
time delays, setting 80, 242 loops, exiting 215
Toggle command operators 212
Breakpoints menu 116 expressions with side effects and 90, 144
Toggle command 105 precedence 143, 212

284 Turbo Debugger for Windows User's Guide


pointers evaluating 88-91
incrementing and decrementing 212 global See global variables
inspecting 95 inactive functions and 250
pseudovariables 140, 141 inspecting 31, 88, 94-100, 102, 246, See also
scalars, inspecting 95 Inspector windows
source code 213, 215 function with same name as 71
structures, inspecting 96 in recursive functions 74
symbols 140 language conventions and 132
unions, inspecting 96 local See local variables
variables, return values 92 logging (breakpoints) 119
Turbo C, expressions, problems with 249 names 92
Turbo Pascal finding 27
units, override syntax 137 problems with 258
type conversion 72, 94 pointing at 91
memory handle to far pointer 175 private 93
problems with 256, 262 program termination and 84
Turbo C++ for Windows reserved words and return values 17, 90
145 inspecting 31
typecasting See type conversion problems with 71, 95
types scalar, character values and 95
data See data, types scope override 135, 137
object See objects, types uninitialized 210
updating 93
u viewing 70-73
in recursive routines 71
UAE See unrecoverable application error
watching 27, 91, 92, 243, See also Watches
unary operators
window
Turbo C++ for Windows 143
Clipboard, and 39
Undo Close command 36
Variables command 70
union members, problems with 258
Variables window 27, 70-73
units, scope override and 137
local menu 198
unrecoverable application error (UAE) 227
opening 70
Until Return command 79
VGA See also graphics adapters; video adapters
UpdateWindow function 237
line display 66
User screen 30, 65
video adapters See also graphics adapters,
User Screen command 30
hardware
utilities, disk-based documentation for 11
display options 66
UTILS.TDW file 11
problems with 262
Super VGA support 2
v supported 248
variables 27, See also Variables window Video Graphics Array Adapter See VGA
accessing 132 videos See monitors; screens
problems with 254 View menu 26, 188
with no type information 145 virtual member functions
debugging 210 dynamic223
DLLs, accessing in 138

Index 285
w exit code returned to 77
functions
Watch command
GlobalAlloc 166
Global pane local menu 72
GlobalLock 167
Module window local menu 125
GlobalPageLock 167
Static/Local pane local menu 73
lnvalidateRect, in TOODEMO 237
Watches window local menu 93
InvalidateRgn 237
Watch dialog box, global symbols and 72
LoadLibrary 172
Watches command 92
LocalAlloc 168
Watches window 27, 92-94
LockData 167
local and static symbols and 73
ReleaseCapture 235
local menu 93, 199
SetCapture 235
opening 92
UpdateWindow 237
using220
Languages setting 2
C tutorial 50
reference books 7
watchpoints 17, 103, See also breakpoints
returning to 6 7
C tutorial 50
running programs from 60
Clipboard, and 39
selectors, accessing 181
reloading programs and 85
switching applications, TDW and 60
wildcards
Task List, TDW and 60
DOS 127,261
TDW,and 157
searching with 126, 204
tips, debugging tips 83
window handle
window messages
accessing in ObjectWindows programs 231
TOODEMO
HWindow in MainWindow 232
WM_LBUTTONOOWN 234
Window menu 47, 190
WM_LBUTTONUP 234
opening 33
WM_MOUSEMOVE 234
window management and 33
WM_NCMOUSEMOVE 234
window messages
WM_PAINT 237
breakpoints
Windows Messages command 158
Get Info message about 76
windows 17, 26-36
setting 164
active 31
setting in TDODEMO 230
returning to 20
logging
bottom line in 42
to a file 165
Breakpoints 26, 105-107
to the TDW window 158
Clipboard 30, 196
window object
closing 36
adding to TDW Windows Messages window
temporarily 35
161
CPU See CPU window
Window Pick command 34
Dump 28, 184, 194
window selection
Execution History 29
adding to TDW Windows Messages window
opening 82
159
File 28, 194
deleting from TDW Windows Messages
opening 126
window 162
Hierarchy 149, 197
Window Selection pane, local menu 195
Inspector See Inspector windows
Windows
layout, saving 36, 67
Display Windows Info command 166

286 Turbo Debugger for Windows User's Guide


local menus and 22 panes 195
Log 27, 120, 120-122, 194 standard Windows application 158
Module See Module window WM_LBUTTONDOWN message 234
mouse support 32-33 WM_LBUTTONUP message 234
moving35 WM_MOUSEMOVE message 234
moving around in 203 capturing 235
multiple 33-34, 126, 130 WM_NCMOUSEMOVE message 234
moving among 33 WM_PAINT message
Numeric Processor 29, 197 erase-screen bug 237
problems with 257 WMLButtonDown function (TDODEMO)
opening bug
duplicate 30 finding 234
new26 fixing 229, 235
panes See panes Scribble Window 226
problems with 30, 258 WMLButtonUp function (TDODEMO) 226
current program location and 81 WMMouseMove function (TDODEMO) 226
recovering last closed 36 bug, finding 227
reducing to icon 33, 35 dynamic virtual member function, as a 224
Registers 29, 184, 198 WMRButtonDown function (TDODEMO) 226
repainting 36, See also display updating bug
resizing 33, 35 finding 236
single-line borders and 35 fixing 238
Stack 27, 73-74, 198 word 180
opening 71 formatting 183
tiled 46 WordStar-style cursor-movement commands
tutorial 46 201, 202
Variables 27, 70-73, 198
opening 70
Watches See Watches windows
z
zoombox33
Windows Messages 30, 195
Zoom command 35
Windows Information dialog box 166
zoomicon33
Windows Messages window
for an ObjectWindows program 160

Index 287
TURBO
DEBUGGER®3.0
FOR WINDOWS

BORLAND
CORPORATE HEAOOUARTERS: 1800 GREEN HILLS ROAO, P.O. BOX 660001. SCOTTS VALLEY, CA 95067-0001 . (408) 438-5300. OFFICES IN: AUSTRALIA.
DENMARK, FRANCE. GERMANY, ITALY, JAPAN. NEW ZEALAND, SINGAPORE. SWEDEN ANO THE UNITED KINGDOM • PART #14MN-TCW03-10 • BOA 2883

You might also like