File: trap-out.asm

package info (click to toggle)
svgalib 1%3A1.4.3-24
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 4,768 kB
  • ctags: 9,153
  • sloc: ansic: 59,341; makefile: 1,141; asm: 630; sh: 61; perl: 54; pascal: 49
file content (344 lines) | stat: -rw-r--r-- 15,592 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
; TRAPOUT2.ASM v2.0 by ARK (ark@lhq.com, root@ark.dyn.ml.org) 11-28-97
; Traps IN and OUT instructions in INT 10h and displays DX and AX/AL values.
;
; In the header "T DX/I AX/L", T is the Type of instruction (I=IN, O=OUT),
;  DX/I is the value of DX or the Immediate value if port<256, and AX/L
;  is the value of AX or AL depending on if an 8 or 16 bit value is listed.
;  AX/L is meaningless for IN's since it is the value if AX/L *before* the
;  call to IN.
;
; This is very useful to find information about how your video card works.
; I wrote this to get register dumps for my Trident TVGA9440AGi card so
;  that I could use it under Linux.
;
; NOTE: Pipe the output or you won't see anything!
;  (ex: TRAP-OUT 4F02 0101 > 640x480.256)
;
; New in v2.0:
;  * Traces into INT 10 calls that are called from inside INT 10!
;  * Allows AX and BX values to be specified!
;  * Command line accepts trailing spaces now.
;  x Code to trap INT's also! (T column='N', DX/I=INT ##, AX/L=AX value)
;    (Its commented out - but you can recompile with it if you want)
;
; How to assemble with Borland:
; tasm /ml /zd ncr.asm (case sensitive, line number debug info only)
; tlink /x /t ncr.obj (no map, make com file)
;

.model tiny           ; Tiny memory model, all segments point to the same 64K
.286                  ; This code will run on a 286...           actually, it 
.code                 ; Everything is in the code segment(cs)   will probably
.startup              ; Startup                               run on anything

jmp Start              ; Go to beginning of progam
realINT1 dd 52411A3Eh  ; Address of original INT 01h routine offset
realINT10 dd 3C1B214Bh ; Memory for [es:bx] of the real INT 10h
                       ; (defaults are '>-ARK!-<' just for looks in the .COM)

; strings
no_command_line db 'Use: TRAPOUT2 [AX] [BX]',13,10
db '     Traces all IN/OUT calls inside INT 10h',13,10,36
tracing db 'Tracing INT 10h with AX:',36
bx_msg db ' BX:',36
header db 13,10,'T DX/I AX/L',13,10,36

INT1 proc               ; Interrupt Service Routine for Single Step Debugging
        push ax                                              ; save registers
        push dx
        push es
        push di
        push bp        

        mov bp,sp                  ; set bp to the stack
        push word ptr cs:[bp+12]   ; put the real cs
        pop es                     ;  into es
        push word ptr cs:[bp+10]   ; put the real ip
        pop di                     ;  into di
        mov al,byte ptr es:[di]    ; set al to the next instruction that will
                                   ;  be executed after this INT 01 is done.

