home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Unsorted BBS Collection
/
thegreatunsorted.tar
/
thegreatunsorted
/
programming
/
asm_programming
/
ASMTUT1.ZIP
/
DEBUGGER.DOC
< prev
next >
Wrap
Text File
|
1990-08-02
|
15KB
|
296 lines
1
DEBUGGERS
Debuggers are designed to take you through your program step by
step. This allows you to see which instruction is being executed
at each moment, and this in turn allows you to pinpoint the spot
where the program starts doing something you don't want it to do.
In the beginning, debuggers like DEBUG would look at each
instruction and give you the text mnemonic for that instruction.
Each individual instruction has exactly one text mnemonic.
This was better than nothing, but it suffered from several
problems. First, it substituted the address of a variable or
subroutine for the variable or subroutine name. A name like
'result' became 0A84h, a hex number. Secondly, in a high level
language, you know what the source code looks like, but you don't
have the slightest idea what the machine code looks like, and you
don't care. It is nearly impossible to tell where you are in a
PASCAL program by looking at the machine code. You are interested
in what is happening, not in how the compiler generated
instructions for your code.
The general solution to these problems is a SYMBOLIC debugger.
While the compiler or assembler is generating the object file, it
keeps track of what LINE you are on in the text file. Each
instruction is indexed by the text line where it is generated.
This information is passed along to the linker, which processes
it if it is asked to do so . Here is a program which was
assembled once with the symbolic information and once without the
information:
MIT OBJ 1978 7-23-90 4:31p
OHNE OBJ 952 7-23-90 4:31p
MIT.OBJ has the symbolic information, OHNE.OBJ doesn't. As you
can see, this debugging information can take up as much space as
the rest of the file.
When you start up the program under the debugger, the debugger
reads both the executable file and the TEXT file into memory and
displays the appropriate text line for each machine instruction.
In order to use a symbolic debugger, you need to:
1) tell the compiler to generate the debugger information
2) tell the linker to process the information
3) leave your text files UNALTERED.
For MASM, the instructions are:
1) masm /zi filename1 ;
2) link /co filename1+... ;
______________________
The PC Assembler Tutor - Copyright (C) 1990 Chuck Nelson
Debuggers 2
_________
For TASM, the instructions are:
1) tasm /zi filename1 ;
2) tlink /v filename1+... ;
where the dots indicate that you may be linking more than one
file.
It is not necessary for all the object files to have the
debugging information. The debuggers will read the text files for
those parts which have the debugging information and will
generate code like DEBUG for those parts which don't have any
information.
If you have a large program you probably want to concentrate on
the section that is causing the problems. You set a breakpoint
(which is a command to stop execution at a certain spot) for the
start of this section, run the program, and then single step
through the section. That one section is the only place that
needs the symbolic information.
Both Codeview and Turbo Debugger do much the same thing. Here is
the Turbo screen:
*************************** TURBO SCREEN {1} ***************************
File View Run Breakpoints Data Window Options READY
.Module: debugtst File: debugtst.asm 74.................................1.
. .
. start: push ds ; set up for return .Registers......3. .
. sub ax,ax . ax 5C94 .c=0. .
. push ax . bx 0000 .z=1. .
. . cx 0000 .s=0. .
. mov ax, DATASTUFF ; load ds . dx 0000 .o=0. .
. mov ds,ax . si 0000 .p=1. .
. . di 0000 .a=0. .
. outer_loop: . bp 0000 .i=1. .
. lea ax, multiplicand ; load multi. sp 09FA .d=0. .
. call get_unsigned_8byte . ds 4AD6 . . .
. call print_unsigned_8byte . es 4A26 . . .
. call get_unsigned ; unsigned w. ss 4A36 . . .
. mov multiplier, ax . cs 4B27 . . .
. . ip 0019 . . .
. .................. .
. lea si, multiplicand ; load pointers .
...........................................................................
.Watches.................................................................2.
.multiplier,d 23700 .
.multiplicand qword 00000042E843515D .
...........................................................................
F1-Help F2-Bkpt F3-Close F4-Here F5-Zoom F6-Next F7-Trace F8-Step F9-Run
******************************* END TURBO *******************************
Here's the Codeview screen:
____________________
1. Turbo Debugger Version 1.5
Copyright (C) 1988, 1989 Borland International
Debuggers 3
_________
************************* CODEVIEW SCREEN {2} ***************************
.File View Search Run Watch Options Language Calls Help .
F8=Trace F5=Go
.......................... debugtst.ASM ..................................
73: main proc far . AX = 0000
74: . BX = 0000
75: start: push ds ; set up for return . CX = 0000
76: sub ax,ax . DX = 0000
77: push ax . SP = 0A00
78: . BP = 0000
79: mov ax, DATASTUFF ; load ds . SI = 0000
80: mov ds,ax . DI = 0000
81: . DS = 44FD
82: outer_loop: . ES = 44FD
83: lea ax, multiplicand ; load multipli. SS = 450D
84: call get_unsigned_8byte . CS = 4601
85: call print_unsigned_8byte . IP = 0000
86: call get_unsigned ; unsigned word.
87: mov multiplier, ax . NV UP
88: . EI PL
89: . NZ NA
90: lea si, multiplicand ; load pointers. PO NC
.........................................................................
Microsoft (R) CodeView (R) Version 2.2
(C) Copyright Microsoft Corp. 1986-1988. All rights reserved.
>
***************************** END CODEVIEW *****************************
As you can see, they look almost the same and they operate
similarly. The Borland people (Turbo Debugger) have gone an extra
step and have made it possible to use Turbo Debugger with both
Borland and Microsoft high-level languages.
I/O AND ASMHELP
All programs do output. These two debuggers deal with this by
reserving a section of video memory for the program's output. You
put output in one place in memory and the debugger puts output in
a different place. As long as things are being done in an orderly
manner, when your screen is doing output your screen is visible
and when the debugger has charge its screen is showing.
The problem here is that your program may take only 1/100 of a
second to write to the screen. This will appear as a flash on the
screen. You won't see anything. Both debuggers allow you to
toggle back and forth between the debugger screen and your
screen. This is tedious, but it works.
In order to alleviate the problem, ASMHELP has a timer. You
____________________
2. Microsoft (R) CodeView (R) Version 2.2
(C) Copyright Microsoft Corp. 1986-1988.
All rights reserved.
Debuggers 4
_________
activate the timer with:
mov al, # ; # is a number from 1 to 5
call set_timer
where you put a number from 1 to 5 in AL. You deactivate it with:
call kill_timer
You put a number from 1 to 5 in AL before the call to
'set_timer'. This will create a 1 to 5 second delay. From that
point on, every time a print function in ASMHELP is called, it
will show the screen for the specified number of seconds. If you
put a number larger than 5 in AL:
mov al, 120
call set_timer
ASMHELP will require you to press the ENTER key before
continuing. This allows you to view the user screen as much time
or as little time as you want.
The idea here is for you to set the timer at the beginning of
your program. Then the rest of the program will have the extended
viewing time for the print functions.
D86
D86 is what I'd call a semi-symbolic debugger. It does not use
line information - it uses a symbol table. This is a list of
symbols in the program along with where they appear in the code.
This is much better than DEBUG but is not as valuable as using
the text files. It also means that it can't work that well with
high-level languages. Here is the D86 output from the same piece
of code:
*************************** D86 SCREEN {3} ***************************
START: B Set permanent breakpoints
# 0000 PUSH DS F Find MARKed memory bytes
0001 SUB AX,AX G Go, until address(es) reached
0003 PUSH AX J Jump within this code segment
0004 MOV AX,0253F L List disassembly to LST file
0007 MOV DS,AX O set operating system-call traps
OUTER_LOOP: Q Quit debugging session
0009 MOV AX,8 W Write program and SYM to disk
000C CALL 0151A
000F CALL 01253 Alt-F9 restore trashed screen
0012 CALL 069B Shift-F7 set MARK at CS:IP
0015 MOV MULTIPLIER,AX Home Jump last-trap/prog-start
0018 MOV SI,8
001B MOV BX,012
____________________
3. D86 Version 3.22 (C) Copyright 1990 Eric Isaacson
Debuggers 5
_________
AX 0929 1:
BX 001A IP 0000 2:
CX 0000 CS 2593 3:
DX 0000 SS 249F 4:
SI 0010 DS 253F 5:
DI 0000 ES 248F 6:
BP 42D9 SP 09F2 6: 001A 06B1 F202 0015 0000 248F
g 0015
****************************** END D86 *******************************
As you can see, D86 has lost some of the information, but you can
follow this as long as you have a printout of the text file at
your side.
D86 has some weaknesses. It makes no allowance for user output,
so all user output is either erased immediately or is mixed with
the information on the debugger screen. It has no key to let you
jump over subroutines (you either need to go through the whole
subroutine or set a breakpoint after every subroutine call).
Finally, it alters the counter which keeps track of where you are
in the program.
When using a debugger you want to scroll through the program to
find places where you want to stop, and then set breakpoints. If
you scroll with D86, it will change the program location. If you
don't know the EXACT location where you were before you started
scrolling, you can't get back to continue debugging the program.
You need to reload the file and start over again. Think of what
this would mean if you had been working on a program for 15
minutes. Why D86 does this is completely beyond me.