home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / trace.zip / TRACE.ASM < prev    next >
Assembly Source File  |  1986-04-08  |  70KB  |  2,932 lines

  1.     page    60,132
  2.     .lfcond
  3.     title    "TRACE - Interrupt Tracer"
  4.     subttl    Introduction
  5.     page
  6.     comment    \
  7.  
  8. TRACE is an INT tracer. It traps INT's, traces the registers at the entry
  9. to the INT, executes the INT itself, and then traces the regs at exit from
  10. the INT. It also allows the user at the keyboard to see all of this traced
  11. information, either at the screen or on the printer.
  12.  
  13. The INT's that are to be traced are specified in the source code (see config
  14. section below). Once defined, they may be enabled or disabled from the
  15. keyboard.
  16.  
  17.       <<< REBOOT AS SOON AS POSSIBLE AFTER INVOKING TRACE!!! >>>
  18.  
  19. This is not foolproof or bugfree. We use it 'cause it's a terrific tool
  20. for deprotecting copy-protected software. You use it at your own risk.
  21. When you've gotten a printout of the trace activity that interests you,
  22. reboot your system. Don't say that we didn't warn you.
  23.  
  24. Enjoy.
  25.  
  26.     \
  27.     page
  28. code    segment    para 'code'
  29.     assume    cs:code,ds:code
  30.     org    0100h
  31. start:    jmp    init
  32.  
  33. ;********************************************************
  34. ;
  35. ; Definition of one interrupt control table
  36. ;
  37. ;********************************************************
  38.  
  39. ICT             struc
  40. ICT_flags       db      ?       ;See below
  41. ICT_intnum      db      ?       ;interrupt # this table belongs to
  42. ICT_AH_lo       db      ?       ;lower AH limit to trace
  43. ICT_AH_hi       db      ?       ;upper AH limit to trace
  44. ICT_orig_hndlr  dd      ?       ;cs:ip of original handler
  45. ICT_hits    dw      ?       ;# traces made for this ICT
  46. ICT_num        db      ?       ;ICT number (0-7)
  47. ICT             ends
  48.  
  49. ;
  50. ; Equates for flags byte of ICT
  51. ;
  52.  
  53. F_ACTIVE    equ    10000000b    ;Bit 7 = this ICT is active
  54. F_RET        equ    01000000b    ;Bit 6 = This INT exits via RET
  55. F_RET2        equ    00100000b    ;Bit 5 = This INT exits via RET2
  56. F_IRET        equ    00010000b    ;Bit 4 = This INT exits via IRET
  57. F_ENABLE    equ    00001000b    ;Bit 3 = Tracing enabled for this ICT
  58. F_FCB        equ    00000100b    ;Bit 2 = enable FCB/ASCII traces for INT 21h
  59. F_ROM        equ    00000010b    ;Bit 1 = exclude ROM invocations of this INT
  60. F_BELOW        equ    00000001b    ;Bit 0 = exclude invokers below us (DOS etc)
  61.  
  62.     page
  63. ;*******************************************************
  64. ;    B E G I N     C O N F I G U R A T I O N
  65. ;*******************************************************
  66.  
  67. ;
  68. ; Set trace_size to number of bytes to set aside for trace table.
  69. ;
  70.  
  71. trace_size    equ    30000
  72.  
  73. ;
  74. ; Set peri_int to the interrupt number (usually 060H) to be used
  75. ; by Periscope to invoke our reporting routines.
  76. ;
  77.  
  78. peri_int    equ    060h
  79.  
  80. ;
  81. ; Set prt_scr non-zero to assemble code that allows control via SHIFT-PrtSc.
  82. ;
  83.  
  84. prt_scr        equ    1
  85.  
  86. ;
  87. ; Set use_prt non-zero to start up using the printer instead of the screen
  88. ;
  89.  
  90. use_prt        equ    0
  91.  
  92. ;
  93. ; Set num_feeds to number of extra Linefeeds to send to printer to jack
  94. ; up the paper enough to let you read it, after display of menus etc.
  95. ;
  96.  
  97. num_feeds    equ    10
  98.  
  99.  
  100. ;
  101. ; Define interrupts to be traced by filling in the following ICT's.
  102. ; Note that there are only 8. That's the max that can be traced.
  103. ; Note that the F_ACTIVE flag must be set in used ICT's, and off in
  104. ; those that aren't defining something that you want traced.
  105. ;
  106. ; Don't mess with the last 3 fields in the ICT!!! Leave 'em as-is.
  107. ;
  108. ;   It is EXTREMELY important that you specify how the interrupt exits.
  109. ;   Set exactly one of the following flag bits:
  110. ;
  111. ;   F_RET   Interrupt exits via simple far RET, leaving original interrupts
  112. ;           on the stack for the caller to pop. INT's 025H and 026H are prime
  113. ;           examples.
  114. ;
  115. ;   F_RET2  Interrupt exits via RET 2, dropping original flags and returning
  116. ;           flags as set by interrupt handler. INT 021H (and anybody else
  117. ;           that uses flags like CARRY or ZERO to reflect results) does this.
  118. ;
  119. ;   F_IRET  Interrupt exits via IRET, restoring original flags from stack.
  120. ;           Hardware interrupt handlers do this, and many ROM BIOS routines.
  121. ;
  122. ;   Note that some interrupts may exit differently, depending on the specific
  123. ;   function requested. You may want to define several ICT's for a given
  124. ;   interrupt, each handling a different AH range.
  125. ;
  126. ;
  127.  
  128. ict0    ICT     <F_ACTIVE+F_RET2+F_ENABLE+F_FCB,021H,0dh,0ffh,0,0,0>    ;DOS funcs 0Dh thru FFh
  129. ict1    ICT     <F_ACTIVE+F_RET2+F_ENABLE,013H,0,0ffh,0,0,1>        ;ROM BIOS INT 13h (all)
  130. ict2    ICT     <F_ACTIVE+F_RET2,021H,0,0ch,0,0,2>            ;DOS funcs 00h thru 0Ch
  131. ict3    ICT     <F_ACTIVE+F_RET+F_ENABLE,025h,0,0ffh,0,0,3>        ;RAW disk I/O
  132. ict4    ICT     <F_ACTIVE+F_RET+F_ENABLE,026h,0,0ffh,0,0,4>        ;RAW disk I/O
  133. ict5    ICT     <0,0,0,0,0,0,5>                        ;unused
  134. ict6    ICT     <0,0,0,0,0,0,6>                        ;unused
  135. ict7    ICT     <0,0,0,0,0,0,7>                        ;unused
  136.  
  137.  
  138. ;*******************************************************
  139. ;    E N D    C O N F I G U R A T I O N
  140. ;*******************************************************
  141.     page
  142. ;
  143. ; Trace entry byte zero (the type byte) identifies entry as follows:
  144. ;   Bits 7-4 = trace type
  145. ;
  146. ;               0000 = BEFORE int was executed
  147. ;               0001 = AFTER int was executed
  148. ;               0010 = FCB referenced by an INT 21h
  149. ;               0011 = ASCIIZ referenced by an INT 21h
  150. ;
  151. ;   Bit 3    = RESERVED
  152. ;
  153. ;   Bits 2-0 = ICT # (0-7) which made this trace record
  154. ;
  155. ; Record formats are as follows:
  156. ;
  157.  
  158. BEFORE        struc        ;BEFORE trace entry
  159. B_type        db    ?    ;see above
  160. B_int        db    ?    ;INT # that was trapped
  161. B_ax        dw    ?    ;Regs BEFORE executing INT
  162. B_bx        dw    ?
  163. B_cx        dw    ?
  164. B_dx        dw    ?
  165. B_es        dw    ?
  166. B_ds        dw    ?
  167. B_ss        dw    ?
  168. B_sp        dw    ?
  169. B_si        dw    ?
  170. B_di        dw    ?
  171. B_bp        dw    ?
  172. B_cs        dw    ?    ;CS of invoker of INT
  173. B_ip        dw    ?    ;IP of invoker
  174. BEFORE        ends
  175.  
  176. AFTER        struc        ;AFTER record type
  177. A_type        db    ?    ;see above
  178. A_int        db    ?    ;INT # that was executed
  179. A_ax        dw    ?    ;Regs AFTER executing INT
  180. A_bx        dw    ?
  181. A_cx        dw    ?
  182. A_dx        dw    ?
  183. A_es        dw    ?
  184. A_ds        dw    ?
  185. A_si        dw    ?
  186. A_di        dw    ?
  187. A_bp        dw    ?
  188. A_flags        dw    ?    ;Flags AFTER doing INT
  189. AFTER        ends
  190.  
  191. FCB        struc            ;INT 21h FCB record
  192. FCB_type     db    ?        ;see above
  193. FCB_int        db    ?        ;INT # that was executed (21h)
  194. FCB_drive    db    ?        ;drive field of FCB
  195. FCB_name    db    "????????"    ;filename field of FCB
  196. FCB_ext        db    "???"        ;extension field of FCB
  197. FCB        ends
  198.  
  199. ASCIIZ        struc            ;INT 21h ASCIIZ record
  200. AZ_type     db    ?        ;see above
  201. AZ_int        db    ?        ;INT # that was executed (21h)
  202. AZ_str        db    "?????????????????????????????????????????????????????????????????"
  203. ASCIIZ        ends
  204.  
  205.     subttl  Resident Storage
  206.     page
  207.  
  208. ;
  209. ; Things defined here are present even after we become resident and
  210. ; exit to DOS.
  211. ;
  212.  
  213. ;
  214. ; Definitions used by print_edit()
  215. ;
  216.  
  217. Edit_End    equ    0f0h    ;End of input line
  218. Edit_Byte    equ    0f1h    ;Next byte is 8-bit value to be printed in hex
  219. Edit_Word    equ    0f2h    ;Next 2 bytes are 16-bit value to be printed in hex
  220. Edit_Line    equ    0f3h    ;Next 2 bytes are address of string for print_line()
  221. Edit_Call    equ    0f4h    ;Next byte is AH arg, next 2 are DX arg,
  222.                 ;and next 2 are subroutine address to call
  223. Edit_Dec8    equ    0f5h    ;Next byte is 8-bit value to be printed as decimal
  224. Edit_Dec16    equ    0f6h    ;Next 2 bytes are 16-bit value to be printed as decimal
  225. Edit_Skip    equ    0f7h    ;Ignore this byte (don't display it)
  226.  
  227. ;********************************************************
  228. ;
  229. ; Index table pointing to all ICT's
  230. ;
  231. ;********************************************************
  232.  
  233. ict_index label word
  234.     dw      offset ict0
  235.     dw      offset ict1
  236.     dw      offset ict2
  237.     dw      offset ict3
  238.     dw      offset ict4
  239.     dw      offset ict5
  240.     dw      offset ict6
  241.     dw      offset ict7
  242.  
  243. ;********************************************************
  244. ;
  245. ; Index table pointing to all handlers
  246. ;
  247. ;********************************************************
  248.  
  249. hndlr_index label word
  250.     dw      offset handler0
  251.     dw      offset handler1
  252.     dw      offset handler2
  253.     dw      offset handler3
  254.     dw      offset handler4
  255.     dw      offset handler5
  256.     dw      offset handler6
  257.     dw      offset handler7
  258.  
  259. ;********************************************************
  260. ;
  261. ; Trace table itself, with plenty of room
  262. ;
  263. ;********************************************************
  264.  
  265. next_byte       dw      offset trace_table      ;address of next entry
  266.  
  267. trace_table     db      trace_size dup (0)
  268.  
  269. last_byte       db      80 dup (0)          ;sloppy way of handling overflow
  270.  
  271. ;********************************************************
  272. ;
  273. ; Table of sizes for each trace record type. Must be in same
  274. ; order as record types themselves.
  275. ;
  276. ;********************************************************
  277.  
  278. rec_sizes    label    word
  279.         dw    size BEFORE
  280.         dw    size AFTER
  281.         dw    size FCB
  282.         dw    size ASCIIZ
  283.  
  284. ;********************************************************
  285. ;
  286. ; Table of INT 21h functions that include an FCB pointer in DS:DX
  287. ;
  288. ;********************************************************
  289.  
  290. FCB_table    label    byte
  291.         db    0fh,10h,11h,12h,13h,14h,15h,16h,17h,21h,22h,23h,24h,27h,28h
  292. FCB_end        label    byte
  293.  
  294.  
  295. ;********************************************************
  296. ;
  297. ; Table of INT 21h functions that include an ASCIIZ pointer in DS:DX
  298. ;
  299. ;********************************************************
  300.  
  301. ASCIIZ_table    label    byte
  302.         db    4bh,3ch,3dh,41h,43h,4eh,56h,5ah,5bh,39h,3ah,3bh
  303. ASCIIZ_end    label    byte
  304.  
  305. ;********************************************************
  306. ;
  307. ; Misc storage
  308. ;
  309. ;********************************************************
  310.  
  311. our_cs          dw      0               ;our CS (not for segment checking)
  312. test_cs         dw      0               ;our normalized CS (for segment checking)
  313. long_addr       dd      0               ;for long JMP's and CALLs
  314. our_ICT         dw      0               ;for quick save of our ICT pointer
  315. our_flags    db    0            ;for quick save of our ICT flags
  316. prt_base    dw    0            ;base I/O address of printer
  317. prt_flag    db    0            ;non-zero to send output to printer
  318.         db    255 dup (0)        ;stack for Periscope Int handler
  319. our_tos        dw    0            ;top of that stack
  320. stack_inuse    db    0            ;non-zero when above stack is in use
  321. save_ss        dw    0            ;for stack-swapping
  322. save_sp        dw    0
  323.  
  324.  
  325.     subttl  Interrupt Trappers and Tracing
  326.     page
  327.  
  328. ;********************************************************
  329. ;
  330. ; Interrupt handler entry points for each ICT
  331. ;
  332. ;********************************************************
  333.  
  334. handler macro   ictloc
  335.     cli                ;*** NO INTERRUPTS!!! ***
  336.     push    bp              ;save stack pointer, so that...
  337.     mov     bp,sp           ;...we can ref things via BP
  338.     push    bx              ;set BX to point to ICT
  339.     mov     bx,offset cs:ictloc
  340.     jmp     short int_common    ;goto common code
  341.     endm
  342.  
  343. interrupt proc  far
  344.  
  345. handler0:
  346.     handler ict0
  347.  
  348. handler1:
  349.     handler ict1
  350.  
  351. handler2:
  352.     handler ict2
  353.  
  354. handler3:
  355.     handler ict3
  356.  
  357. handler4:
  358.     handler ict4
  359.  
  360. handler5:
  361.     handler ict5
  362.  
  363. handler6:
  364.     handler ict6
  365.  
  366. handler7:
  367.     handler ict7
  368.  
  369.  
  370. int_common:
  371.  
  372.     push    ax
  373.  
  374. ;********************************************************
  375. ;
  376. ; Common code for all trapped INT's.
  377. ;
  378. ; At this point:
  379. ;
  380. ;   BX holds ICT address.
  381. ;   BP points to stack as follows:
  382. ;
  383. ;                   AX
  384. ;                   BX
  385. ;      (BP) ---->   BP
  386. ;               +2  IP    of caller
  387. ;               +4  CS    of caller
  388. ;               +6  FLAGS of caller
  389. ;
  390. ;********************************************************
  391.  
  392.     test    cs:[bx].ICT_flags,F_ENABLE    ;tracing enabled for this ICT?
  393.     jz      no_trace                ;no, don't trace it
  394.     cmp     ah,cs:[bx].ICT_AH_lo        ;is AH within bounds?
  395.     jb      no_trace                ;no, don't trace it
  396.     cmp     ah,cs:[bx].ICT_AH_hi
  397.     ja      no_trace                ;no, don't trace it
  398.  
  399. ;
  400. ; See if we should check caller's CS:IP
  401. ;
  402.  
  403.     test    cs:[bx].ICT_flags,F_BELOW+F_ROM
  404.  
  405.     jz      int_common3         ;no segment checks to be made
  406.     mov     ax,2[bp]        ;get caller's IP
  407.     shr     ax,1            ;prepare to normalize segment #
  408.     shr     ax,1
  409.     shr     ax,1
  410.     shr     ax,1
  411.     add     ax,4[bp]        ;add in segment
  412.  
  413. ;
  414. ; ------ AX now equals normalized segment #
  415. ;
  416.  
  417.     test    cs:[bx].ICT_flags,F_BELOW
  418.  
  419.     jz      int_common2         ;don't check for invoker below us
  420.     cmp     ax,cs:test_cs        ;is caller below us?
  421.     jb      no_trace        ;yes, don't trace
  422.  
  423. int_common2:
  424.  
  425.     test    cs:[bx].ICT_flags,F_ROM
  426.  
  427.     jz      int_common3         ;don't check for invoker in ROM
  428.     cmp     ax,0c000h           ;is caller in ROM?
  429.     jae     no_trace        ;yes, don't trace
  430.  
  431. int_common3:
  432.  
  433. ;
  434. ; See if we have room for this trace
  435. ;
  436.  
  437.     mov     ax,cs:next_byte     ;get address of next entry
  438.     push    ax
  439.     add    ax,size BEFORE        ;add size of this record
  440.     cmp     ax,offset cs:last_byte  ;would record fit?
  441.     pop    ax
  442.     jb      yes_trace           ;yes, there's room
  443.  
  444. no_trace:
  445.  
  446. ;
  447. ; We are not to trace this INT, for whatever reason.
  448. ; Just go to original handler, and return to caller (not to us).
  449. ;
  450.  
  451.     mov     ax,word ptr cs:[bx].ICT_orig_hndlr
  452.     mov     word ptr cs:long_addr,ax
  453.     mov     ax,word ptr cs:[bx].ICT_orig_hndlr+2
  454.     mov     word ptr cs:long_addr+2,ax
  455.     pop     ax
  456.     pop     bx
  457.     pop     bp
  458.     jmp     cs:long_addr    ;let original handler return to caller
  459.  
  460.  
  461. yes_trace:
  462.  
  463. ;
  464. ; We are to proceed with trace of this INT. Make trace entry.
  465. ;
  466.  
  467.     push    es
  468.     push    di
  469.  
  470. ;
  471. ; At this point:
  472. ;
  473. ;   AX holds offset to next trace entry.
  474. ;   BX holds ICT address.
  475. ;   BP points to stack as follows:
  476. ;
  477. ;                   DI
  478. ;                   ES
  479. ;                   AX
  480. ;                   BX
  481. ;      (BP) ---->   BP
  482. ;               +2  IP    of caller
  483. ;               +4  CS    of caller
  484. ;               +6  FLAGS of caller
  485. ;
  486.  
  487.     mov     di,ax           ;set ES:DI to next trace entry
  488.     mov     ax,cs
  489.     mov     es,ax
  490.     cld                     ;forward!!!
  491.     mov     ah,cs:[bx].ICT_intnum   ;get interrupt # being traced
  492.     mov     al,cs:[bx].ICT_num    ;get ICT #, make BEFORE record type
  493.     stosw
  494.     mov     ax,-4[bp]           ;original AX
  495.     stosw
  496.     mov     ax,-2[bp]           ;original BX
  497.     stosw
  498.     mov     ax,cx
  499.     stosw
  500.     mov     ax,dx
  501.     stosw
  502.     mov     ax,-6[bp]           ;original ES
  503.     stosw
  504.     mov     ax,ds
  505.     stosw
  506.     mov     ax,ss
  507.     stosw
  508.     mov     ax,bp           ;original SP
  509.     add     ax,2
  510.     stosw
  511.     mov     ax,si
  512.     stosw
  513.     mov     ax,-8[bp]           ;original DI
  514.     stosw
  515.     mov     ax,[bp]         ;original BP
  516.     stosw
  517.     mov     ax,4[bp]        ;caller's CS
  518.     stosw
  519.     mov     ax,2[bp]        ;caller's IP
  520.     stosw
  521.  
  522.     mov     cs:next_byte,di     ;save spot for next trace entry
  523.     inc    cs:[bx].ICT_hits    ;bump number of traces made for this ICT
  524.  
  525. ;
  526. ; We're done with the BEFORE trace. See if we are to do an FCB or ASCIIZ
  527. ; trace record.
  528. ;
  529.  
  530.     test    cs:[bx].ICT_flags,F_FCB
  531.     jz    no_FCB            ;no, we are definitely not supposed to
  532.     cmp    cs:[BX].ICT_intnum,021h    ;is this an INT 21h?
  533.     jnz    no_FCB            ;no, can't trace it then
  534.  
  535. ;
  536. ; Search through ASCIIZ function table, to see if function that was called
  537. ; is one that contains an ASCIIZ pointer in DS:DX
  538. ;
  539.  
  540.     mov    ax,-4[bp]        ;get AX at time of call
  541.     push    cx
  542.     mov    di,offset cs:ASCIIZ_table
  543.     mov    cx,offset cs:ASCIIZ_end
  544.     sub    cx,di            ;CX now has size of table
  545.     mov    al,ah            ;get function to AL
  546.     repnz    scasb            ;see if it's in table
  547.     pop    cx
  548.     jz    trace_ASCIIZ        ;it's there, so do ASCIIZ trace
  549.  
  550. ;
  551. ; Search through FCB function table, to see if function that was called
  552. ; is one that contains an FCB pointer in DS:DX
  553. ;
  554.  
  555.     push    cx
  556.     mov    di,offset cs:FCB_table
  557.     mov    cx,offset cs:FCB_end
  558.     sub    cx,di            ;CX now has size of table
  559.     repnz    scasb            ;see if it's in table
  560.     pop    cx
  561.     jnz    no_FCB            ;no FCB or ASCIIZ trace called for
  562.  
  563. ;
  564. ; We are to do trace of FCB pointed to by DS:DX
  565. ;
  566.  
  567.     mov    al,00100000b        ;trace record number for FCB trace
  568.     mov    ah,size FCB        ;size of record
  569.     jmp    short trace_common    ;rest is common code
  570.  
  571. trace_ASCIIZ:
  572.  
  573. ;
  574. ; We are to do trace of ASCIIZ string pointed to by DS:DX
  575. ;
  576.  
  577.     mov    al,00110000b        ;trace record number for ASCIIZ trace
  578.     mov    ah,size ASCIIZ        ;size of record
  579.  
  580. trace_common:
  581.  
  582. ;
  583. ; Copy bytes from DS:DX to new ASCIIZ or FCB trace record.
  584. ;
  585. ; At this point:
  586. ;
  587. ;   AL holds trace record type, properly positioned in bits 7-4
  588. ;   AH holds size of record that we're doing (the full record)
  589. ;
  590.  
  591.     sub    ah,2            ;minus two bytes for record header
  592.     mov    di,cs:next_byte        ;see if there's room...
  593.     push    di
  594.     push    ax
  595.     mov    al,ah            ;get record size to AX
  596.     xor    ah,ah
  597.     add    di,ax
  598.     cmp    di,offset cs:last_byte
  599.     pop    ax
  600.     pop    di
  601.     jae    no_FCB            ;no room
  602.     push    ax            ;save AX over this
  603.     mov    ah,cs:[bx].ICT_intnum    ;start header with interrupt #
  604.     or    al,cs:[bx].ICT_num    ;add ICT number to trace type
  605.     stosw                ;start new record with it
  606.     pop    ax            ;restore AX
  607.     push    cx
  608.     push    si
  609.     mov    si,dx            ;access DS:DX as DS:SI
  610.     mov    cl,ah            ;record size to CX
  611.     xor    ch,ch
  612.     rep    movsb            ;that's how many to copy
  613.     pop    si
  614.     pop    cx
  615.     mov    cs:next_byte,di        ;save offset to next record
  616.  
  617. no_FCB:                    ;end of FCB/ASCIIZ tracing
  618.  
  619.  
  620. ;
  621. ; Having traced all of those, now invoke original interrupt handler. Have
  622. ; it return to us, not the original caller of the interrupt.
  623. ;
  624.  
  625.     mov     cs:our_ICT,bx       ;save ICT pointer for a nanosecond
  626.     mov    al,cs:[bx].ICT_flags    ;save copy of flags that we can get to
  627.     mov    cs:our_flags,al
  628.  
  629.     mov     ax,word ptr cs:[bx].ICT_orig_hndlr
  630.     mov     word ptr cs:long_addr,ax
  631.     mov     ax,word ptr cs:[bx].ICT_orig_hndlr+2
  632.     mov     word ptr cs:long_addr+2,ax
  633.  
  634.     pop     di
  635.     pop     es
  636.     pop     ax
  637.     pop     bx
  638.     pop     bp
  639.     push    cs:our_ICT          ;save ICT pointer on stack
  640.     test    cs:our_flags,F_RET    ;should we push flags?
  641.     jnz    no_flags        ;no, cause they'd be left on stack
  642.     pushf                   ;yes, give handler some flags to drop
  643.  
  644. no_flags:
  645.     call    cs:long_addr        ;invoke original handler
  646.  
  647.  
  648. ;
  649. ; We're back from the real interrupt handler, and can make the "after" trace.
  650. ; Our ICT address is on stack.
  651. ;
  652.  
  653.     sti                ;give world a crack at interrupts
  654.     nop
  655.     nop
  656.     cli                ;*** NO INTERRUPTS!!! ***
  657.     push    bp              ;establish stack reference
  658.     mov     bp,sp
  659.     pushf                   ;save resultant flags
  660.     push    es
  661.     push    di
  662.     push    ax
  663.     push    bx
  664.  
  665. ;
  666. ; At this point:
  667. ;
  668. ;                     BX
  669. ;                     AX
  670. ;                     DI
  671. ;                     ES
  672. ;                     FLAGS (as returned by real interrupt)
  673. ;     (BP) -------->  BP
  674. ;                     ICT address
  675. ;                     IP of caller
  676. ;                     CS of caller
  677. ;                     FLAGS of original caller
  678. ;
  679.  
  680.     mov     bx,2[bp]        ;recover ICT address
  681.     mov     di,cs:next_byte     ;room for "after" trace entry?
  682.     push    di
  683.     add    di,size AFTER
  684.     cmp     di,offset cs:last_byte
  685.     pop    di
  686.     jae     no_after        ;no, skip it
  687.     mov     ax,cs           ;make ES:DI point to next entry
  688.     mov     es,ax
  689.     cld                     ;forward!!!
  690.     mov     ah,cs:[bx].ICT_intnum   ;get interrupt #
  691.     mov     al,cs:[bx].ICT_num    ;get ICT #, make AFTER record type
  692.     or    al,00010000b
  693.     stosw
  694.     mov     ax,-8[bp]           ;AX at int's return
  695.     stosw
  696.     mov     ax,-10[bp]          ;BX at int's return
  697.     stosw
  698.     mov     ax,cx
  699.     stosw
  700.     mov     ax,dx
  701.     stosw
  702.     mov     ax,-4[bp]           ;ES at int's return
  703.     stosw
  704.     mov     ax,ds
  705.     stosw
  706.     mov     ax,si
  707.     stosw
  708.     mov     ax,-6[bp]           ;DI at int's return
  709.     stosw
  710.     mov     ax,[bp]         ;BP at int's return
  711.     stosw
  712.     mov     ax,-2[bp]           ;FLAGS at int's return
  713.     stosw
  714.  
  715.     mov     cs:next_byte,di     ;save offset to next entry
  716.  
  717. no_after:
  718.  
  719. ;
  720. ; All done making "after" trace, or we've skipped it cause there was
  721. ; no room for it.
  722. ;
  723. ; Now just exit back to the original caller.
  724. ;
  725.  
  726.     mov    al,cs:[bx].ICT_flags    ;save flags where we can get to them
  727.     mov    cs:our_flags,al
  728.     pop     bx
  729.     pop     ax
  730.     pop     di
  731.     pop     es
  732.     popf
  733.     pop     bp
  734.     pop     cs:our_ICT      ;drop ICT address without affecting flags
  735.  
  736. ;
  737. ; HOW we exit is extremely important. We must exit the same way that the
  738. ; real interrupt does.
  739. ;
  740.  
  741.     pushf                ;save current flags in case we return them
  742.     test    cs:our_flags,F_RET
  743.     jnz    exit_ret
  744.     test    cs:our_flags,F_RET2
  745.     jnz    exit_ret2
  746.  
  747. ;
  748. ; Assume IRET.
  749. ;
  750.  
  751. exit_iret:
  752.     popf            ;exit via IRET, reloading original flags
  753.     STI            ;Allow interrupts now
  754.     iret
  755.  
  756. exit_ret2:
  757.     popf            ;exit via RET 2, discarding original flags
  758.     STI            ;Allow interrupts now
  759.     ret    2
  760.  
  761. exit_ret:
  762.     popf            ;exit via far RET, leaving original flags
  763.     STI            ;Allow interrupts now
  764.     ret
  765.  
  766. interrupt endp
  767.  
  768.     subttl    Support routines - Printer & Screen I/O
  769.     page
  770. ;*****************************************
  771. ;
  772. ; Select video for subsequent output
  773. ;
  774. ;*****************************************
  775.  
  776. selvideo proc    near
  777.     mov    prt_flag,0
  778.     ret
  779. selvideo endp
  780.  
  781.  
  782. ;*****************************************
  783. ;
  784. ; Select printer for subsequent output
  785. ;
  786. ;*****************************************
  787.  
  788. selprint proc    near
  789.     push    ax
  790.     mov    ax,prt_base    ;do we have a printer?
  791.     or    al,ah
  792.     mov    prt_flag,al    ;al is non-zero if we do
  793.     pop    ax
  794.     ret
  795. selprint endp
  796.  
  797. ;********************************************************
  798. ;
  799. ; Output AL to printer or screen, depending on prt_flag.
  800. ;
  801. ;********************************************************
  802.  
  803. print    proc    near
  804.     push    dx
  805.     push    cx
  806.     push    bx
  807.     push    ax
  808.  
  809. ; ----- See if it should go to printer
  810.  
  811.     test    prt_flag,0ffh        ;send it to printer?
  812.     jnz    print1            ;yes
  813.  
  814. print0:
  815.  
  816. ;
  817. ; Send char to video via INT 010H
  818. ;
  819.  
  820.     mov    bl,1
  821.     mov    ah,14            ;"Write TTY" func
  822.     int    010h
  823.     clc                ;show no I/O error
  824.     jmp    short print9
  825.  
  826. print1:
  827.  
  828. ;----- Send it to printer
  829.  
  830.     mov    dx,prt_base        ;get printer base I/O address
  831.     inc    dx            ;up to status port
  832.     mov    ah,al            ;save char in ah
  833.     xor    cx,cx            ;init timeout ticker
  834.  
  835. print2:
  836.     in    al,dx            ;get status
  837.     test    al,080h            ;is printer busy?
  838.     jnz    print5            ;no, proceed to send char
  839.  
  840. ;
  841. ; We're not immediately ready. Some printers require more of a wait than
  842. ; the simple 64K loop found in CX. So here's a time waster that you may
  843. ; want to tailor to your printer.
  844. ;
  845.  
  846.     mov    al,8            ;greatly extend timeout value
  847.  
  848. print3:
  849.     dec    al
  850.     jnz    print3
  851.  
  852.     loop    print2            ;wait for whole timeout
  853.     stc                ;set carry for timeout
  854.     jmp    short print9        ;and exit
  855.  
  856. print5:
  857.     dec    dx            ;down to data reg
  858.     mov    al,ah            ;recover char to be sent
  859.     out    dx,al            ;put it on data lines
  860.     inc    dx            ;up to control port
  861.     inc    dx
  862.     mov    al,0dh            ;set strobe low
  863.     out    dx,al
  864.     mov    al,0ch            ;set strobe high again
  865.     out    dx,al
  866.     clc                ;show no error
  867.  
  868. print9:
  869.  
  870. ;
  871. ; At this point, CARRY is SET if we were going to the printer and had an
  872. ; I/O error.
  873. ;
  874.  
  875.     jnc    print10            ;no error
  876.     call    selvideo        ;error, so switch to video
  877.     pop    ax            ;recover AL
  878.     push    ax
  879.     jmp    print0            ;go send it to video
  880.  
  881. print10:
  882.     pop    ax
  883.     pop    bx
  884.     pop    cx
  885.     pop    dx
  886.     ret
  887. print    endp
  888.  
  889. ;********************************************************
  890. ;
  891. ; Output binary AL as 2 hex digits
  892. ;
  893. ;********************************************************
  894.  
  895. print_hex proc    near
  896.     push    bx
  897.     push    ax
  898.     mov    bl,al            ;isolate HO nibble
  899.     shr    bl,1
  900.     shr    bl,1
  901.     shr    bl,1
  902.     shr    bl,1
  903.     and    bx,0fh
  904.     mov    al,hextab[bx]        ;xlit to hex char
  905.     call    print            ;print 1st char
  906.     pop    ax
  907.     push    ax
  908.     mov    bl,al            ;isolate LO nibble
  909.     and    bx,0fh
  910.     mov    al,hextab[bx]        ;xlit to hex char
  911.     call    print            ;print 2nd char
  912.     pop    ax
  913.     pop    bx
  914.     ret
  915. print_hex endp
  916.  
  917. hextab    db    '0123456789ABCDEF'
  918.  
  919. ;********************************************************
  920. ;
  921. ; Output binary word AX as 4 hex digits
  922. ;
  923. ;********************************************************
  924.  
  925. print_word proc    near
  926.     xchg    ah,al            ;get HO half to AL
  927.     call    print_hex        ;print 1st 2 chars
  928.     xchg    ah,al            ;get LO half back to AL
  929.     call    print_hex        ;print 2nd 2 chars
  930.     ret
  931. print_word endp
  932.  
  933. ;********************************************************
  934. ;
  935. ; Output binary word AX as 4 hex digits, plus a blank
  936. ;
  937. ;********************************************************
  938.  
  939. print_wordb proc near
  940.     push    ax
  941.     call    print_word
  942.     mov    al,' '
  943.     call    print
  944.     pop    ax
  945.     ret
  946. print_wordb endp
  947.  
  948. ;*****************************************
  949. ;
  950. ; Print CRLF.
  951. ;
  952. ;*****************************************
  953.  
  954. crlf    proc    near
  955.     push    ax
  956.     mov    al,0dh
  957.     call    print
  958.     mov    al,0ah
  959.     call    print
  960.     pop    ax
  961.     ret
  962. crlf    endp
  963.  
  964. ;*****************************************
  965. ;
  966. ; Print string at DS:DX, up to "$" character.
  967. ;
  968. ;*****************************************
  969.  
  970. print_line proc    near
  971.     push    si
  972.     push    ax
  973.     cld            ;forward!
  974.     mov    si,dx        ;DS:SI = string
  975.  
  976. print_line2:
  977.     lodsb            ;get next byte to print
  978.     cmp    al,'$'        ;terminating char?
  979.     jz    print_line9    ;yes, exit
  980.     call    print        ;print this char
  981.     jmp    print_line2    ;continue till "$"
  982.  
  983. print_line9:
  984.     pop    ax
  985.     pop    si
  986.     ret
  987. print_line endp
  988.  
  989. ;*****************************************
  990. ;
  991. ; Print DX (HO), AX (LO) as xxxx:xxxx.
  992. ;
  993. ;*****************************************
  994.  
  995. print_seg proc    near
  996.     push    ax
  997.     mov    ax,dx        ;get HO word first
  998.     call    print_word
  999.     mov    al,':'        ;show seperator too
  1000.     call    print
  1001.     pop    ax        ;recover LO word
  1002.     call    print_word
  1003.     ret
  1004. print_seg endp
  1005.  
  1006. ;********************************************************************
  1007. ;
  1008. ; Print a line at [DX], edited.
  1009. ;
  1010. ; Line may contain Edit_xxxx escape characters, as defined above.
  1011. ;
  1012. ;********************************************************************
  1013.  
  1014. print_edit proc    near
  1015.     push    si
  1016.     push    dx
  1017.     push    cx
  1018.     push    bx
  1019.     push    ax
  1020.         mov    si,dx            ;use DS:SI to read line
  1021.         cld                ;forward!!!
  1022.  
  1023. print_edit2:
  1024.         lodsb                ;get next byte of line
  1025.         cmp    al,Edit_Byte        ;binary byte to expand?
  1026.         jnz    print_edit3        ;no
  1027.         lodsb                ;yes, get 8-bit value
  1028.         call    print_hex        ;print it as hex
  1029.  
  1030. print_edit2b:
  1031.         mov    al,'H'            ;tack "H" for HEX after it
  1032.  
  1033. print_edit2c:
  1034.         call    print
  1035.         jmp    print_edit2        ;go get next char
  1036.  
  1037. print_edit3:
  1038.         cmp    al,Edit_Word        ;16-bit binary to expand?
  1039.         jnz    print_edit4        ;no
  1040.         lodsw                ;yes, get 16-bit word
  1041.         call    print_word        ;display as hex
  1042.         jmp    print_edit2b        ;follow with 'H' and continue
  1043.  
  1044. print_edit4:
  1045.         cmp    al,Edit_Call        ;call another routine?
  1046.         jnz    print_edit5        ;no
  1047.         lodsb                ;yes, get AH argument
  1048.         mov    bh,al            ;save for a nano...
  1049.         lodsw                ;get DX argument
  1050.         mov    dx,ax
  1051.         lodsw                ;get address to call
  1052.         mov    cx,ax
  1053.         mov    ah,bh            ;recover AH argument to use
  1054.         push    si            ;save our precious SI
  1055.         call    cx            ;call the routine
  1056.         pop    si
  1057.         jmp    print_edit2        ;go get next char
  1058.  
  1059. print_edit5:
  1060.     cmp    al,Edit_Dec8        ;8-bit decimal value?
  1061.     jnz    print_edit6        ;no
  1062.     lodsb                ;yes, get 8-bit byte
  1063.     xor    ah,ah            ;clear HO byte
  1064.  
  1065. print_edit5b:
  1066.     call    print_dec        ;print AX as decimal
  1067.     jmp    print_edit2        ;go get next input char
  1068.  
  1069. print_edit6:
  1070.     cmp    al,Edit_Dec16        ;16-bit decimal value?
  1071.     jnz    print_edit7        ;no
  1072.     lodsw                ;yes, get 16-bit byte
  1073.     jmp    print_edit5b        ;print it and go get next char
  1074.  
  1075. print_edit7:
  1076.     cmp    al,Edit_End        ;end of input string?
  1077.     jnz    print_edit2c        ;no, assume ASCII char and print it
  1078.  
  1079.     pop    ax
  1080.     pop    bx
  1081.     pop    cx
  1082.     pop    dx
  1083.     pop    si
  1084.         ret
  1085. print_edit endp
  1086.  
  1087.  
  1088. ;**************************************************
  1089. ;
  1090. ; Print AX in decimal, suppressing leading zeroes
  1091. ;
  1092. ;**************************************************
  1093.  
  1094. print_dec proc    near
  1095.     push    dx
  1096.     push    cx
  1097.     push    bx
  1098.     push    ax
  1099.     mov    cx,10            ;divisor
  1100.     xor    dx,dx
  1101.     div    cx            ;DL=units, AX = answer
  1102.     mov    bh,dl            ;save units
  1103.     xor    dx,dx
  1104.     div    cx            ;DL=tens, AX = answer
  1105.     mov    bl,dl            ;get tens
  1106.     or    bx,03030h        ;make into 2 ASCII digits
  1107.     mov    word ptr dec_buf+3,bx
  1108.     div    cl            ;AH=hunds, AL = answer
  1109.     mov    bh,ah            ;save hundreds
  1110.     xor    ah,ah
  1111.     div    cl            ;AH=thous, AL = ten_thousands
  1112.     mov    bl,ah            ;get thous
  1113.     or    bx,03030h        ;make into 2 ASCII digits
  1114.     mov    word ptr dec_buf+1,bx
  1115.     or    al,030h            ;make ten-thousands into ASCII digit
  1116.     mov    byte ptr dec_buf,al
  1117.  
  1118. ;
  1119. ; Now edit out leading zeroes by advancing BX to 1st non-zero
  1120. ;
  1121.  
  1122.     mov    bx,offset dec_buf
  1123.     mov    cx,4            ;max # to suppress
  1124.  
  1125. print_dec2:
  1126.     cmp    byte ptr [bx],'0'
  1127.     jnz    print_dec5        ;found non-zero, so exit
  1128.     inc    bx            ;up to next digit
  1129.     loop    print_dec2
  1130.  
  1131. print_dec5:
  1132.  
  1133. ;
  1134. ; All set. Print from [BX] on...
  1135. ;
  1136.  
  1137.     mov    dx,bx
  1138.     call    print_line
  1139.     pop    ax
  1140.     pop    bx
  1141.     pop    cx
  1142.     pop    dx
  1143.     ret
  1144. print_dec endp
  1145.  
  1146. dec_buf    db    "99999$"
  1147.  
  1148.  
  1149. ;********************************************************************
  1150. ;
  1151. ; Print one string from a table of possible strings.
  1152. ;
  1153. ; On entry: AH holds selector
  1154. ;           DX holds table address
  1155. ;
  1156. ; Each table entry is as follows:
  1157. ;
  1158. ;    db    <selector>,"string",<term>
  1159. ;
  1160. ; where:
  1161. ;       <selector> is 8-bit byte that is compared with AH. If it
  1162. ;                   matches, then this string is printed.
  1163. ;
  1164. ;       "string" is the string to be printed
  1165. ;
  1166. ;       <term> is the terminating character, as follows:
  1167. ;
  1168. ;               00H : end of this string
  1169. ;               80H : end of this string, and end of table too
  1170. ;
  1171. ; If no <selector> matches AH, then "????" is printed.
  1172. ;
  1173. ;********************************************************************
  1174.  
  1175. table_print proc near
  1176.     push    si
  1177.     push    dx
  1178.     push    cx
  1179.     push    bx
  1180.     push    ax
  1181.         mov    si,dx            ;use DS:SI to read table
  1182.         cld                ;forward!!!
  1183.  
  1184. table_print2:
  1185.         lodsb                ;get next selector
  1186.         cmp    al,ah            ;does it match AH?
  1187.         jnz    table_print5        ;no, skip to next one
  1188.  
  1189. table_print3:
  1190.  
  1191. ;
  1192. ; We have found string to print. Output it until a terminator is found.
  1193. ;
  1194.  
  1195.         lodsb                ;get byte of string
  1196.         test    al,07fh            ;terminator?
  1197.         jz    table_print9        ;yes, exit
  1198.         call    print            ;no, print this char
  1199.         jmp    table_print3
  1200.  
  1201. table_print5:
  1202.  
  1203. ;
  1204. ; Not this selector. Skip over string till terminator, then go peek
  1205. ; at next selector.
  1206. ;
  1207.  
  1208.         lodsb                ;get byte of string
  1209.         test    al,07fh            ;terminator?
  1210.         jnz    table_print5        ;no, keep skipping
  1211.  
  1212. ;
  1213. ; We have terminator at end of skipped string. It may be end of whole table...
  1214. ;
  1215.  
  1216.         cmp    al,080h            ;end of table?
  1217.         jnz    table_print2        ;no, go check next selector
  1218.         mov    dx,offset huh        ;yes, print "????" message cause match not found
  1219.         call    print_line
  1220.  
  1221. table_print9:
  1222.     pop    ax
  1223.     pop    bx
  1224.     pop    cx
  1225.     pop    dx
  1226.     pop    si
  1227.         ret
  1228. table_print endp
  1229.  
  1230. huh    db    "????$"
  1231.  
  1232. ;*********************************************
  1233. ;
  1234. ; Issue extra linefeeds if we're going to the printer. This
  1235. ; moves the paper up enough to be read.
  1236. ;
  1237. ; This should be called before any input, and whenever output is
  1238. ; generally finished.
  1239. ;
  1240. ;*********************************************
  1241.  
  1242. feed    proc    near
  1243.     push    ax
  1244.     push    cx
  1245.     test    prt_flag,0ffh    ;are we going to the printer?
  1246.     jz    feed9        ;no, just exit
  1247.     mov    cx,num_feeds    ;# linefeeds to do
  1248.     jcxz    feed9        ;none, so exit
  1249.  
  1250. feed2:
  1251.     call    crlf
  1252.     loop    feed2
  1253.  
  1254. feed9:
  1255.     pop    cx
  1256.     pop    ax
  1257.     ret
  1258. feed    endp
  1259.  
  1260.     subttl    Menu Handling
  1261.     page
  1262. ;*********************************************
  1263. ;
  1264. ; Get uppercase keyboard char to AL. AH is clobbered.
  1265. ;
  1266. ;*********************************************
  1267.  
  1268. key    proc    near
  1269.     mov    ah,0        ;use ROM BIOS to read keyboard
  1270.     int    016h
  1271.     cmp    al,'a'        ;lowercase char?
  1272.     jb    key9        ;no
  1273.     cmp    al,'z'
  1274.     ja    key9        ;likewise no
  1275.     and    al,0dfh        ;yes, convert to uppercase
  1276. key9:
  1277.     ret
  1278. key    endp
  1279.  
  1280.  
  1281. ;*********************************************
  1282. ;
  1283. ; Reset all ICT hits to zero, and restart trace buffer
  1284. ;
  1285. ;*********************************************
  1286.  
  1287. zap_hits proc    near
  1288.     push    si
  1289.     push    ax
  1290.     push    bx
  1291.     push    cx
  1292.     mov    cx,8            ;Number of ICT's
  1293.     xor    si,si            ;start with # 0
  1294.     cli                ;no interrupts!
  1295.  
  1296. zap_hits2:
  1297.     mov    bx,ict_index[si]    ;[BX] --> ICT
  1298.     mov    [bx].ICT_hits,0
  1299.     add    si,2            ;up to next ICT
  1300.     loop    zap_hits2        ;till we've done all of them
  1301.  
  1302.     mov    next_byte,offset trace_table
  1303.     sti                ;interrupts OK now
  1304.     pop    cx
  1305.     pop    bx
  1306.     pop    ax
  1307.     pop    si
  1308.     ret
  1309. zap_hits endp
  1310.     page
  1311. ;*********************************************
  1312. ;
  1313. ; Handle main menu selection whose ASCII keypress is in AL.
  1314. ;
  1315. ; Returns: CARRY SET if we should loop back to main menu.
  1316. ;          CARRY CLEAR to exit.
  1317. ;
  1318. ;*********************************************
  1319.  
  1320. do_main proc    near
  1321.     push    ax
  1322.     cmp    al,'P'        ;select printer?
  1323.     jnz    do_main1    ;no
  1324.     call    selprint    ;yes, do it
  1325.     stc            ;"Loop back to main menu" flag
  1326.     jmp    short do_main9
  1327.  
  1328. do_main1:
  1329.     cmp    al,'S'        ;select screen?
  1330.     jnz    do_main2    ;no
  1331.     call    selvideo    ;yes, do it
  1332.     stc            ;"Loop back to main menu" flag
  1333.     jmp    short do_main9
  1334.  
  1335. do_main2:
  1336.     cmp    al,'T'        ;Dump Traces?
  1337.     jnz    do_main3    ;no
  1338.     call    do_traces    ;yes, do it
  1339.     stc            ;"Loop back to main menu" flag
  1340.     jmp    short do_main9
  1341.  
  1342. do_main3:
  1343.     cmp    al,'E'        ;Enable ICT?
  1344.     jnz    do_main4    ;no
  1345.     mov    al,F_ENABLE    ;yes, get bit value to set/clear
  1346.  
  1347. do_main3b:
  1348.     call    do_enable    ;enable/disable F_ENABLE per AL
  1349.     stc            ;"Loop back to main menu" flag
  1350.     jmp    short do_main9
  1351.  
  1352. do_main4:
  1353.     cmp    al,'D'        ;Disable ICT?
  1354.     jnz    do_main5    ;no
  1355.     mov    al,0        ;yes, get bit value to set/clear
  1356.     jmp    do_main3b
  1357.  
  1358. do_main5:
  1359.     cmp    al,'L'        ;List ICT's?
  1360.     jnz    do_main6    ;no
  1361.     call    disp_active    ;yes, do it
  1362.     stc            ;"Loop back to main menu" flag
  1363.     jmp    short do_main9
  1364.  
  1365. do_main6:
  1366.     cmp    al,'C'        ;Clear trace table?
  1367.     jnz    do_main7    ;no
  1368.     call    zap_hits    ;yes, do it
  1369.     stc            ;"Loop back to main menu" flag
  1370.     jmp    short do_main9
  1371.  
  1372. do_main7:
  1373.     cmp    al,'Q'        ;Quit?
  1374.     jnz    do_main8    ;no
  1375.     clc            ;"Exit" flag
  1376.     jmp    short do_main9
  1377.  
  1378. do_main8:
  1379.     cmp    al,'F'        ;F_FCB toggle?
  1380.     jnz    do_main8B    ;no
  1381.     call    do_fcb        ;yes, toggle something
  1382.     stc            ;"Loop back to main menu" flag
  1383.     jmp    short do_main9
  1384.  
  1385. do_main8b:
  1386.  
  1387. ; ------ Unknown selection
  1388.  
  1389.     stc            ;"Loop back to main menu" flag
  1390.  
  1391. do_main9:
  1392.     pop    ax
  1393.     ret
  1394. do_main    endp
  1395.  
  1396.  
  1397. ;**********************************************
  1398. ;
  1399. ; Pick ICT's with which to do something.
  1400. ;
  1401. ; This is called to select ICT for various operations.
  1402. ;
  1403. ; On entry, DX holds address of question (no CRLF's) to be asked.
  1404. ;
  1405. ; Returns: CARRY SET if user selected ABORT to cancel the caller's operation
  1406. ;
  1407. ;          CARRY CLEAR if AL has been set to 8-bit pattern, with each
  1408. ;          bit from 0 to 7 representing an ICT (0-7) that was selected.
  1409. ;
  1410. ;**********************************************
  1411.  
  1412. pick_ict proc    near
  1413.     push    bx
  1414.     push    cx
  1415.     push    dx
  1416.     mov    byte ptr pick_map,0    ;init to nobody selected
  1417.  
  1418. pick_ict1:
  1419.  
  1420. ;
  1421. ; Put up our selection menu
  1422. ;
  1423.  
  1424.     call    crlf
  1425.     pop    dx            ;display caller's question
  1426.     push    dx
  1427.     call    print_line
  1428.     mov    dx,offset pick_menu    ;put up our menu
  1429.     call    print_line
  1430.  
  1431. ;
  1432. ; Fill in choices already made, as if he had typed them
  1433. ;
  1434.  
  1435.     mov    cx,8            ;# ICT's
  1436.     mov    ah,byte ptr pick_map    ;AH has bitmap
  1437.     mov    al,'0'            ;AL holds ASCII '0' - '7'
  1438.  
  1439. pick_ict1b:
  1440.     test    ah,1            ;Is this ICT selected?
  1441.     jz    pick_ict1c        ;no
  1442.     call    print            ;yes, show corresponding ASCII char
  1443.  
  1444. pick_ict1c:
  1445.     inc    al            ;Bump ASCII char
  1446.     shr    ah,1            ;get next bit to test
  1447.     loop    pick_ict1b        ;till done all 8
  1448.     call    feed            ;eject paper on printer
  1449.  
  1450. pick_ict2:
  1451.  
  1452. ;
  1453. ; Get and handle next keypress
  1454. ;
  1455.  
  1456.     call    key
  1457.     cmp    al,'0'            ;ICT number?
  1458.     jb    pick_ict3        ;no
  1459.     cmp    al,'7'
  1460.     ja    pick_ict3        ;no
  1461.     call    print            ;yes, echo it
  1462.  
  1463. ;
  1464. ; Convert this ASCII char to bitmap bit, and add to our map
  1465. ;
  1466.  
  1467.     call    bin_to_bit        ;comes back in AL
  1468.     or    byte ptr pick_map,al    ;add this new bit into pattern
  1469.     jmp    pick_ict2        ;go get next keypress
  1470.  
  1471. pick_ict3:
  1472.     cmp    al,'L'            ;List ICT's?
  1473.     jnz    pick_ict4        ;no
  1474.     call    disp_active        ;yes, show all active ICT's
  1475.     jmp    pick_ict1        ;give our menu again
  1476.  
  1477. pick_ict4:
  1478.     cmp    al,'R'            ;Restart?
  1479.     jnz    pick_ict5        ;no
  1480.     mov    byte ptr pick_map,0    ;yes, clear map
  1481.     jmp    pick_ict1        ;give new menu
  1482.  
  1483. pick_ict5:
  1484.     cmp    al,'G'            ;Go with choices?
  1485.     jnz    pick_ict6        ;no
  1486.  
  1487. pick_ict5b:
  1488.     mov    al,byte ptr pick_map    ;yes, get choices as bitmap
  1489.     clc                ;tell caller to use it
  1490.     jmp    short pick_ict9        ;exit
  1491.  
  1492. pick_ict6:
  1493.     cmp    al,0dh            ;Carriage Return?
  1494.     jz    pick_ict5b        ;yes, same as "Go"
  1495.     cmp    al,'A'            ;Abort operation?
  1496.     jnz    pick_ict7        ;no
  1497.  
  1498. pick_ict6b:
  1499.     stc                ;tell caller to abort
  1500.     jmp    short pick_ict9        ;exit
  1501.  
  1502. pick_ict7:
  1503.     cmp    al,1bh            ;ESCAPE?
  1504.     jz    pick_ict6b        ;yes, same as "Abort"
  1505.  
  1506. ; ------ Unknown choice
  1507.  
  1508.     jmp    pick_ict2        ;go get next keypress
  1509.  
  1510. pick_ict9:
  1511.     pop    dx
  1512.     pop    cx
  1513.     pop    bx
  1514.     ret
  1515. pick_ict endp
  1516.  
  1517. pick_menu    db    0dh,0ah
  1518.         db    "0-7 picks ICT   (L)ist ICT's  (A)bort  (R)estart  (G)o with choices"
  1519.         db    0dh,0ah,":$"
  1520.  
  1521. pick_map    db    0    ;bitmap of selected ICT's
  1522.  
  1523.  
  1524. ;*********************************************
  1525. ;
  1526. ; Handle "Traces" main menu option
  1527. ;
  1528. ;*********************************************
  1529.  
  1530. do_traces proc    near
  1531.     push    ax
  1532.     push    dx
  1533.     mov    dx,offset trace_menu    ;put up our menu
  1534.     call    print_line
  1535.     call    feed            ;extra CRLF's for printer
  1536.     call    key            ;get his selection
  1537.     cmp    al,'A'            ;dump All?
  1538.     jnz    do_traces2        ;no
  1539.     mov    al,0ffh            ;yes, get bitmap for all ICT's
  1540.     jmp    short do_traces7    ;dump 'em
  1541.  
  1542. do_traces2:
  1543.     cmp    al,'S'            ;Selected ICT's?
  1544.     jnz    do_traces9        ;no, so exit
  1545.     mov    dx,offset trace_prompt    ;point to question to be used
  1546.     call    pick_ict        ;get ICT's as bitmap in AL
  1547.     jc    do_traces9        ;user wants to forget about it
  1548.  
  1549. do_traces7:
  1550.  
  1551. ;
  1552. ; Do dump, with AL holding bitmap of ICT's that are to be included
  1553. ;
  1554.  
  1555.     call    dump_buf        ;with AL already set
  1556.  
  1557. do_traces9:
  1558.     pop    dx
  1559.     pop    ax
  1560.     ret
  1561. do_traces endp
  1562.  
  1563. trace_menu    db    0dh,0ah
  1564.         db    "Display (A)ll or (S)elected ICTs' traces:$"
  1565. trace_prompt    db    "Pick ICT's whose traces are to be included in dump$"
  1566.  
  1567.  
  1568. ;*********************************************
  1569. ;
  1570. ; Set or Clear F_ENABLE.
  1571. ;
  1572. ; On entry, AL holds bit value for F_ENABLE (i.e. - ON or OFF).
  1573. ;
  1574. ; This routine asks user for ICT's to be enabled or disabled.
  1575. ;
  1576. ;*********************************************
  1577.  
  1578. do_enable proc    near
  1579.     push    si
  1580.     push    dx
  1581.     push    cx
  1582.     push    bx
  1583.     push    ax            ;push him last so we can get to him
  1584.  
  1585.     mov    dx,offset enable_prompt    ;Assume "Enable"
  1586.     test    al,F_ENABLE        ;are we enabling?
  1587.     jnz    do_enable1        ;yes, we have right message
  1588.     mov    dx,offset disable_prompt ;Use "Disable" message
  1589.  
  1590. do_enable1:
  1591.     call    pick_ict        ;get ICT's to be affected
  1592.     jc    do_enable9        ;user wants to forget it
  1593.     mov    byte ptr enable_map,al    ;save bitmap of ICT's to be done
  1594.     xor    si,si            ;start with ICT #0
  1595.     mov    cx,8            ;number of ICT's to look at
  1596.  
  1597. do_enable2:
  1598.     test    byte ptr enable_map,1    ;Should this ICT be done?
  1599.     jz    do_enable5        ;no
  1600.     mov    bx,ict_index[si]    ;yes, point to ICT
  1601.     cli                ;*** NO INTERRUPTS!!! ***
  1602.     pop    ax            ;get F_ENABLE value
  1603.     push    ax
  1604.     and    al,F_ENABLE        ;isolate our bit
  1605.     mov    ah,[bx].ICT_flags    ;get current flags value
  1606.     and    ah,F_ENABLE XOR 0ffh    ;turn off our bit
  1607.     or    ah,al            ;set it per caller's desire
  1608.     mov    [bx].ICT_flags,ah    ;replace it in ICT
  1609.     STI                ;*** INTERRUPTS OK NOW ***
  1610.  
  1611. do_enable5:
  1612.     add    si,2            ;up to next ICT
  1613.     shr    byte ptr enable_map,1    ;get next ICT's bitmap bit to Bit 0
  1614.     loop    do_enable2        ;till we've looked at all ICT's
  1615.  
  1616. do_enable9:
  1617.     pop    ax
  1618.     pop    bx
  1619.     pop    cx
  1620.     pop    dx
  1621.     pop    si
  1622.     ret
  1623. do_enable endp
  1624.  
  1625. enable_prompt    db    "Pick ICT's to have tracing ENABLED$"
  1626. disable_prompt    db    "Pick ICT's to have tracing DISABLED$"
  1627. enable_map    db    0        ;bitmap of ICT's to be altered
  1628.  
  1629.  
  1630.  
  1631.  
  1632. ;*********************************************
  1633. ;
  1634. ; Toggle F_FCB in some ICT's.
  1635. ;
  1636. ;*********************************************
  1637.  
  1638. do_fcb proc    near
  1639.     push    si
  1640.     push    dx
  1641.     push    cx
  1642.     push    bx
  1643.     push    ax            ;push him last so we can get to him
  1644.  
  1645.     mov    dx,offset fcb_toggle
  1646.     call    pick_ict        ;get ICT's to be affected
  1647.     jc    do_fcb9            ;user wants to forget it
  1648.     xor    si,si            ;start with ICT #0
  1649.     mov    cx,8            ;number of ICT's to look at
  1650.  
  1651. do_fcb2:
  1652.     test    al,1            ;Should this ICT be done?
  1653.     jz    do_fcb5            ;no
  1654.     mov    bx,ict_index[si]    ;yes, point to ICT
  1655.     xor    [bx].ICT_flags,F_FCB    ;toggle current setting
  1656.  
  1657. do_fcb5:
  1658.     add    si,2            ;up to next ICT
  1659.     shr    al,1            ;get next ICT's bitmap bit to Bit 0
  1660.     loop    do_fcb2            ;till we've looked at all ICT's
  1661.  
  1662. do_fcb9:
  1663.     pop    ax
  1664.     pop    bx
  1665.     pop    cx
  1666.     pop    dx
  1667.     pop    si
  1668.     ret
  1669. do_fcb endp
  1670.  
  1671. fcb_toggle    db    "Pick ICT's to have F_FCB toggled$"
  1672.  
  1673.     subttl    Reporting Routines
  1674.     page
  1675. ;**************************************************
  1676. ;
  1677. ; Dump trace buffer for ICT's represented by bitmap in AL.
  1678. ;
  1679. ; If bit n in AL is set, then ICT n's trace records are to be included
  1680. ; in dump.
  1681. ;
  1682. ;**************************************************
  1683.  
  1684.  
  1685. dump_buf proc    near
  1686.     push    di
  1687.     push    si
  1688.     push    dx
  1689.     push    cx
  1690.     push    bx
  1691.     push    ax            ;push bitmap last so that we can get to it
  1692.     xor    di,di            ;di is printed line counter
  1693.     mov    si,offset trace_table   ;start at front of buf
  1694.  
  1695. dump_buf2:
  1696.     cmp    si,next_byte        ;done whole buffer?
  1697.     jae    dump_buf9        ;yes, exit
  1698.  
  1699. ;
  1700. ; Let a keypress interrupt us
  1701. ;
  1702.  
  1703.     mov    ah,1            ;ROM BIOS "Check for keypress" func
  1704.     int    016h            ;keypress present?
  1705.     jnz    dump_buf9        ;yes, exit
  1706.  
  1707.     mov    al,[si].B_type        ;get ICT #
  1708.     call    bin_to_bit        ;convert to bitmap bit
  1709.     pop    bx            ;peek at caller's requested bitmap
  1710.     push    bx
  1711.     and    bl,al            ;is this ICT included in caller's bitmap?
  1712.     jz    dump_buf5        ;no, skip it
  1713.  
  1714. ;
  1715. ; See if it's time for title line
  1716. ;
  1717.  
  1718.     test    di,07h            ;every 8 lines
  1719.     jnz    dump_buf4        ;not time for title line
  1720.     mov    dx,offset dump_title    ;print title line
  1721.     call    print_line
  1722.  
  1723. dump_buf4:
  1724.     call    dump_rec        ;dump this record
  1725.     inc    di            ;bump # lines printed
  1726.  
  1727. dump_buf5:
  1728.  
  1729. ;
  1730. ; Skip over this record, to next one. To do that, we need to know what
  1731. ; type of record it is, so that we know how big a record
  1732. ; we have to skip over.
  1733. ;
  1734.  
  1735.     mov    bl,[si].B_type        ;get trace record type
  1736.     and    bx,11110000b        ;isolate type itself
  1737.     shr    bx,1            ;develop type times 2
  1738.     shr    bx,1
  1739.     shr    bx,1
  1740.     add    si,rec_sizes[bx]    ;add record size to current pointer
  1741.     jmp    dump_buf2        ;continue till buffer exhausted
  1742.  
  1743. dump_buf9:
  1744.     pop    ax
  1745.     pop    bx
  1746.     pop    cx
  1747.     pop    dx
  1748.     pop    si
  1749.     pop    di
  1750.     ret
  1751. dump_buf endp
  1752.  
  1753. dump_title    db    0dh,0ah
  1754.         db    0dh,0ah
  1755.         db    "INT #   AX   BX   CX   DX   ES   DS   SI   DI   BP   SS   SP   CS:IP"
  1756.         db    0dh,0ah
  1757.         db    "--- -   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---------$"
  1758.  
  1759. ;***********************************************
  1760. ;
  1761. ; Given binary number (0-7) in AL, return bitmap in AL with corresponding
  1762. ; bit (Bit 0 thru Bit 7) set.
  1763. ;
  1764. ; AH is zeroed.
  1765. ;
  1766. ;***********************************************
  1767.  
  1768. bin_to_bit proc    near
  1769.     mov    ah,al        ;AH is counter, from 7 to 0
  1770.     mov    al,1        ;AL is bitmap, Bit 0 to Bit 7
  1771.     and    ah,7        ;constrain input
  1772.     jz    bin_to_bit9    ;binary was 0, so return with Bit 0 set
  1773.  
  1774. bin_to_bit3:
  1775.     add    al,al        ;shift bitmap left 1 bit
  1776.     dec    ah        ;dec count by one
  1777.     jnz    bin_to_bit3
  1778.  
  1779. bin_to_bit9:
  1780.     ret
  1781. bin_to_bit endp
  1782.  
  1783. ;***********************************************
  1784. ;
  1785. ; Dump trace record at [SI]. This routine prints the common
  1786. ; header information, then calls specific routines to expand
  1787. ; details.
  1788. ;
  1789. ;***********************************************
  1790.  
  1791. dump_rec proc    near
  1792.     push    si
  1793.     push    dx
  1794.     push    cx
  1795.     push    bx
  1796.     push    ax
  1797.  
  1798.     call    crlf
  1799.     mov    al,[si].B_int        ;get Interrupt #
  1800.     call    print_hex        ;show interrupt #
  1801.     mov    al,'H'
  1802.     call    print
  1803.     mov    al,' '
  1804.     call    print
  1805.     mov    al,[si].B_type        ;get ICT #
  1806.     and    al,7
  1807.     or    al,'0'            ;make into ASCII digit
  1808.     call    print
  1809.     mov    al,' '
  1810.     call    print
  1811.     mov    bl,[si].B_type        ;get trace type
  1812.     and    bx,11110000b        ;isolate type of trace
  1813.     shr    bx,1            ;develop type times 2
  1814.     shr    bx,1
  1815.     shr    bx,1
  1816.     mov    bx,word ptr dump_table[bx]
  1817.     call    bx            ;call proper specific routine
  1818.     pop    ax
  1819.     pop    bx
  1820.     pop    cx
  1821.     pop    dx
  1822.     pop    si
  1823.     ret
  1824. dump_rec endp
  1825.  
  1826. ;
  1827. ; Table of routines to handle various record types
  1828. ;
  1829.  
  1830. dump_table    label    word
  1831.         dw    offset dump_before    ;record type 0 = BEFORE
  1832.         dw    offset dump_after    ;record type 1 = AFTER
  1833.         dw    offset dump_fcb        ;record type 2 = FCB
  1834.         dw    offset dump_asciiz    ;record type 3 = ASCIIZ
  1835.  
  1836. ;***********************************************
  1837. ;
  1838. ; Dump BEFORE record at [SI]
  1839. ;
  1840. ;***********************************************
  1841.  
  1842. dump_before proc near
  1843.     push    si
  1844.     push    dx
  1845.     push    cx
  1846.     push    bx
  1847.     push    ax
  1848.     mov    al,'B'            ;Display "B" for BEFORE
  1849.     call    print
  1850.     mov    al,' '            ;plus blank after
  1851.     call    print
  1852.     mov    ax,[si].B_ax
  1853.     call    print_wordb
  1854.     mov    ax,[si].B_bx
  1855.     call    print_wordb
  1856.     mov    ax,[si].B_cx
  1857.     call    print_wordb
  1858.     mov    ax,[si].B_dx
  1859.     call    print_wordb
  1860.     mov    ax,[si].B_es
  1861.     call    print_wordb
  1862.     mov    ax,[si].B_ds
  1863.     call    print_wordb
  1864.     mov    ax,[si].B_si
  1865.     call    print_wordb
  1866.     mov    ax,[si].B_di
  1867.     call    print_wordb
  1868.     mov    ax,[si].B_bp
  1869.     call    print_wordb
  1870.     mov    ax,[si].B_ss
  1871.     call    print_wordb
  1872.     mov    ax,[si].B_sp
  1873.     call    print_wordb
  1874.     mov    dx,[si].B_cs
  1875.     mov    ax,[si].B_ip
  1876.     call    print_seg
  1877.  
  1878. ;
  1879. ; Try to interpret this BEFORE record, to make reading easier
  1880. ;
  1881.  
  1882.     call    interp
  1883.     pop    ax
  1884.     pop    bx
  1885.     pop    cx
  1886.     pop    dx
  1887.     pop    si
  1888.     ret
  1889. dump_before endp
  1890.  
  1891. ;***********************************************
  1892. ;
  1893. ; Dump AFTER record at [SI]
  1894. ;
  1895. ;***********************************************
  1896.  
  1897. dump_after proc near
  1898.     push    si
  1899.     push    dx
  1900.     push    cx
  1901.     push    bx
  1902.     push    ax
  1903.     mov    al,'A'            ;Display "A" for AFTER
  1904.     call    print
  1905.     mov    al,' '            ;plus blank after
  1906.     call    print
  1907.     mov    ax,[si].A_ax
  1908.     call    print_wordb
  1909.     mov    ax,[si].A_bx
  1910.     call    print_wordb
  1911.     mov    ax,[si].A_cx
  1912.     call    print_wordb
  1913.     mov    ax,[si].A_dx
  1914.     call    print_wordb
  1915.     mov    ax,[si].A_es
  1916.     call    print_wordb
  1917.     mov    ax,[si].A_ds
  1918.     call    print_wordb
  1919.     mov    ax,[si].A_si
  1920.     call    print_wordb
  1921.     mov    ax,[si].A_di
  1922.     call    print_wordb
  1923.     mov    ax,[si].A_bp
  1924.     call    print_wordb
  1925.  
  1926. ;
  1927. ; Now expand flags byte for clarity
  1928. ;
  1929.  
  1930.     mov    dx,[si].A_flags        ;hold flags in DX
  1931.     mov    si,offset dump_flags    ;SI = next flag's name
  1932.     mov    bx,0fd5h        ;mask of valid bits in flags word
  1933.     mov    cx,12            ;# bits to walk through
  1934.     cld                ;forward!!!
  1935.  
  1936. dump_after2:
  1937.     test    bx,1            ;is this a valid flag bit?
  1938.     jz    dump_after4        ;no, move to next one
  1939.     lodsb                ;yes, get next name
  1940.     test    dx,1            ;is bit set?
  1941.     jnz    dump_after3        ;yes, use name
  1942.     mov    al,' '            ;no, use blank
  1943.  
  1944. dump_after3:
  1945.     call    print            ;print flag name or space
  1946.  
  1947. dump_after4:
  1948.     shr    dx,1            ;shift flags so next flag is in bit 0
  1949.     shr    bx,1            ;ditto for mask
  1950.     loop    dump_after2        ;till done all 12 bits
  1951.  
  1952.     pop    ax
  1953.     pop    bx
  1954.     pop    cx
  1955.     pop    dx
  1956.     pop    si
  1957.     ret
  1958. dump_after endp
  1959.  
  1960. dump_flags    db    "CPAZSTIDO"
  1961.  
  1962.  
  1963. ;***********************************************
  1964. ;
  1965. ; Dump FCB record at [SI]
  1966. ;
  1967. ;***********************************************
  1968.  
  1969. dump_fcb proc near
  1970.     push    si
  1971.     push    dx
  1972.     push    cx
  1973.     push    bx
  1974.     push    ax
  1975.     mov    al,[si].FCB_drive    ;display drive # as number
  1976.     mov    byte ptr fcb_drv,al
  1977.     mov    dx,offset fcb_line    ;and put up rest of header
  1978.     call    print_edit
  1979.     add    si,3            ;skip to filename field
  1980.     mov    cx,8            ;max # chars to display
  1981.     cld                ;forward!!!
  1982.  
  1983. dump_fcb2:
  1984.     lodsb                ;get byte of filename
  1985.     cmp    al,020h            ;control char or blank?
  1986.     jbe    dump_fcb3b        ;yes, we're done with name
  1987.     call    print            ;no, display char as-is
  1988.     loop    dump_fcb2        ;till 8 done or early exit
  1989.     jmp    short dump_fcb4
  1990.  
  1991. dump_fcb3:                ;skip over rest of filename
  1992.     lodsb
  1993.  
  1994. dump_fcb3b:
  1995.     loop    dump_fcb3
  1996.  
  1997. dump_fcb4:                ;output extension too
  1998.     mov    al,'.'            ;seperate it with period
  1999.     call    print
  2000.     mov    cx,3            ;# extension bytes to print
  2001.  
  2002. dump_fcb5:
  2003.     lodsb                ;get byte of extension
  2004.     cmp    al,020h            ;control char?
  2005.     jb    dump_fcb6        ;yes, skip it
  2006.     call    print            ;no, use as-is
  2007.  
  2008. dump_fcb6:
  2009.     loop    dump_fcb5
  2010.     pop    ax
  2011.     pop    bx
  2012.     pop    cx
  2013.     pop    dx
  2014.     pop    si
  2015.     ret
  2016. dump_fcb endp
  2017.  
  2018.  
  2019. fcb_line    label    byte
  2020.         db    "FCB Drive:"
  2021.         db    Edit_Dec8
  2022. fcb_drv        db    0
  2023.         db    " Filename: "
  2024.         db    Edit_End
  2025.  
  2026. ;***********************************************
  2027. ;
  2028. ; Dump ASCIIZ record at [SI]
  2029. ;
  2030. ;***********************************************
  2031.  
  2032. dump_asciiz proc near
  2033.     push    si
  2034.     push    dx
  2035.     push    cx
  2036.     push    bx
  2037.     push    ax
  2038.     mov    dx,offset asciiz_line    ;put up header
  2039.     call    print_line
  2040.     add    si,2            ;skip to start of ASCIIZ text
  2041.     mov    cx,size ASCIIZ        ;max # chars to display
  2042.     sub    cx,2            ;(minus 2 for header)
  2043.     cld                ;forward!!!
  2044.  
  2045. dump_asciiz5:
  2046.     lodsb                ;get byte of extension
  2047.     or    al,al            ;NUL terminator?
  2048.     jz    dump_asciiz9        ;yes, exit
  2049.     cmp    al,020h            ;control char?
  2050.     jb    dump_asciiz6        ;yes, skip it
  2051.     call    print            ;no, use as-is
  2052.  
  2053. dump_asciiz6:
  2054.     loop    dump_asciiz5
  2055.  
  2056. dump_asciiz9:
  2057.     pop    ax
  2058.     pop    bx
  2059.     pop    cx
  2060.     pop    dx
  2061.     pop    si
  2062.     ret
  2063. dump_asciiz endp
  2064.  
  2065.  
  2066. asciiz_line    label    byte
  2067.         db    "ASCIIZ: $"
  2068.  
  2069.  
  2070. ;*****************************************
  2071. ;
  2072. ; Display what we know about ICT # AL (0-7).
  2073. ;
  2074. ;*****************************************
  2075.  
  2076. ict_dump proc    near
  2077.     push    dx
  2078.     push    bx
  2079.     push    ax
  2080.  
  2081.     and    ax,7            ;edit ICT #
  2082.     mov    bx,ax            ;get ICT #
  2083.     shl    bx,1
  2084.     mov    bx,ict_index[bx]    ;[BX] --> ICT itself
  2085.  
  2086.     or    al,030h            ;make ASCII digit for message
  2087.     mov    byte ptr ict_msg1a,al    ;insert it into message
  2088.     mov    dx,offset ict_msg1      ;"ICT #n at ..."
  2089.     call    print_line
  2090.  
  2091.     mov    dx,ds            ;display seg:offset of ICT
  2092.     mov    ax,bx
  2093.     call    print_seg
  2094.  
  2095.     mov    dx,offset ict_ena    ;show whether enabled or disabled
  2096.     test    [bx].ICT_flags,F_ENABLE
  2097.     jnz    ict_dump2        ;got right message
  2098.     mov    dx,offset ict_dis    ;get other message
  2099.  
  2100. ict_dump2:
  2101.     call    print_line        ;display "ENABLED" or "DISABLED"
  2102.  
  2103.     mov    dx,offset ict_msg2      ;"INT xxH "
  2104.     call    print_line
  2105.     mov    al,[bx].ICT_intnum    ;display interrupt #
  2106.     call    print_hex
  2107.  
  2108.     mov    dx,offset ict_msg3      ;"AH range ll/hh"
  2109.     call    print_line
  2110.     mov    al,[bx].ICT_AH_lo    ;display AH range lower limit
  2111.     call    print_hex
  2112.     mov    al,'/'          ;add seperator
  2113.     call    print
  2114.     mov    al,[bx].ICT_AH_hi       ;display AH range upper limit
  2115.     call    print_hex
  2116.  
  2117.     mov    al,'*'            ;display '*' if FCB/ASCIIZ set
  2118.     test    [bx].ICT_flags,F_FCB
  2119.     jnz    ict_dump3        ;it's set
  2120.     mov    al,' '            ;not set, so use blank
  2121.  
  2122. ict_dump3:
  2123.     call    print
  2124.  
  2125.     mov    dx,offset ict_msg4      ;"Exit: RET/RET2/IRET"
  2126.     call    print_line
  2127.     mov    al,[bx].ICT_flags    ;interpret exit type
  2128.     mov    dx,offset ict_exit    ;get to first 6-char message
  2129.     test    al,F_RET
  2130.     jz    ict_dump5        ;not this one
  2131.     call    print_line
  2132.  
  2133. ict_dump5:
  2134.     add    dx,6            ;up to next 6-char exit name
  2135.     test    al,F_RET2
  2136.     jz    ict_dump6        ;not this one
  2137.     call    print_line
  2138.  
  2139. ict_dump6:
  2140.     add    dx,6            ;up to next 6-char exit name
  2141.     test    al,F_IRET
  2142.     jz    ict_dump7        ;not this one
  2143.     call    print_line
  2144.  
  2145. ict_dump7:
  2146.     mov    dx,offset ict_msg4a    ;"Hits: "
  2147.     call    print_line
  2148.     mov    ax,[bx].ICT_hits
  2149.     call    print_dec
  2150.  
  2151.     pop    ax
  2152.     pop    bx
  2153.     pop    dx
  2154.     ret
  2155.  
  2156. ict_msg1    db    0dh,0ah,"ICT#"
  2157. ict_msg1a    db    "0 @ $"
  2158. ict_msg2    db    " INT $"
  2159. ict_msg3    db    "H AH:$"
  2160. ict_msg4    db    " Exit:$"
  2161. ict_msg4a    db    "Hits: $"
  2162. ict_exit    db    "RET  $"    ;6-char exit type names
  2163.         db    "RET2 $"
  2164.         db    "IRET $"
  2165. ict_ena        db    " ENABLED $"
  2166. ict_dis        db    " DISABLED$"
  2167.  
  2168. ict_dump endp
  2169.  
  2170.  
  2171. ;*********************************************
  2172. ;
  2173. ; Display all active ICT's
  2174. ;
  2175. ;*********************************************
  2176.  
  2177. disp_active    proc    near
  2178.     push    si
  2179.     push    ax
  2180.     push    bx
  2181.     push    cx
  2182.  
  2183.     mov    cx,8            ;Number of ICT's
  2184.     xor    si,si            ;start with # 0
  2185.  
  2186. disp_active2:
  2187.     mov    bx,ict_index[si]    ;[BX] --> ICT
  2188.     test    [bx].ICT_flags,F_ACTIVE    ;Is this ICT active?
  2189.     jz    disp_active5        ;no, skip it
  2190.     mov    ax,si            ;yes, develop ICT # 0-7
  2191.     shr    ax,1
  2192.     call    ict_dump        ;display it
  2193.  
  2194. disp_active5:
  2195.     add    si,2            ;up to next ICT
  2196.     loop    disp_active2        ;till we've done all of them
  2197.     pop    cx
  2198.     pop    bx
  2199.     pop    ax
  2200.     pop    si
  2201.     ret
  2202. disp_active endp
  2203.  
  2204.     subttl    Interpretation - Misc Routines
  2205.     page
  2206. ;********************************************************************
  2207. ;*                                                                  *
  2208. ;*  This file contains the routines that interpret selected         *
  2209. ;*  BEFORE trace records and print out sensible summaries of        *
  2210. ;*  their meanings. This sure beats having to read a lotta hex      *
  2211. ;*  function codes.                                                 *
  2212. ;*                                                                  *
  2213. ;*  The main routine - interp() - is called just after we've        *
  2214. ;*  printed all of the trace record in hex. If this record is       *
  2215. ;*  one that we know about, we should now print a one-line          *
  2216. ;*  interpretation of the record. This is done via lower-level      *
  2217. ;*  routines called by interp() per the INT in the record.          *
  2218. ;*                                                                  *
  2219. ;********************************************************************
  2220.  
  2221.  
  2222. ;********************************************************************
  2223. ;
  2224. ; Interpret BEFORE trace record at [SI].
  2225. ;
  2226. ;********************************************************************
  2227.  
  2228. interp    proc    near
  2229.     push    bx
  2230.     push    ax
  2231.     mov    ah,[SI].B_int        ;get INT type
  2232.     mov    bx,offset interp_tab    ;point to table of handlers
  2233.  
  2234. interp2:
  2235.     cmp    ah,[bx]            ;does this handler go with this INT?
  2236.     jnz    interp5            ;no
  2237.     mov    bx,1[bx]        ;yes, get handler's address
  2238.     call    bx            ;call that handler
  2239.     jmp    interp9            ;exit
  2240.  
  2241. interp5:
  2242.     add    bx,3            ;up to next entry in table
  2243.     cmp    bx,offset interp_end    ;searched whole table yet?
  2244.     jb    interp2            ;no, try next one
  2245.  
  2246. interp9:
  2247.  
  2248.     pop    ax
  2249.     pop    bx
  2250.         ret
  2251. interp    endp
  2252.  
  2253. ;
  2254. ; Table of interpreters for various interrupts.
  2255. ;
  2256. ; Each entry is as follows:
  2257. ;
  2258. ;       db    <intnum>        ;interrupt number
  2259. ;       dw    offset <handler>    ;address of handler to interpret this int's record
  2260. ;
  2261. ;
  2262.  
  2263. interp_tab    label    byte
  2264.         db    013h            ;INT 13h is Diskette I/O
  2265.         dw    offset interp_13    ;handler for INT 13h
  2266.         db    021h            ;INT 21h is DOS Function Handler
  2267.         dw    offset interp_21    ;handler for INT 21h
  2268.         db    025h            ;INT 025H is DOS ABSOLUTE DISK READ
  2269.         dw    offset interp_25
  2270.         db    026h            ;INT 026H is DOS ABSOLUTE DISK WRITE
  2271.         dw    offset interp_25    ;uses same interpreter
  2272. interp_end    label    byte            ;end of table
  2273.  
  2274.     subttl    Interpretation - INT 13 (Diskette I/O)
  2275.     page
  2276. ;
  2277. ; Tables used to interpret INT 13h
  2278. ;
  2279.  
  2280. Floppy_or_Hard    db    0,"Floppy:",0
  2281.         db    080h,"Fixed:",080h
  2282.  
  2283. Cyl_or_Track    db    0,"Track:",0
  2284.         db    080h,"Cyl:",080h
  2285.  
  2286. int13_functab    label    byte
  2287.         db    0,"Reset Disk",0
  2288.         db    1,"Read Status",0
  2289.         db    2,"Read to ES:BX",0
  2290.         db    3,"Write from ES:BX",0
  2291.         db    4,"Verify",0
  2292.         db    5,"Format Track per ES:BX",0
  2293.         db    6,"Format & Set Bad Sects",0
  2294.         db    7,"Format Drive from Track",0
  2295.         db    8,"Get Drive Params",0
  2296.         db    9,"Init Drive Params",0
  2297.         db    10,"Read Long",0
  2298.         db    11,"Write Long",0
  2299.         db    12,"Seek",0
  2300.         db    13,"Alt Disk Reset",0
  2301.         db    14,"Read Sect Buf",0
  2302.         db    15,"Write Sect Buf",0
  2303.         db    16,"Test Drive Ready",0
  2304.         db    17,"Recalibrate",0
  2305.         db    18,"Ram Diagnostic",0
  2306.         db    19,"Drive Diagnostic",0
  2307.         db    20,"Internal Diagnostic",0
  2308.         db    21,"Get Disk Type",0
  2309.         db    22,"Change Status",0
  2310.         db    23,"Set Disk Type",080h
  2311.  
  2312. int13_line    label    byte
  2313.         db    0dh,0ah,"      "
  2314.         db    Edit_Call
  2315. int13_F_or_H    db    0
  2316.         dw    offset Floppy_or_Hard
  2317.         dw    offset table_print
  2318.         db    Edit_Dec8
  2319. int13_drive    db    0
  2320.         db    " Head:"
  2321.         db    Edit_Dec8
  2322. int13_head    db    0
  2323.         db    " "
  2324.         db    Edit_Call
  2325. int13_C_or_T    db    0
  2326.         dw    offset Cyl_or_Track
  2327.         dw    offset table_print
  2328.         db    Edit_Dec16
  2329. int13_cyl    dw    0
  2330.         db    " Sect:"
  2331.         db    Edit_Dec8
  2332. int13_sect    db    0
  2333.         db    " #Sects:"
  2334.         db    Edit_Dec8
  2335. int13_numsects    db    0
  2336.         db    " "
  2337.         db    Edit_Call
  2338. int13_func    db    0
  2339.         dw    offset int13_functab
  2340.         dw    offset table_print
  2341.         db    Edit_End
  2342.  
  2343. ;**************************************************
  2344. ;
  2345. ; Interpret INT 13h BEFORE trace record at [SI]
  2346. ;
  2347. ;**************************************************
  2348.  
  2349. interp_13 proc    near
  2350.     push    dx
  2351.     push    cx
  2352.     push    ax
  2353.     mov    dx,[SI].B_dx        ;get DX at time of INT
  2354.     mov    al,dl            ;Get drive #
  2355.     and    al,080h            ;isolate floppy/hard bit
  2356.     mov    int13_F_or_H,al        ;use it to select device name...
  2357.     mov    int13_C_or_T,al        ;...as well as cylinders/tracks
  2358.     and    dl,07fh            ;isolate drive #
  2359.     mov    int13_drive,dl
  2360.     mov    int13_head,dh        ;store head #
  2361.     mov    cx,[SI].B_cx        ;get CX at time of INT
  2362.     xor    ax,ax            ;calc 10-bit cylinder #
  2363.     mov    al,cl
  2364.     shl    ax,1
  2365.     shl    ax,1
  2366.     mov    al,ch
  2367.     mov    int13_cyl,ax        ;save as word
  2368.     and    cl,00111111b        ;isolate sector #
  2369.     mov    int13_sect,cl
  2370.     mov    ax,[SI].B_ax        ;get AX at time of INT
  2371.     mov    int13_numsects,al
  2372.     mov    int13_func,ah
  2373.     mov    dx,offset int13_line    ;now print edited line
  2374.     call    print_edit
  2375.     pop    ax
  2376.     pop    cx
  2377.     pop    dx
  2378.     ret
  2379. interp_13 endp
  2380.  
  2381.     subttl    Interpretation - INT 21h (DOS)
  2382.     page
  2383. ;
  2384. ; Tables used in interpreting INT 21h
  2385. ;
  2386.  
  2387. int21_functab label byte
  2388.     db    0,"Terminate program",0
  2389.     db    1,"Console input w/echo to AL",0
  2390.     db    2,"Display Output of DL",0
  2391.     db    3,"AUX input to AL",0
  2392.     db    4,"AUX output from DL",0
  2393.     db    5,"Printer output from DL",0
  2394.     db    6,"Input to AL (DL=0FFh) or Display DL",0
  2395.     db    7,"Raw keyboard input w/o echo to AL",0
  2396.     db    8,"Console input w/o echo to AL",0
  2397.     db    9,"Print string at DS:DX till '$'",0
  2398.     db    0ah,"Buffered console input to DS:DX",0
  2399.     db    0bh,"Set AL=0FFh if input ready, else AL=0",0
  2400.     db    0ch,"Clear buf and do function in AL",0
  2401.     db    0dh,"Reset disk",0
  2402.     db    0eh,"Select drive per DL (0=A)",0
  2403.     db    0fh,"Open file, FCB at DS:DX",0
  2404.     db    10h,"Close file, FCB at DS:DX",0
  2405.     db    11h,"Search for first per pattern FCB at DS:DX",0
  2406.     db    12h,"Search for next per pattern FCB at DS:DX",0
  2407.     db    13h,"Delete file per FCB at DS:DX",0
  2408.     db    14h,"Read sequential, FCB at DS:DX",0
  2409.     db    15h,"Write sequential, FCB at DS:DX",0
  2410.     db    16h,"Create file, FCB at DS:DX",0
  2411.     db    17h,"Rename file, special FCB at DS:DX",0
  2412.     db    19h,"Return current drive in AL (0=A)",0
  2413.     db    1ah,"Set DTA to DS:DX",0
  2414.     db    1bh,"Get FAT info for default drive",0
  2415.     db    1ch,"Get FAT info for drive DL (0=default)",0
  2416.     db    21h,"Random Read, FCB at DS:DX",0
  2417.     db    22h,"Random Write, FCB at DS:DX",0
  2418.     db    23h,"Set file size per FCB pattern at DS:DX",0
  2419.     db    24h,"Set random rec field in FCB at DS:DX",0
  2420.     db    25h,"Set Interrupt <AL> vector to DS:DX",0
  2421.     db    26h,"Create new segment at <DX>:0000",0
  2422.     db    27h,"Random Read of <CX> records, FCB at DS:DX",0
  2423.     db    28h,"Random Write of <CX> records, FCB at DS:DX",0
  2424.     db    29h,"Parse filename at DS:SI into FCB at ES:DI",0
  2425.     db    2ah,"Get year to CX, month to DH, day to DL",0
  2426.     db    2bh,"Set year to CX, month to DH, day to DL",0
  2427.     db    2ch,"Get CH=hours CL=mins DH=secs DL=tenths",0
  2428.     db    2dh,"Set hours=CH mins=CL secs=DH tenths=DL",0
  2429.     db    2eh,"IFF DL=0 then set VERIFY per AL",0
  2430.     db    2fh,"Get DTA to ES:BX",0
  2431.     db    30h,"Get DOS version to AL (major), AH (minor)",0
  2432.     db    31h,"Term/stay resident, DX=# para's AL=exit code",0
  2433.     db    33h,"Request (AL=0) or set (AL=1,DL=value) BREAK value",0
  2434.     db    34h,"Set ES:BX to DOS 'in-use' flag",0
  2435.     db    35h,"Set ES:BX to vector for INT # <AL>",0
  2436.     db    36h,"Get disk space for drive DL (0=default)",0
  2437.     db    38h,"Return country info to DS:DX",0
  2438.     db    39h,"Create directory per ASCIIZ at DS:DX",0
  2439.     db    3ah,"Remove directory per ASCIIZ at DS:DX",0
  2440.     db    3bh,"Change directory to ASCIIZ at DS:DX",0
  2441.     db    3ch,"Create file per ASCIIZ at DS:DX, attrib <CX>",0
  2442.     db    3dh,"Open file per ASCIIZ at DS:DX, access <AL>",0
  2443.     db    3eh,"Close file handle <BX>",0
  2444.     db    3fh,"Read <CX> bytes from file handle <BX> to DS:DX",0
  2445.     db    40h,"Write <CX> bytes from DS:DX to file handle <BX>",0
  2446.     db    41h,"Delete file per ASCIIZ at DS:DX",0
  2447.     db    42h,"LSEEK file handle <BX> <CX:DX> bytes, method <AL>",0
  2448.     db    43h,"Set (AL=1, CX=value) or get (AL=0) attrib for ASCIIZ at DS:DX",0
  2449.     db    44h,"IOCTL for file handle <BX>, func <AL>",0
  2450.     db    45h,"DUP file handle <BX> into <AX>",0
  2451.     db    46h,"Force DUP of handle <BX> into handle <CX>",0
  2452.     db    47h,"Get cur dir for drive <DL> (0=default) to DS:SI",0
  2453.     db    48h,"Allocate <BX> paragraphs, address to AX",0
  2454.     db    49h,"Free block starting at <ES>",0
  2455.     db    4ah,"Modify segment <ES> to be <BX> para's in size",0
  2456.     db    4bh,"EXEC file at ASCIIZ DS:DX, func <AL>",0
  2457.     db    4ch,"Terminate with exit code <AL>",0
  2458.     db    4dh,"Get EXIT return code to AX",0
  2459.     db    4eh,"Find first per ASCIIZ at DS:DX and attrib <CX>",0
  2460.     db    4fh,"Find next per current DTA",0
  2461.     db    54h,"Get VERIFY state to AL",0
  2462.     db    56h,"Rename filename at ASCIIZ DS:DX to ASCIIZ at ES:DI",0
  2463.     db    57h,"Get (AL=0) or set (AL=1) date/time for file handle <BX>",0
  2464.     db    59h,"Get extended error code",0
  2465.     db    5ah,"Create temp file per ASCIIZ DS:DX and attrib <CX>",0
  2466.     db    5bh,"Create new file per ASCIIZ DS:DX and attrib <CX>",0
  2467.     db    5ch,"Lock (AL=0) or unlock (AL=1) file handle <BX>",0
  2468.     db    62h,"Get PSP segment address to BX",080h
  2469.  
  2470. int21_line label byte
  2471.         db    0dh,0ah,"      DOS: "
  2472.         db    Edit_Call
  2473. int21_func    db    0
  2474.         dw    offset int21_functab
  2475.         dw    offset table_print
  2476.         db    Edit_End
  2477.  
  2478. ;**************************************************
  2479. ;
  2480. ; Interpret INT 21h BEFORE trace record at [SI]
  2481. ;
  2482. ;**************************************************
  2483.  
  2484. interp_21 proc    near
  2485.     push    dx
  2486.     push    ax
  2487.     mov    ax,[SI].B_ax        ;get AX at time of int
  2488.     mov    byte ptr int21_func,ah    ;use it to select function
  2489.     mov    dx,offset int21_line
  2490.     call    print_edit
  2491.     pop    ax
  2492.     pop    dx
  2493.     ret
  2494. interp_21 endp
  2495.  
  2496.     subttl    Interpretation - INT 25h and 26h (Absolute disk I/O)
  2497.     page
  2498. ;
  2499. ; Tables used to interpret INT's 25h and 26h
  2500. ;
  2501.  
  2502. int25_functab    label    byte
  2503.         db    025h,"Read",0
  2504.         db    026h,"Write",080h
  2505.  
  2506. int25_line    label    byte
  2507.         db    0dh,0ah,"      DOS Absolute "
  2508.         db    Edit_Call
  2509. int25_func    db    0
  2510.         dw    offset int25_functab
  2511.         dw    offset table_print
  2512.         db    " Drive:"
  2513.         db    Edit_Dec8
  2514. int25_drv    db    0
  2515.         db    " Sector:"
  2516.         db    Edit_Dec16
  2517. int25_sect    dw    0
  2518.         db    " #Sectors:"
  2519.         db    Edit_Dec16
  2520. int25_numsects    dw    0
  2521.         db    " Buf "
  2522.         db    Edit_Word
  2523. int25_seg    dw    0
  2524.         db    ":"
  2525.         db    Edit_Word
  2526. int25_off    dw    0
  2527.         db    Edit_End
  2528.  
  2529. ;**************************************************
  2530. ;
  2531. ; Interpret INT 25h or INT 26h BEFORE trace record at [SI]
  2532. ;
  2533. ;**************************************************
  2534.  
  2535. interp_25 proc    near
  2536.     push    dx
  2537.     push    ax
  2538.     mov    al,[SI].B_int        ;get INT that was done (25h or 26h)
  2539.     mov    int25_func,al        ;move to printline
  2540.     mov    ax,[SI].B_ax        ;get drive # from AL
  2541.     mov    int25_drv,al        ;move to printline
  2542.     mov    ax,[SI].B_dx        ;get starting sector # from DX
  2543.     mov    int25_sect,ax        ;move to printline
  2544.     mov    ax,[SI].B_cx        ;get # sectors from CX
  2545.     mov    int25_numsects,ax    ;move to printline
  2546.     mov    ax,[SI].B_ds        ;get buffer segment from DS
  2547.     mov    int25_seg,ax        ;move to printline
  2548.     mov    ax,[SI].B_bx        ;get buffer offset from BX
  2549.     mov    int25_off,ax        ;move to printline
  2550.     mov    dx,offset int25_line    ;now print edited line
  2551.     call    print_edit
  2552.     pop    ax
  2553.     pop    dx
  2554.     ret
  2555. interp_25 endp
  2556.  
  2557.     subttl    Periscope Interrupt Interface
  2558.     page
  2559.  
  2560. ;*****************************************
  2561. ;
  2562. ; This is the interrupt handler use by Periscope to access this code.
  2563. ; It may also be called by SHIFT-PrtSc.
  2564. ;
  2565. ; On entry, AH contains function:
  2566. ;
  2567. ;    1 - 8:   User Breakpoint checks (BU 1 thru BU 8, then GT)
  2568. ;    9 - FFh: User exits (/U 9 thru /U FFh)
  2569. ;    0FFh:    Called by PrtSc
  2570. ;
  2571. ;*****************************************
  2572.  
  2573.     db    "PS"            ;sentinel that Periscope checks for
  2574. periscope proc    far
  2575.  
  2576. ;
  2577. ; First, make very sure that we aren't being re-entered!!! This would
  2578. ; wipe out our stack which is already in use.
  2579. ;
  2580.  
  2581.     cli
  2582.     test    cs:stack_inuse,0ffh
  2583.     jz    periscope2        ;it's ok
  2584.  
  2585. periscope1:
  2586.  
  2587.     mov    al,0ffh            ;tell Periscope "No Break, No Command to be executed"
  2588.     iret                ;busy, call back later
  2589.  
  2590. periscope2:
  2591.  
  2592. ;
  2593. ; If we've been entered via Periscope User Break function (during single-stepping,
  2594. ; with BU 1 thru BU 8 in effect), then exit immediately. Things are slow
  2595. ; enough without us being executed when we have no Breakpoint checking to do.
  2596. ;
  2597.  
  2598.     cmp    ah,9            ;BU 1 thru BU 8?
  2599.     jb    periscope1        ;yes, exit
  2600.  
  2601.  
  2602. ;
  2603. ; On entry to this periscope int, we ought to save everything but AX,
  2604. ; and switch to our own stack. Periscope itself doesn't require this,
  2605. ; but the PrtSc routine assumes it.
  2606. ;
  2607.  
  2608.     mov    cs:stack_inuse,0ffh    ;mark our stack busy
  2609.     mov    cs:save_ss,ss
  2610.     mov    cs:save_sp,sp
  2611.     mov    ss,cs:our_cs
  2612.     mov    sp,offset our_tos
  2613.     push    cs:save_ss        ;save old stack stuff for later
  2614.     push    cs:save_sp
  2615.     push    bx
  2616.     push    cx
  2617.     push    dx
  2618.     push    si
  2619.     push    di
  2620.     push    es
  2621.     push    ds
  2622.     push    bp
  2623.     mov    ds,cs:our_cs        ;set DS to us for assume ds:code
  2624.     sti
  2625.  
  2626. ;
  2627. ; Give user stats about trace buffer size
  2628. ;
  2629.  
  2630.     mov    ax,offset last_byte    ;get # free bytes
  2631.     sub    ax,next_byte
  2632.     mov    word ptr size_freeb,ax
  2633.     mov    dx,offset size_msg
  2634.     call    print_edit
  2635.  
  2636. periscope_menu:
  2637.  
  2638. ;
  2639. ; Now display menu and get his selection, until we are to exit
  2640. ;
  2641.  
  2642.     mov    dx,offset mainmenu
  2643.     call    print_line        ;put up main menu
  2644.     call    feed            ;extra CRLF's for printer
  2645.     call    key            ;get keypress
  2646.     call    do_main            ;process it
  2647.     jc    periscope_menu        ;we are to loop back
  2648.     mov    dx,offset shadows    ;give him exit message
  2649.     call    print_line
  2650.  
  2651.  
  2652. periscope_exit:
  2653.  
  2654. ;
  2655. ; Restore regs and original stack. AX is already set to return result.
  2656. ;
  2657.  
  2658.     cli
  2659.     pop    bp
  2660.     pop    ds
  2661.     pop    es
  2662.     pop    di
  2663.     pop    si
  2664.     pop    dx
  2665.     pop    cx
  2666.     pop    bx
  2667.     pop    cs:save_sp    ;restore original stack
  2668.     pop    cs:save_ss
  2669.     mov    ss,cs:save_ss
  2670.     mov    sp,cs:save_sp
  2671.     mov    cs:stack_inuse,0    ;mark our stack not busy
  2672.     iret
  2673. periscope endp
  2674.  
  2675. mainmenu    db    0dh,0ah
  2676.         db    "(P)rinter (S)creen (E)nable (D)isable (F)CB (T)races (L)ist (C)lear (Q)uit$"
  2677.  
  2678. shadows        db    0dh,0ah
  2679.         db    "Back... to the shadows... AGAIN!"
  2680.         db    0dh,0ah,"$"
  2681.  
  2682. size_msg    label    byte
  2683.         db    0dh,0ah
  2684.         db    "TraceBuf Bytes:"
  2685.         db    Edit_Dec16
  2686.         dw    trace_size
  2687.         db    " Free Bytes:"
  2688.         db    Edit_Dec16
  2689. size_freeb    dw    0
  2690.         db    Edit_End
  2691.  
  2692.     subttl    INT 05 (SHIFT-PrtSc) Handler
  2693.     page
  2694. ;**************************************************
  2695. ;
  2696. ; This is another way (besides Periscope) to talk to the tracer, and
  2697. ; get it to report what it's found. This is not as clean a way as
  2698. ; via Periscope, but it beats nothing if the Periscope board isn't in
  2699. ; the system.
  2700. ;
  2701. ; This routine just calls the Periscope interrupt handler.
  2702. ;
  2703. ;**************************************************
  2704.  
  2705.     if    prt_scr
  2706.  
  2707. PrtSc    proc    far
  2708.     cli
  2709.     push    es
  2710.     push    ax
  2711.     mov    ax,050h            ;set ES to 0050:0000
  2712.     mov    es,ax            ;(the print-screen control byte)
  2713.     cmp    byte ptr es:[0],1    ;are we busy with previous request?
  2714.     jz    PrtSc_exit        ;yes, don't do anything
  2715.     mov    byte ptr es:[0],1    ;no, mark us busy now
  2716.     mov    ah,0ffh            ;call Periscope INT with special arg
  2717.     int    peri_int
  2718.     mov    byte ptr es:[0],0    ;mark us not busy now
  2719.  
  2720. PrtSc_exit:
  2721.     pop    ax
  2722.     pop    es
  2723.     iret
  2724. Prtsc    endp
  2725.  
  2726.     endif
  2727.  
  2728.     subttl  Startup (init) code
  2729.         page
  2730.  
  2731. ;********************************************************
  2732. ;
  2733. ; Startup code, which installs us in memory and sets up interrupts
  2734. ; to be handled.
  2735. ;
  2736. ;********************************************************
  2737.  
  2738. init:
  2739.     mov     our_cs,cs           ;save for handlers' use
  2740.     mov    test_cs,cs        ;start normalized CS for testing
  2741.     mov    ax,offset init        ;include all of resident part in it
  2742.     mov    cl,4
  2743.     shr    ax,cl
  2744.     add    test_cs,ax        ;done normalizing it
  2745.     mov    dx,offset copyright
  2746.     mov    ah,9
  2747.     int    021h
  2748.  
  2749. ;
  2750. ; Get printer base I/O address for use later
  2751. ;
  2752.  
  2753.     mov    ax,040h            ;point to parallel table at 0040:0008
  2754.     mov    es,ax
  2755.     mov    dx,es:[8]        ;get LPT1's base address
  2756.     mov    prt_base,dx        ;save it
  2757.     or    dx,dx            ;is there an LPT1?
  2758.     jnz    init2            ;yes, move on
  2759.     mov    dx,offset no_printer    ;no, give warning message...
  2760.     call    selvideo        ;...after switching to video
  2761.     call    print_line
  2762.  
  2763. init2:
  2764.  
  2765. ;
  2766. ; Init proper I/O mode
  2767. ;
  2768.  
  2769.     if    use_prt
  2770.     call    selprint
  2771.     else
  2772.     call    selvideo
  2773.     endif
  2774.  
  2775. ;
  2776. ; Install Periscope access interrupt # 'peri_int'
  2777. ;
  2778.  
  2779.     mov    al,peri_int        ;INT # being installed
  2780.     mov    ah,025h            ;DOS "Install Int Vector" func
  2781.     mov    dx,offset periscope    ;DS:DX = handler for this INT
  2782.     int    021h
  2783.  
  2784. ;
  2785. ; Install SHIFT-PrtSc interrupt
  2786. ;
  2787.  
  2788.     if    prt_scr
  2789.     mov    al,5            ;INT # being installed
  2790.     mov    ah,025h            ;DOS "Install Int Vector" func
  2791.     mov    dx,offset PrtSc        ;DS:DX = handler for this INT
  2792.     int    021h
  2793.     endif
  2794.     
  2795. ;
  2796. ; Install interrupt vectors for any active ICT's
  2797. ;
  2798.  
  2799.     mov    cx,8            ;number of ICT's
  2800.     xor    si,si            ;Start with ICT # 0
  2801.  
  2802. init5:
  2803.     mov    bx,ict_index[si]    ;get pointer to an ICT
  2804.     mov    al,[bx].ICT_flags    ;get flags to AL
  2805.     test    al,F_ACTIVE        ;is this ICT active?
  2806.     jz    init10            ;no, move on to next one
  2807.  
  2808. ; ------- Validate type of interrupt exit
  2809.  
  2810.     and    al,F_RET+F_RET2+F_IRET
  2811.     cmp    al,F_RET
  2812.     jz    init6            ;this one's legal
  2813.     cmp    al,F_RET2
  2814.     jz    init6            ;this one's legal
  2815.     cmp    al,F_IRET
  2816.     jz    init6            ;this one's legal
  2817.     mov    dx,offset bad_exit    ;bad field, give error message
  2818.  
  2819. init5b:
  2820.  
  2821. ;
  2822. ; Print error message at DS:DX and mark ICT de-activated
  2823. ;
  2824.  
  2825.     push    dx            ;save error message text
  2826.     mov    ax,si            ;get ICT # for error message
  2827.     shr    ax,1
  2828.     and    al,7            ;(just in case)
  2829.     or    al,'0'            ;make into ASCII digit
  2830.     mov    err_ict,al        ;move into error header
  2831.     mov    dx,offset err_msg    ;print error header first
  2832.     call    print_line
  2833.     pop    dx            ;recover error message itself
  2834.     call    print_line        ;display it
  2835.     xor    [bx].ICT_flags,F_ACTIVE    ;de-activate this ICT
  2836.     jmp    short init10        ;goto next ICT
  2837.  
  2838. init6:
  2839.     mov    al,[bx].ICT_intnum    ;get int number to AL
  2840.  
  2841.     if    prt_scr
  2842.     cmp    al,5            ;trying to trace INT 5?
  2843.     jnz    init6b            ;no, it's all right
  2844.     mov    dx,offset two_prtscrs    ;yes, give error message
  2845.     jmp    init5b
  2846.  
  2847. init6b:
  2848.     endif
  2849.  
  2850.     mov    ah,035h            ;get current vector for this INT
  2851.     push    bx            ;(save ICT pointer!!!)
  2852.     int    021h
  2853.     mov    dx,bx            ;put vector's offset somewhere safe
  2854.     pop    bx            ;(restore ICT pointer!!!)
  2855.  
  2856.     mov    word ptr [bx].ICT_orig_hndlr,dx
  2857.     mov    word ptr [bx].ICT_orig_hndlr+2,es
  2858.  
  2859.     mov    dx,hndlr_index[si]    ;DS:DX = new vector for this INT
  2860.     mov    ah,025h            ;tell DOS to install it
  2861.     int    021h            ;(intnum still in AL)
  2862.  
  2863. init10:
  2864.     add    si,2            ;up to next ICT
  2865.     loop    init5            ;till done all ICT's
  2866.  
  2867. ;
  2868. ; List final ICT's
  2869. ;
  2870.  
  2871.     mov    dx,offset final_msg
  2872.     call    print_line
  2873.     call    disp_active        ;display all active ICT's
  2874.     call    crlf
  2875.  
  2876. ;
  2877. ; Terminate and stay resident
  2878. ;
  2879.  
  2880.     mov    dx,offset intro_msg    ;give him intro message
  2881.     call    print_line
  2882.     mov    al,peri_int
  2883.     call    print_hex
  2884.     call    crlf
  2885.     call    feed            ;extra CRLF's for printer
  2886.     mov     dx,offset init
  2887.     int     027h
  2888.  
  2889. ;********************************************************
  2890. ;
  2891. ; Startup messages (lost once we're resident)
  2892. ;
  2893. ;********************************************************
  2894.  
  2895. copyright    db    0dh,0ah
  2896.         db    "TRACE - Interrupt Tracer version 1.2 2/26/86"
  2897.         db    0dh,0ah
  2898.         db    0dh,0ah
  2899.         db    "Written by Joan Riff for:"
  2900.         db    0dh,0ah
  2901.         db    "Computerwise Consulting Services P.O. Box 813, McLean VA 22101  (703) 280-2809"
  2902.         db    0dh,0ah
  2903.         db    0dh,0ah
  2904.         db    "Placed in the public domain. There ain't one person in a thousand qualified to"
  2905.         db    0dh,0ah
  2906.         db    "understand or use this thing, so why charge for it?"
  2907.         db    0dh,0ah,"$"
  2908.  
  2909.  
  2910. intro_msg    db    0dh,0ah
  2911.         db    0dh,0ah
  2912.         db    "Trace is now resident."
  2913.         db    0dh,0ah
  2914.         db    "Use '/U 9' Periscope command"
  2915.         if    prt_scr
  2916.         db    " (or SHIFT-PrtSc)"
  2917.         endif
  2918.         db    " for access."
  2919.         db    0dh,0ah
  2920.         db    "When you run Periscope, include command-line arg /I:$"
  2921. bad_exit    db    "has a bad Exit field. ICT deactivated.$"
  2922. two_prtscrs    db    "overlays SHIFT-PrtSc. ICT deactivated.$"
  2923. no_printer    db    0dh,0ah,"*** Warning: LPT1 not available$"
  2924. err_msg        db    0dh,0ah,"*** ICT #"
  2925. err_ict        db    "0 $"
  2926. final_msg    db    0dh,0ah
  2927.         db    0dh,0ah,"Final ICT's:",0dh,0ah,"$"
  2928.  
  2929. code    ends
  2930.     end     start
  2931.