ZeePedia

Debug Interrupts: Debugger using single step interrupt, breakpoint interrupt

<< Real Time Interrupts and Hardware Interfacing
Multitasking: Concept, Elaborate, Multitasking Kernel as TSR >>
img
10
Debug Interrupts
10.1. DEBUGGER USING SINGLE STEP INTERRUPT
The use of the trap flag has been deferred till now. The three flags not used
for mathematical operations are the direction flag, the interrupt flag and the
trap flag. The direction and interrupt flags have been previously discussed.
If the interrupt flag is set, the after every instruction a type 1 interrupt will
be automatically generated. When the IVT and reserved interrupts were
discussed this was named as the single step interrupt. This is like the divide
by zero interrupt which was never explicitly invoked but it came itself. The
single step interrupt behaves in the same manner.
The debugger is made using this interrupt. It allows one instruction to be
executed and then return control to us. It has its display code and its code to
wait for the key in the INT 1 handler. Therefore after every instruction the
values of all registers are shown and the debugger waits for a key. Another
interrupt used by the debugger is the break point interrupt INT 3. Apart from
single stepping debugger has the breakpoint feature. INT 3 is used for this
feature. INT 3 has a single byte opcode so it can replace any instruction. To
put a breakpoint the instruction is replaced with INT 3 opcode and restored
in the INT 3 handler. The INT 3 opcode is placed again by a single step
interrupt that is set up for this purpose after the replaced instruction has
been executed.
There is no instruction to set or clear the trap flag like there are
instructions for the interrupt and direction flags. We use two special
instructions PUSHF and POPF to push and pop the flag from the stack. We
use PUSHF to place flags on the stack, change TF in this image on the stack
and then reload into the flags register with POPF. The single step interrupt
will come after the first instruction after POPF. The interrupt mechanism
automatically clears IF and TF otherwise there would an infinite recursion of
the single step interrupt. The TF is set in the flags on the stack so another
interrupt will comes after one more instruction is executed after the return of
the interrupt.
The following example is a very elementary debugger using the trap flag
and the single step interrupt.
Example 10.1
001
; single stepping using the trap flag and single step interrupt
002
[org 0x0100]
003
jmp start
004
005
flag:
db
0
; flag whether a key pressed
006
oldisr:
dd
0
; space for saving old ISR
007
names:
db
'FL =CS =IP =BP =AX =BX =CX =DX =SI =DI =DS =ES ='
008
009-026
;;;;; COPY LINES 008-025 FROM EXAMPLE 6.2 (clrscr) ;;;;;
027
028
; subroutine to print a number on screen
029
; takes the row no, column no, and number to be printed as parameters
030
printnum:
push bp
031
mov  bp, sp
032
push es
033
push ax
034
push bx
035
push cx
img
Computer Architecture & Assembly Language Programming
Course Code: CS401
CS401@vu.edu.pk
036
push dx
037
push di
038
039
mov
di,
80
;
load di with columns per row
040
mov
ax,
[bp+8]
;
load ax with row number
041
mul
di
;
multiply with columns per row
042
mov
di,
ax
;
save result in di
043
add
di,
[bp+6]
;
add column number
044
shl
di,
1
;
turn into byte count
045
add
di,
8
;
to end of number location
046
047
mov
ax,
0xb800
048
mov
es,
ax
;
point es to video base
049
mov
ax,
[bp+4]
;
load number in ax
050
mov
bx,
16
;
use base 16 for division
051
mov
cx,
0
;
initialize count of digits
052
053
nextdigit:
mov  dx, 0
;
zero upper half of dividend
054
div  bx
;
divide by 10
055
add  dl, 0x30
;
convert digit into ascii value
056
cmp  dl, 0x39
;
is the digit an alphabet
057
jbe  skipalpha
;
no, skip addition
058
add  dl, 7
;
yes, make in alphabet code
059
skipalpha:
mov  dh, 0x07
;
attach normal attribute
060
mov [es:di], dx
;
print char on screen
061
sub  di, 2
;
to previous screen location
062
loop nextdigit
;
if no divide it again
063
064
pop
di
065
pop
dx
066
pop
cx
067
pop
bx
068
pop
ax
069
pop
es
070
pop
bp
071
ret
6
072
073
; subroutine to print a string
074
; takes row no, column no, address of string, and its length
075
; as parameters
076
printstr:
push bp
077
mov bp, sp
078
push es
079
push ax
080
push bx
081
push cx
082
push dx
083
push si
084
push di
085
086
mov
ax, 0xb800
087
mov
es, ax
; point es to video base
088
089
mov
di,
80
;
load di with columns per row
090
mov
ax,
[bp+8]
;
load ax with row number
091
mul
di
;
multiply with columns per row
092
mov
di,
ax
;
save result in di
093
add
di,
[bp+6]
;
add column number
094
shl
di,
1
;
turn into byte count
095
096
mov
si, [bp+6]
; string to be printed
097
mov
cx, [bp+4]
; length of string
098
mov
ah, 0x07
; normal attribute is fixed
099
100
nextchar:
mov
al, [si]
;
load next char of string
101
mov
[es:di], ax
;
show next char on screen
102
add
di, 2
;
move to next screen location
103
add
si, 1
;
move to next char
104
loop
nextchar
;
repeat the operation cx times
105
106
pop
di
107
pop
si
108
pop
dx
109
pop
cx
110
pop
bx
111
pop
ax
126
img
Computer Architecture & Assembly Language Programming
Course Code: CS401
CS401@vu.edu.pk
112
pop
es
113
pop
bp
114
ret
8
115
116
; keyboard interrupt service routine
117
kbisr:
push ax
118
119
in
al, 0x60
;
read a char from keyboard port
120
test
al, 0x80
;
is it a press code
121
jnz
skipflag
;
no, leave the interrupt
123
add
byte [cs:flag], al
;
yes, set flag to proceed
124
125
skipflag:
mov  al, 0x20
126
out  0x20, al
127
pop  ax
128
iret
129
130
; single step interrupt service routine
131
trapisr:
push bp
132
mov bp, sp
; to read cs, ip and flags
133
push ax
134
push bx
135
push cx
136
push dx
137
push si
138
push di
139
push ds
140
push es
141
142
sti
; waiting for keyboard interrupt
143
push cs
144
pop  ds
; initialize ds to data segment
145
146
mov  byte [flag], 0
; set flag to wait for key
147
call clrscr
; clear the screen
148
149
mov
si,
6
;
first
register is at bp+6
150
mov
cx,
12
;
total
12 registers to print
151
mov
ax,
0
;
start
from row 0
152
mov
bx,
5
;
print
at column 5
153
154
l3:
push
ax
; row number
155
push
bx
; column number
156
mov
dx, [bp+si]
157
push
dx
;
number to be printed
158
call
printnum
;
print the number
159
sub
si, 2
;
point to next register
160
inc
ax
;
next row number
161
loop
l3
;
repeat for the 12 registers
162
163
mov
ax,
0
;
start from row 0
164
mov
bx,
0
;
start from column 0
165
mov
cx,
12
;
total 12 register names
166
mov
si,
4
;
each name length is 4 chars
167
mov
dx,
names
;
offset of first name in dx
168
169
l1:
push
ax
;
row number
170
push
bx
;
column number
171
push
dx
;
offset of string
172
push
si
;
length of string
173
call
printstr
;
print the string
174
add
dx, 4
;
point to start of next string
175
inc
ax
;
new row number
176
loop
l1
;
repeat for 12 register names
177
178
keywait:
cmp
byte [flag], 0
; has a key been pressed
179
je
keywait
; no, check again
180
181
pop
es
182
pop
ds
183
pop
di
184
pop
si
185
pop
dx
186
pop
cx
187
pop
bx
188
pop
ax
127
img
Computer Architecture & Assembly Language Programming
Course Code: CS401
CS401@vu.edu.pk
189
pop  bp
190
iret
191
192
start:
xor
ax, ax
193
mov
es, ax
; point es to IVT base
194
mov
ax, [es:9*4]
195
mov
[oldisr], ax
; save offset of old routine
196
mov
ax, [es:9*4+2]
197
mov
[oldisr+2], ax
; save segment of old routine
198
mov
word [es:1*4], trapisr ; store offset at n*4
199
mov
[es:1*4+2], cs
; store segment at n*4+2
200
cli
; disable interrupts
201
mov
word [es:9*4], kbisr ; store offset at n*4
202
mov
[es:9*4+2], cs
; store segment at n*4+2
203
sti
; enable interrupts
204
205
pushf
;
save flags on stack
206
pop  ax
;
copy flags in ax
207
or
ax, 0x100
;
set bit corresponding to TF
208
push ax
;
save ax on stack
209
popf
;
reload into flags register
210
211
; the trap flag bit is
on now, INT 1 will come after next instruction
212
; sample code to check
the working of our elementary debugger
213
mov  ax,
0
214
mov  bx,
0x10
215
mov  cx,
0x20
216
mov  dx,
0x40
217
218
l2:
inc
ax
219
add
bx, 2
220
dec
cx
221
sub
dx, 2
222
jmp
l2
10.2. DEBUGGER USING BREAKPOINT INTERRUPT
We now write a debugger using INT 3. This debugger stops at the same
point every time where the breakpoint has been set up unlike the previous
one which stopped at every instruction. The single step interrupt in this
example is used only to restore the breakpoint interrupt which was removed
by the breakpoint interrupt handler temporarily so that the original
instruction can be executed.
Example 10.2
001
; elementary debugger using breakpoint interrupt
002
[org 0x0100]
003
jmp start
004
005
flag:
db
0
; flag whether a key pressed
006
oldisr:
dd
0
; space for saving old ISR
007
names:
db
'FL =CS =IP =BP =AX =BX =CX =DX =SI =DI =DS =ES ='
008
opcode:
db 0
009
opcodepos:
dw 0
010
011-028
;;;;;
COPY
LINES
008-025
FROM
EXAMPLE
6.2 (clrscr) ;;;;;
029-072
;;;;;
COPY
LINES
028-071
FROM
EXAMPLE
10.1 (printnum) ;;;;;
073-114
;;;;;
COPY
LINES
073-114
FROM
EXAMPLE
10.1 (printstr) ;;;;;
115-127
;;;;;
COPY
LINES
116-128
FROM
EXAMPLE
10.1 (kbisr) ;;;;;
128
129
; single step interrupt service routine
130
trapisr:
push bp
131
mov  bp, sp
132
push ax
133
push di
134
push ds
135
push es
136
137
push cs
138
pop  ds
; initialize ds to data segment
128
img
Computer Architecture & Assembly Language Programming
Course Code: CS401
CS401@vu.edu.pk
139
140
mov
ax, [bp+4]
141
mov
es, ax
;
load interrupted segment in es
142
mov
di, [opcodepos]
;
load saved opcode position
143
mov
byte [es:di], 0xCC ;
reset the opcode to INT3
144
and
word [bp+6], 0xFEFF;
clear TF in flags on stack
145
146
pop
es
147
pop
ds
148
pop
di
149
pop
ax
150
pop
bp
151
iret
152
153
; breakpoint interrupt service routine
154
debugisr:
push bp
155
mov  bp, sp
; to read cs, ip and flags
156
push ax
157
push bx
158
push cx
159
push dx
160
push si
161
push di
162
push ds
163
push es
164
165
sti
; waiting for keyboard interrupt
166
push cs
167
pop  ds
; initialize ds to data segment
168
169
mov
ax, [bp+4]
170
mov
es, ax
; load interrupted segment in es
171
dec
word [bp+2]
; decrement the return address
172
mov
di, [bp+2]
; read the return address in di
173
mov
word [opcodepos], di ; remember the return position
174
mov
al, [opcode]
; load the original opcode
175
mov
[es:di], al
; restore original opcode there
176
177
mov  byte [flag], 0
; set flag to wait for key
178
call clrscr
; clear the screen
179
180
mov
si,
6
;
first
register is at bp+6
181
mov
cx,
12
;
total
12 registers to print
182
mov
ax,
0
;
start
from row 0
183
mov
bx,
5
;
print
at column 5
184
185
l3:
push
ax
; row number
186
push
bx
; column number
187
mov
dx, [bp+si]
188
push
dx
;
number to be printed
189
call
printnum
;
print the number
190
sub
si, 2
;
point to next register
191
inc
ax
;
next row number
192
loop
l3
;
repeat for the 12 registers
193
194
mov
ax,
0
;
start from row 0
195
mov
bx,
0
;
start from column 0
196
mov
cx,
12
;
total 12 register names
197
mov
si,
4
;
each name length is 4 chars
198
mov
dx,
names
;
offset of first name in dx
199
200
l1:
push
ax
;
row number
201
push
bx
;
column number
202
push
dx
;
offset of string
203
push
si
;
length of string
204
call
printstr
;
print the string
205
add
dx, 4
;
point to start of next string
206
inc
ax
;
new row number
207
loop
l1
;
repeat for 12 register names
208
209
or word [bp+6], 0x0100
; set TF in flags image on stack
210
211
keywait:
cmp
byte [flag], 0
; has a key been pressed
212
je
keywait
; no, check again
213
214
pop es
129
img
Computer Architecture & Assembly Language Programming
Course Code: CS401
CS401@vu.edu.pk
215
pop ds
216
pop di
217
pop si
218
pop dx
219
pop cx
220
pop bx
221
pop ax
222
pop bp
223
iret
224
225
start:
xor
ax, ax
226
mov
es, ax
; point es to IVT base
227
mov
word [es:1*4], trapisr ; store offset at n*4
228
mov
[es:1*4+2], cs
; store segment at n*4+2
229
mov
word [es:3*4], debugisr ; store offset at n*4
230
mov
[es:3*4+2], cs
; store segment at n*4+2
231
cli
; disable interrupts
232
mov
word [es:9*4], kbisr ; store offset at n*4
233
mov
[es:9*4+2], cs
; store segment at n*4+2
234
sti
; enable interrupts
235
236
mov
si, l2
;
load breakpoint position in si
237
mov
al, [cs:si]
;
read opcode at that position
238
mov
[opcode], al
;
save opcode for later use
239
mov
byte [cs:si], 0xCC
;
change opcode to INT3
240
241
; breakpoint is set now, INT3 will come at l2 on every iteration
242
; sample code to check the working of our elementary debugger
243
mov ax, 0
244
mov bx, 0x10
245
mov cx, 0x20
246
mov dx, 0x40
247
248
l2:
inc
ax
249
add
bx, 2
250
dec
cx
251
sub
dx, 2
252
jmp
l2
130