; This code will trap INT's also...
;        cmp al,0CDh                ; If al is not CD (INT) keep going
;        jne not_int                ; If it is, display some stuff...
;; This will skip doing the INT's...
;;        add word ptr cs:[bp+10],2  ; Add 2 to the real ip, to skip the INT
;        mov dl,4Eh                 ; Display an N
;        mov ah,02h                 ;  The immediate value/DX is the INT ##
;        int 21h                    ;  that is called. AX is the value before
;        mov dl,20h                 ; Display a space
;        mov ah,02h                 ; 
;        int 21h                    ; Display the immediate value which is
;        jmp is_imm                 ;  reallly the interrupt number called.

    not_int:
        and al,0F4h                ; If al is E4-E7 or EC-EF (all IN/OUT's)
        cmp al,0E4h                ; Then we display our stuff
        jne not_io                 ; Otherwise, do nothing
                                   ; note: 1 more byte of code after this
                                   ; jmp will make it out of range...

        mov al,byte ptr es:[di]         ; Set al to next instruction
        test al,02h                     ; If bit 1 is set then we have an OUT
        jz is_in                        ; If bit 1 is 0, we have an IN

        mov dl,4Fh                                             ; Display an O
        mov ah,02h
        int 21h
        jmp dx_or_imd

    is_in:                                                     ; Display an I
        mov dl,49h
        mov ah,02h
        int 21h

    dx_or_imd:                                              ; Display a space
        mov dl,20h
        mov ah,02h
        int 21h

        mov al,byte ptr es:[di]    ; Set al to next instruction
        test al,08h                ; If bit 3 is set then we are using DX
        jz is_imm                  ; If bit 3 is 0, we are using an immediate

        mov ax,[bp+6]                                      ; restore dx to ax
        call ShowHex                                       ; Display dx
        call ShowHex
        call ShowHex
        call ShowHex
        jmp ax_or_al

    is_imm:
        mov dl,20h                                         ; Display 2 spaces
        mov ah,02h
        int 21h
        mov dl,20h
        mov ah,02h
        int 21h

        mov ah,byte ptr es:[di+1] ; Set ah to byte after the next instruction
        call ShowHex              ; Display the immediate value
        call ShowHex

    ax_or_al:
        mov dl,2Ch                                          ; Display a comma
        mov ah,02h
        int 21h

        mov al,byte ptr es:[di]        ; Set al to next instruction
        test al,01h                    ; If bit 0 is set then we are using AX
        jz is_al                       ; If bit 0 is 0, we are using AL

        mov ax,[bp+8]                                            ; Restore ax
        call ShowHex                                             ; Display ax
        call ShowHex
        call ShowHex
        call ShowHex
        jmp print_next_line

    is_al:
        mov ah,[bp+8]                                      ; Restore al to ah
        call ShowHex                                       ; Display al
        call ShowHex

    print_next_line:
        mov dl,0Dh                                          ; print a newline
        mov ah,02h
        int 21h
        mov dl,0Ah
        mov ah,02h
        int 21h
    
    not_io:
        pop bp                                            ; restore registers
        pop di
        pop es
        pop dx
        pop ax
        iret                                                  ; end interrupt
INT1 endp

; INT 10h that fakes the real INT 10 and sets the trap flag.
INT10 proc                    ; Interrupt Service Routine for Tracing INT 10h
        push ax           ; Save AX
        pushf             ; Put flags on the stack
        pop ax            ; Then into AX
        or ax,0100h       ; Set the trap flag
        push ax           ; Trap Flag calls INT 01h between every instruction
        popf              ; Stuff new flags back into the flags register
        pop ax            ; Restore AX

        cli              ; Fake INT call: clear interrupt flag, skip clearing
        pushf            ;  trap flag, push flags, call to location.
        call cs:[realINT10]      ; This call to INT 10h is be trapped for
                                 ; IN/OUT/INT Normal INT calls would clear
                                 ; the trap flag and then INT 01h would never
                                 ; be called.
        iret                                                  ; end interrupt
INT10 endp

; function that prints the highest 4 bits of ax as text {0-9,A-F} to stdout
; ax will be shifted left 4 bits on return.
ShowHex proc
        push ax                                              ; save registers
        push dx

        shr ax,0Ch                  ; move the highest 4 bits to the lowest 4
        and al,0Fh                  ; limit to lowest 4 bits
        or  al,30h                  ; change range to 30h-3Fh {0-9:;<=>?}
        cmp al,39h                  ; if it is 30h-39h
        jbe is_0_thru_9             ; then its already set
        add al,07h                  ; otherwise change :;<=>? to A-F
    is_0_thru_9:
        mov dl,al
        mov ah,02h
        int 21h

        pop dx                                      ; restore dx
        pop ax                                      ; restore ax
        shl ax,4                                    ; set up ax for next call
        ret                                         ; return
ShowHex endp

Start:                               ; Program begins here
        mov si,0080h                 ; CS:0080h is the command line 
        cmp byte ptr [si],10         ; I want it to be at least 10 bytes long
        jae  process_command_line    ; if not, abort

        mov dx,offset no_command_line        ; ds is preset
        mov ah,09h                           ; Dos function 09h
        int 21h                              ; Display no command line string
        ret                                  ; Exit program

    process_command_line:
        inc si                  ; move si to start of actual string
        mov ax,[si+1]           ; copy first 2 chrs to ax, skipping the space
        mov bx,[si+3]           ; copy 2nd two characters to bx
        sub al,30h              ; subtract 30h so chrs 0-9 have value 0-9
        cmp al,09h              ; if its 0-9, its ok.
        jbe al_is_ok            ; if its not, its probably A-F or a-f
        sub al,07h              ; so subtract 7 more
        and al,0Fh              ; and limit to 0-F
    al_is_ok:
        sub ah,30h              ; do the same to ah
        cmp ah,09h
        jbe ah_is_ok
        sub ah,07h
        and ah,0Fh
    ah_is_ok:
        sub bl,30h              ; do the same to bl
        cmp bl,09h
        jbe bl_is_ok
        sub bl,07h
        and bl,0Fh
    bl_is_ok:
        sub bh,30h              ; do the same to bh
        cmp bh,09h
        jbe bh_is_ok
        sub bh,07h
        and bh,0Fh
    bh_is_ok:
        shl al,04h              ; Combine the values so that AL-AH-BL-BH
        or  ah,al               ; Goes into                  --AH- --AL-
        mov al,bl               ;                            <----AX--->
        shl al,04h
        or  al,bh
        mov word ptr [si],ax    ; store the value over the string
        
        mov ax,[si+6]           ; copy 3rd 2 chrs to ax, skip the 2nd space
        mov bx,[si+8]           ; copy 4th two characters to bx
        sub al,30h              ; subtract 30h so chrs 0-9 have value 0-9
        cmp al,09h              ; if its 0-9, its ok.
        jbe al_is_ok2           ; if its not, its probably A-F or a-f
        sub al,07h              ; so subtract 7 more
        and al,0Fh              ; and limit to 0-F
    al_is_ok2:
        sub ah,30h              ; do the same to ah
        cmp ah,09h
        jbe ah_is_ok2
        sub ah,07h
        and ah,0Fh
    ah_is_ok2:
        sub bl,30h              ; do the same to bl
        cmp bl,09h
        jbe bl_is_ok2
        sub bl,07h
        and bl,0Fh
    bl_is_ok2:
        sub bh,30h              ; do the same to bh
        cmp bh,09h
        jbe bh_is_ok2
        sub bh,07h
        and bh,0Fh
    bh_is_ok2:
        shl al,04h              ; Combine the values so that AL-AH-BL-BH
        or  ah,al               ; Goes into                  --AH- --AL-
        mov al,bl               ;                            <----AX--->
        shl al,04h
        or  al,bh
        mov word ptr [si+2],ax  ; store the value over the string
                             ; Now [si] contains the real values of AX and BX

        mov dx,offset tracing                      ; ds is preset
        mov ah,09h                                 ; Dos function 09h
        int 21h                                    ; Display tracing string
        mov ax,word ptr [si]                       ; Restore ax
        call ShowHex                               ; Display command line
        call ShowHex                               ;  ax value back to user
        call ShowHex                               ;  by placing it in ax
        call ShowHex                               ;  and calling ShowHex
        mov dx,offset bx_msg                       ; ds is preset
        mov ah,09h                                 ; Dos function 09h
        int 21h                                    ; Display bx message
        mov ax,word ptr [si+2]                     ; Restore bx into ax
        call ShowHex                               ; Display command line
        call ShowHex                               ;  bx value back to user
        call ShowHex                               ;  by placing it in ax
        call ShowHex                               ;  and calling ShowHex
        mov dx,offset header                       ; ds is preset
        mov ah,09h                                 ; Dos function 09h
        int 21h                                    ; Display header to output

        mov ax,3501h                ; Dos function 35h, Get vector of INT 01h
        int 21h                     ; Store it in es:bx
        mov word ptr [realINT1],bx   ; Store address of original INT 01h
        mov word ptr [realINT1+2],es ; into realINT1
        
        mov ax,3510h                ; Dos function 35h, Get vector of INT 10h
        int 21h                     ; Store it in es:bx
        mov word ptr [realINT10],bx  ; Store address of original INT 10h
        mov word ptr [realINT10+2],es ; into realINT10 so we can fake an INT

        mov ax,2501h               ; Dos function 25h, Store DS:DX to INT 01h
        mov dx,offset INT1         ; ds is preset, dx is the handler's offset
        int 21h                    ; Set new Single Step handler
        
        mov ax,2510h               ; Dos function 25h, Store DS:DX to INT 10h
        mov dx,offset INT10        ; ds is preset, dx is the handler's offset
        int 21h                    ; Set new Video Interrupt

        mov ax,word ptr [si]             ; We will use the command line ax/bx
        mov bx,word ptr [si+2]           ; values for the fake int call
        int 10h                          ; Call my int 10 which fakes the
                                         ;  real int 10 and traps it.

        mov ax,2501h               ; Dos function 25h, Store DS:DX to INT 01h
        mov dx,word ptr [realINT1] ; ds/dx are in realINT1
        push ds                    ; Save old ds
        push word ptr [realINT1+2] ; Put segment on stack
        pop ds                     ; Set ds to the segment
        int 21h                    ; Reset old Single Step handler
        pop ds                     ; Restore old ds

        mov ax,2510h               ; Dos function 25h, Store DS:DX to INT 10h
        mov dx,word ptr [realINT10] ; ds/dx are in realINT10
        push ds                     ; Save old ds
        push word ptr [realINT10+2] ; Put segment on stack
        pop ds                      ; Set ds to the segment
        int 21h                     ; Reset old Video Interrupt
        pop ds                      ; Restore old ds

        mov ax,0003h               ; Set ax to 3
        int 10h                    ; Set 80x25 Text mode
        ret                        ; End of program
end                                                             ; End of file