home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_200
/
228_01
/
cwindemo.doc
< prev
next >
Wrap
Text File
|
1987-07-31
|
25KB
|
658 lines
C-window Demonstration Copyright (C) 1983 by c-systems
C-window Demonstration Document File
------------------------------------
Do it NOW!
----------
This file shows how to use the c-window DEMO provided in
Diskette B.
Print this file and the file "dump.c" (also on Diskette B),
as constant reference will be made to them in this document.
Overview
--------
C-window(tm) is used to debug C programs at the source-code
level. C-window provides an interactive debugging
environment that simplifies the program development process.
C-window commands can:
o set breakpoints at a function name and
source-code line,
o single step and trace at the C
source-statement level,
o display the value of variables, using the
same variable names as used in the C source
code (Local and external are supported),
o display the source code of the program
under test,
o display complex expressions, like the third
element of an array of characters, which is
a member of a structure, which is an
element in an array of structures, and
o override minor program bugs allowing more
of the program to be tested before a
recompilation is needed.
To use the c-window debugger, the source code must be
compiled using the "-w" option of the c-systems C compiler.
During the link step the object code library, c-window.lib,
is included, which embeds the c-window executive into the
executable object file. When the final test module is
invoked, the c-window executive is actually given control,
not the program being tested.
The Programs Dump.C and Dump.Exe
--------------------------------
Dump.c is the source code for a dump utility that dumps an
ASCII file in both hex. and ASCII format, while showing the
address of the data in the file. The executable module,
"dump.exe" is also contained on Diskette B.
To study the output of this program, type:
A>dump dump.c
(For the purposes of this DEMO package we assume that all
files mentioned are available on drive A.)
The program reads the input file dump.c and displays three
fields on the monitor. The leftmost field contains the
starting address of the data displayed. The middle field
contains the hex. representation of the file, and the
rightmost field contains the ASCII representation of the
hex. data. Periods are displayed in the rightmost field to
represent extended-ASCII characters.
C-window Demonstration Program
------------------------------
I suggest that you review the "dump.c" source code before
proceeding with this DEMO.
The DEMO program,"cwdump.exe", is also contained on Diskette
B. Assuming it is on drive A, type
A>cwdump dump.c
to start the DEMO.
If you are using an IBM-PC or compatible, the screen is
divided into three sections. These sections are treated as
independent windows by the c-window executive. The top
window is the debugger interface. All commands issued and
responses received are displayed within the top window. The
middle window is dedicated to the application keyboard input
and screen output. The hex. dump that you saw when you ran
"dump.exe" will appear only within this window. The last
window, at the bottom of the screen, displays the source
code of the file being debugged. Whenever a single step, a
trace, or a breakpoint occurs the last window is updated to
show the results of the instruction. This allows for
debugging at the source level without the need to reprint
the source code each time a source code change is made.
When the program begins execution a message is issued
indicating the function name ("main") and the line number
where execution begins. The message
entry at main line 22
>>
should appear in the top window, showing that execution of
the program under test started in the function named "main"
at line 22. The ">>" is the c-window command-line prompt and
indicates that c-window is waiting for a command. C-window's
response to your command is not preceded by the ">>' prompt,
so you can easily tell them apart.
To exit the DEMO, type "ex" after the ">>' prompt displayed
in the top window.
As our first command to the debugger, let's display the
arguments passed into the "main" function (i.e. argc and
argv). The command
>>d argc
2
displays the number of parameters typed on the command line
when the program was invoked. The "2" shown on the next line
is c-window's response to this command.
To display the parameter entered on the command line, type:
>>ds argv[1]
dump.c
The <ds> command tells c-window to display "argv[1]" using
the string format, and indeed C-window's response to the
command matches the command-line entry used to invoke
"cwdump.exe"
We saw earlier that "argc" was equal to 2. On line 22 of
"dump.c" an "if" statement checks to see if "argc" is less
than 2. Since "argc" is not less than 2, we expect that
lines 23, 24, and 25 (the body of the "if" statement) will
be skipped and execution resumed at line 26, the first
statement after the "if" statement. C-window`s single step
command is used below. Let's see what happens.
>>s
step at main line 26
Sure enough. The body of the "if" statement was skipped and
line 26 will be executed next.
The "if" statement on line 26 tries to open the file named
in argv[1] ("dump.c") and then checks the value returned by
"fopen" to see if any errors were detected. Let's single
step again and look at the results.
>>s
step at main line 30
C-window's response shows that no errors were detected since
line 27 and 28 were skipped. The pointer "infp" now holds
the file pointer that will be used for all subsequent file
operations on "dump.c".
The "if" statement on line 30 checks if an output file name
was entered on the command line of "cwdump" and also checks
that the output file is not the same file as the input file.
>>s
step at main line 37
As no output file was typed on the command line when
"cwdump.exe" was executed "argc" is not greater than 2. So
lines 31, 32, and 33 were skipped, and line 37 is the next
line to be executed. Line 37 assigns the console to the
output file pointer so subsequent output done by the program
will go to the console screen.
Now let's set a non-sticky breakpoint using the <g> command.
(go command). This breakpoint will be set at line 40 of
function "main". This line follows the code that reads the
first 16 bytes of "dump.c".
>>g main,40
break at main line 40
Execution begins at the current location and stops when line
40 in "main" is to be executed. C-window's response shows
where the breakpoint occurred. The number of elements
actually read from the file, in "nread", can be displayed
using the command:
>>d nread
10
The <d> command indicates to display the variable "nread" in
hex. format (Any C expression can be displayed, not just
simple variables.) So "nread" = 0x10 or 16 decimal. Notice
that you typed "nread", the same name declared in the source
code. This is symbolic debugging. The value of "nread" shows
that 16 bytes were read from "dump.c"
Alternately, to display the contents of "nread" in decimal,
use:
>>dd nread
16
Let's look at the data that was read from "dump.c". Since we
know that this data was placed into a buffer with address
"buf", to display the data in a byte-format memory dump,
use:
>>db buf
66a0 : 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a /***************
66b0 : 10 00 02 00 70 04 06 48 82 00 00 01 c7 13 02 00 ....p..H........
66c0 : d4 47 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .G..............
66d0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
66e0 : 00 64 75 6d 70 2e 63 00 00 00 00 00 00 00 00 00 .dump.c.........
66f0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
6700 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
6710 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
As 16 bytes have been read from "dump.c", only the data
between addresses 66a0 and 66af, inclusive, are of interest
to us at this time. (The addresses shown in this dump may
vary from those shown in your dump.) The output of our test
program should look very similar to this data dump.
Now, to make c-window display the first 16 bytes of the file
we go to line 53 of "main". Lines 47 - 52 print either the
value in "buf" or a "." if an extended-ASCII character was
found.
>>g main,53
0 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a /***************
break at main line 53
The line of data displayed after the <g> command, but before
the break message, is the output of the application program.
The output looks very much like the memory dump that we saw
earlier. If this had not been the case then a bug would have
been present.
Line 53 increments the file position indicator "position" by
the number of bytes read from the file, "nread". Before line
53 is executed it may be of some interest to display the
value of the "position" variable before the assignment
statement occurs. The command
>>d position
0
shows that the current value of "position" is 0. As "nread"
is 16 we expect "position" to equal 16 after the execution
of line 53.
Before executing line 53, I want to demonstrate another
powerful feature of c-window called an "automatic command".
Since we are interested in the value of "position", it would
be helpful if its value were displayed whenever we entered a
command that caused a portion of the program to be executed.
The automatic command feature is set by using the <cs>
command:
>>cs 1 d position
>>
This causes the command "d position" to be executed whenever
a single step, a breakpoint, or a trace occurs. Now that the
command has been entered, a single step should cause the
contents of "position" to change, and the new contents of
"position" to be displayed. (Recall that we are currently at
line 52 in "dump.c")
>>s
step at main line 38
<1>d position
10
Notice that when the single step occurred, the message "step
at main line 38" is displayed, and the automatic command "d
position" is executed. The <1> means that the first
automatic command has been executed. If there were other
automatic commands they would all have been executed, and
the number of the automatic command would appear in place of
the "1". A breakpoint set at line 53 should cause the
current value of "position" to be displayed. At this point
it should match what has just been printed on the screen.
The breakpoint can be set with the command:
>>cs 2 g
This causes the <g> command to be executed as the second
automatic command.
Currently we have two automatic commands; the first
generates a breakpoint and the second restarts execution.
Typing the <g> command will cause the program to loop. This
loop may be stopped by pressing the "h" key. Type <g>, but
be prepared to type "h."
>>g
10 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a ****************
break at main line 53
<1>d
10
<2>g
20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a ****************
break at main line 53
<1>d position
20
<2>g
30 2a 2f 0d 0a 2f 2a 09 09 09 09 09 09 2a 2f 0d 0a */../*......*/..
break at main line 53
<1>d position
30
<2>g
stopped at main line 38
>>h
If you have not done so already, press the "h" key on your
keyboard. The line at which the program stopped may not
match that shown above, depending upon when the "h" key was
pressed. For the remainder of this demonstration the point
where program execution stopped is unimportant.
Notice that c-window echoes the character "h" after taking
control. Also notice that the automatic commands were not
executed when a keyboard hit signaled to stop program
execution. This was done so that if execution is stopped
manually it will not be started again, unintentionally, due
to an automatic command. (I pressed the "h" key purposely to
show the on-line help command. Press the Enter key to
display the help menu.)
The program-stop feature you have just seen can be useful
during the early stages of debugging when a program does not
act properly. It may not hit any of the set breakpoints or
may even hang in an endless loop. Pressing a key, when
console I/O is not expected, returns control to the
executive level of the debugger. This effectively eliminates
type-ahead when in the debugging mode.
Next I want to demonstrate the variable display commands.
The <l> and <e> commands are used to display the values of
all local and global (external) variables in the current
function.
>>l
Function: main
8[bp]<66be> argc: 2
10[bp]<66c0> argv: 6764, *argv: 66e0
-2[bp]<66b4> infp: 452, *infp: 11cb
-4[bp]<66b2> outfp: 3, *outfp: 6420
-6[bp]<66b0> nread: 10
si i: 10
-22[bp]<66a0> buf
-24[bp]<669e> position: 30
>>e
External data:
< 434> stdout: 3, *stdout: 6420
There are some interesting things to note in the displays.
First, the <l> command generated variables with both
positive and negative offsets from the "bp" register. (The
bp register is the base pointer register in the 8086 from
which all stack variables are referenced.) Variables passed
in parameters have positive offsets and variable allocated
on the stack have negative offsets. The number within a
bracket "<>" indicates the value of an address within the
data segment. This is a handy tool for watching the
operation of recursive procedures and is also useful for
monitoring the amount of stack space used when the program
executes.
The variable "i" was declared as a register variable and the
local-variable dump shows which register the variable was
assigned to as well as its current value.
Note that the value of "outfp" in the local-variable dump
and "stdout" in the external-variable dump are identical.
This is because the value of "stdout" was assigned to
"outfp" on line 37 of the dump program.
The last feature that I want to demonstrate is the
expression-breakpoint. This is one of the most powerful
features of the debugger since it essentially allows a
user-definable breakpoint based upon the values of variables
as well as the relationships between variables. An
arbitrarily complex expression can be entered and evaluated,
and a breakpoint occurs when the expression evaluates as
TRUE.
Let's set a breakpoint such that when the value of
"position" exceeds 256 (100 hex.) the program returns
control to the c-window executive. First, the breakpoints at
"main", line 53, must be cleared. This can be done by:
>>bc .
All breakpoints cleared
>>cc .
All auto commands cleared
Next, the expression-breakpoint can be set using the
command:
>>bx main,1,position > 0x100
Using the <g> command to begin execution gives:
>>g
40 2f 2a 09 64 75 6d 70 2e 63 09 09 09 09 09 2a 2f /*.dump.c.....*/
50 0d 0a 2f 2a 09 09 09 09 09 09 2a 2f 0d 0a 2f 2a ../*......*/../*
60 09 44 75 6d 70 20 74 68 65 20 63 6f 6e 74 65 64 .Dump the conten
70 74 73 20 6f 66 20 74 68 65 20 73 70 65 63 69 66 ts of the specif
80 69 65 64 09 2a 2f 0d 0a 2f 2a 09 66 69 6c 65 20 ied.*/../*.file
90 74 6f 20 74 68 65 20 73 63 72 65 65 2e 09 2a 2f to the screen or
a0 20 6f 75 74 70 75 74 20 66 69 6c 65 2e 09 2a 2f output file..*/
b0 0d 0a 2f 2a 09 09 09 09 09 09 2a 2f 0d 0a 2f 2a ../*......*/../*
c0 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a ****************
d0 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a ****************
e0 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a ****************
f0 0d 0a 0d 0a 23 69 6e 63 6c 75 64 65 20 3c 73 74 ....#include <st
100 64 69 6f 2e 68 3e 0d 0a 23 64 65 66 69 6e 65 20 dio.h>..#define
expression break at main line 38
position > 0x100 :1
>>
The hex. dump of the program continued until the first
statement after which the contents of "position" exceeded
100. This was at line 38.
Now we let the program execute until it terminates, at which
time it will return to DOS as in a normal program
termination. The <g> command is used after we have cleared
all automatic commands.
>>bx .
>>g
This is only the tip of the iceberg. Experiment with the
"cwdump.exe" module; become familiar with its commands.
We at c-systems hope that you will find the c-window
debugger, used in conjunction with the c-systems compiler,
to be as useful in your software development projects as
they have been in ours.
Command Summary
---------------
A brief summary and explanation of the commands supported by
c-window are provided below.
s Single step
t n Trace n statements
g Execute
bs <fname>,<line>,[count] Set execution break
bc [<fname>,line[.] Clear break
b Display execution breakpoints
bx <fname>,<count>,<expr> Set expression break
bx . Clear expression breakpoint
bx Display expression breakpoint
cs [#] <expr> Enter automatic command
cc [#] [.] Clear automatic command
cd [#] Display automatic command
d[d] [x] [c] [s] [b] [w] Display expression
dl[x] <lvar> [w] Display expression
l Display local variables
e Display external variables
p Display execution position pointer
c <line> Display source code at <line>
fs,<expr>,<string> Place <string> at <expr>
ex Exit to dos
The <s> command causes the program to single step one C
source-level statement and then display a message showing
the current function name and line number.
The <t> command traces through "n" C source-level statements
and displays a message after each statement showing the
current function and line number.
The <g> or "go" command causes program execution to begin at
the current position in the program and continue until a
breakpoint is encountered, or until the program terminates.
Optionally, a non-sticky breakpoint can be entered with the
<g> command to cause program execution to stop when the
function name and line number are encountered. The syntax of
the non-sticky breakpoint is <g fname, line> where "fname"
is the function name and "line" is the line number.
The <bs> or breakpoint-set command causes a sticky
breakpoint to be set at function name <fname>, line number
<line>, with an optional count <count>. The <bs> command
causes program execution to stop and control returns to
c-window whenever the function name and line number are
executed <count> times. If the count is omitted, a count of
1 is assumed.
The <bc> command clears a sticky breakpoint. The <fname> and
line number are specified in the same format as used by the
<bs> command. All breakpoints may be cleared simultaneously
by using the <bc .> command.
The <b> command displays all sticky breakpoints. If no
sticky breakpoints are currently set, a message to that
effect is displayed.
The <bx> command sets an expression breakpoint <expr> within
function <fname> at count <count>. An expression breakpoint
differs from a normal breakpoint in the way the break is
determined. With a normal breakpoint, the break occurs when
program execution reaches a certain line in a specified
function. An expression breakpoint, however, operates by
evaluating the given expression <expr>, and a breakpoint
occurs when <expr> is TRUE <count> times. This is one of the
most powerful commands in c-window since boundary conditions
can be checked and execution stopped when known error
conditions occur, instead of repeatedly setting breakpoints
until the error is trapped. All expression breakpoints may
be cleared by following the <bx> commands by a period.
The <cs> command is another very powerful command in
c-window. The <cs> command is used to establish a maximum of
5 automatic commands that are executed each time a single
step, a trace, or a breakpoint occurs. Any command which can
be entered on the c-window command line can be used as an
automatic command. This feature is very helpful when
specific variables are being interrogated frequently, since
the variables are displayed when any action is taken by the
program under test. The <#> specifies the number of the
automatic commands. Automatic commands are always executed
starting from the lowest number (usually 1) and ending with
the highest number found.
The <cc> command can be used to clear automatic commands. If
a number between 1 and 5 is entered, the corresponding
automatic command is cleared. Use <cc .> to clear all
automatic commands.
The <cd #> command displays the automatic command with
number "#" and executes that command. This can be used
almost as a macro in the sense that if an expression
containing many characters is displayed, the expression can
be entered once as an automatic command and then executed by
asking for the display of that automatic command.
The <d> command displays variables in a number of formats.
The default display-format is hexadecimal. This can be
overridden by appending another character to the <d>
command. The available formats are listed below:
dd Display in decimal
dx Display in hexadecimal
dc Display as an ASCII character
ds Display as an ASCII text string
db Display as a byte format hexadecimal dump
dw Display as a word format hexadecimal dump
The <fs> command is used to initialize a character array or
the address pointed to by a pointer, to an ASCII text
string. It is assumed that that the string is null
terminated.
The <l> command displays all local variables declared within
the currently executing function.
The <e> command displays all external (global) variables
declared and used in the currently executing function.
The <p> command (position) displays the current function
name and line number.
The <ex> command terminates execution of both the program
under test and c-window. Control is returned to DOS.