home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / DOS_HELP / STPDOS11.ZIP / STEPDOS.ASM < prev    next >
Encoding:
Assembly Source File  |  1987-11-13  |  73.5 KB  |  2,725 lines

  1.  
  2.         PAGE    60,132
  3.         TITLE   'Step DOS Calls'
  4.         NAME    STEPDOS
  5. ;
  6. ;       ***********************************************************
  7. ;       *                                                         *
  8. ;       *                   S  T  E  P  D  O  S                   *
  9. ;       *                                                         *
  10. ;       *                        Rev 1.1                          *
  11. ;       *                                                         *
  12. ;       *                      Nov 13, 1987                       *
  13. ;       *                                                         *
  14. ;       *               Mike Parker - CIS 70270,161               *
  15. ;       *                                                         *
  16. ;       *  This program allows you to step through the execution  *
  17. ;       *  of another program by intercepting all calls to DOS    *
  18. ;       *  INT 21H. A window will pop up displaying all register  *
  19. ;       *  values and a short description of the DOS function     *
  20. ;       *  being called. Program execution will continue when     *
  21. ;       *  you press a key. You can optionally break again after  *
  22. ;       *  the DOS function completes so you can see the result   *
  23. ;       *  code in the AX register along with important flags.    *
  24. ;       *                                                         *
  25. ;       ***********************************************************
  26. ;
  27. ; Changes for version 1.1:
  28. ;     Made STEPDOS a COM file instead of EXE.
  29. ;     Implement arrow keys to reposition window.
  30. ;     Only keep as much memory as needed for STEPDOS instead of 64K.
  31. ;     Doesn't add <NULL> to command line string passed to target program.
  32. ;     Changed stack switching in 'New21'.
  33. ;     Recognize DOS switch character ('/') in command line.
  34. ;     Use 'FIND FIRST' function 4eh when searching for target program
  35. ;        instead of trying to do 'OPEN'.
  36. ;     Support monochrome cards.
  37. ;     Display window on screen even if target program changes video page.
  38. ;     Change 'Disp_09' code to stop display at '$' terminator.
  39. ;     Rev 1.0 did not return the IF bit in the flag register to the user's
  40. ;        original state.
  41. ;
  42. ;
  43. ; To run, type STEPDOS <filename>
  44. ;  where <filename> is the full pathname of an EXE or COM file.
  45. ;
  46. ;
  47. TESTING    EQU    0
  48.  
  49. BG         EQU    10H               ; BG sets background color (10h = BLUE)
  50.  
  51. BLACK      EQU    00H + BG
  52. BLUE       EQU    01H + BG
  53. GREEN      EQU    02H + BG
  54. CYAN       EQU    03H + BG
  55. RED        EQU    04H + BG
  56. MAGENTA    EQU    05H + BG
  57. BROWN      EQU    06H + BG
  58. WHITE      EQU    07H + BG
  59. GRAY       EQU    08H + BG
  60. LTBLUE     EQU    09H + BG
  61. LTGREEN    EQU    0AH + BG
  62. LTCYAN     EQU    0BH + BG
  63. LTRED      EQU    0CH + BG
  64. LTMAGENTA  EQU    0DH + BG
  65. YELLOW     EQU    0EH + BG
  66. HIWHITE    EQU    0FH + BG
  67. ;
  68. CR         EQU    13
  69. LF         EQU    10
  70. BIGR       EQU    1352H             ; 'R' key
  71. SMALLR     EQU    1372H             ; 'r'
  72. BIGS       EQU    1F53H             ; 'S' key
  73. SMALLS     EQU    1F73H             ; 's'
  74. ESCAPE     EQU    011BH
  75. HOME       EQU    4700H
  76. UPARROW    EQU    4800H
  77. PGUP       EQU    4900H
  78. LEFTARROW  EQU    4B00H
  79. RIGHTARROW EQU    4D00H
  80. XEND       EQU    4F00H
  81. DOWNARROW  EQU    5000H
  82. PGDN       EQU    5100H
  83. ;
  84. BLANK      EQU    32
  85. BRDROW     EQU    205
  86. BRDCOL     EQU    186
  87. ULC        EQU    201
  88. URC        EQU    187
  89. LLC        EQU    200
  90. LRC        EQU    188
  91. ;
  92. REGBX      EQU    00                ; offsets on saved register stack
  93. REGCX      EQU    02
  94. REGDX      EQU    04
  95. REGDI      EQU    06
  96. REGSI      EQU    08
  97. REGBP      EQU    10
  98. REGES      EQU    12
  99. ;
  100. IF TESTING
  101. INT21OFF   EQU    0e0h*4            ; during testing an unused INT is used
  102. ELSE
  103. INT21OFF   EQU    21h*4
  104. ENDIF
  105.  
  106. Code    SEGMENT PUBLIC PARA 'CODE'
  107.  
  108.         ASSUME  CS:Code, DS:Code
  109.  
  110.         ORG     100h
  111. Main:                               ; starting point
  112.         cli
  113.         cld
  114.         mov     AX,CS
  115.         mov     SS,AX
  116.         mov     SP,OFFSET Pstack
  117.         mov     BX,DS               ; get difference between segments
  118.         sub     AX,BX               ;  so .EXE file can run during testing
  119. ;
  120.         mov     BX,OFFSET PRSIZE    ; program size in bytes
  121.         mov     CL,4
  122.         shr     BX,CL               ; convert it to paragraphs
  123.         add     BX,AX               ; add difference between segments
  124.         inc     BX                  ; make it next multiple of 16 bytes
  125.         mov     AH,4ah              ; modify memory block size
  126.         int     21h
  127.         sti
  128. ;
  129. ; Copy command line from PSP to local area
  130. ;
  131.         mov     AX,CS
  132.         mov     ES,AX               ; change ES to be local area
  133. ;
  134.         mov     SI,0080h
  135.         mov     CL,[SI]             ; get command line character count
  136.         or      CL,CL               ; zero char count in cmd line?
  137.         jnz     notzcl
  138.         mov     AX,CS               ; yes, display 'Usage' message
  139.         mov     DS,AX               ;  and exit
  140.         mov     DX,OFFSET Umsg
  141.         mov     AH,9
  142.         int     21h
  143.         jmp     exit
  144. notzcl:
  145.         xor     CH,CH
  146.         inc     SI
  147.         mov     DI,OFFSET PSPstr
  148. rep     movsb                       ; copy command line
  149.         xor     AL,AL
  150.         stosb                       ; <NULL> terminator at end
  151. ;
  152.         mov     BX,002ch
  153.         mov     BX,[BX]             ; get segment addr of environment from PSP
  154. ;
  155.         mov     AX,CS
  156.         mov     DS,AX               ; change DS to local area
  157.         mov     SegEnv,BX           ; save in EXEC control block
  158. ;
  159.         mov     DX,OFFSET INITmsg
  160.         mov     AH,9
  161.         int     21h
  162. ;
  163. ; Check equipment list to see if we have graphics or monochrome card
  164. ;
  165.         int     11h
  166.         and     AX,0030h            ; save video mode
  167.         mov     BX,0b000h
  168.         cmp     AX,0030h            ; monochrome?
  169.         jz      setcrd
  170.         mov     BX,0b800h           ; no, graphics card
  171. setcrd:
  172.         mov     Scrseg,BX           ; save base segment
  173. ;
  174. ; Calculate starting address on screen for window
  175. ;
  176.         mov     BX,OFFSET W1        ; window parameters
  177.         call    Window_Parms        ; calc start addr of window, wid and ht
  178. ;
  179. ; Do DOS call to allocate memory
  180. ;
  181.         mov     CL,4
  182.         shr     AX,CL               ; divide by 16 to get # paragraphs
  183.         inc     AX                  ; handle any remainder
  184.         mov     BX,AX
  185.         mov     AH,48h              ; 'allocate memory' DOS call
  186.         int     21h
  187.         mov     Winseg,AX           ; save returned segment
  188.         jnc     cpynam
  189.         mov     DX,OFFSET Memerr    ; ERROR - display string
  190.         mov     AH,9
  191.         int     21h
  192.         jmp     exit                ;  and terminate
  193. ;
  194. ; Copy target program name
  195. ;
  196. cpynam:
  197.         mov     AX,3700h            ; get DOS switch character
  198.         int     21h
  199.         mov     Sw_Char,DL
  200. ;
  201.         mov     SI,OFFSET PSPstr + 1
  202.         mov     DI,OFFSET Filename
  203.         xor     CX,CX               ; zero char count
  204. fnlp:
  205.         mov     AL,[SI]
  206.         cmp     AL,' '              ; look for <SP>
  207.         jz      fndn
  208.         cmp     AL,00               ;  or <NULL> terminator
  209.         jz      fndn
  210.         cmp     AL,Sw_Char          ;  or switch character ('/')
  211.         jz      fndn
  212.         movsb
  213.         inc     CX                  ; count number of filename char's
  214.         jmp     fnlp
  215. fndn:
  216.         or      CX,CX
  217.         jnz     gotfn
  218.         mov     DX,OFFSET Findmsg   ; error if zero filename length
  219.         mov     AH,9
  220.         int     21h
  221.         jmp     freemem
  222. gotfn:
  223.         xor     AL,AL
  224.         stosb
  225.         mov     FNsize,CX
  226. ;
  227. ; Copy command line string
  228. ; SI -> first parameter after filename
  229. ;
  230.         mov     DI,OFFSET CLstr + 1
  231.         xor     CX,CX               ; zero char count
  232. cllp:
  233.         cmp     BYTE PTR [SI],00    ; look for <NULL> terminator
  234.         jz      dncl
  235.         movsb
  236.         inc     CX                  ; count number of cmd line char's
  237.         jmp     cllp
  238. dncl:
  239.         mov     AL,CR               ; put <CR> past end
  240.         stosb
  241.         mov     CLstr,CL            ; store cmd line count
  242. ;
  243. ; Build EXEC control block
  244. ;
  245.         mov     SegCmd,OFFSET CLstr
  246.         mov     SegCmd+2,DS
  247.         mov     FCBptr1,OFFSET FCB1
  248.         mov     FCBptr1+2,DS
  249.         mov     FCBptr2,OFFSET FCB2
  250.         mov     FCBptr2+2,DS
  251. ;
  252. ; Parse first parameter
  253. ;
  254.         mov     SI,OFFSET CLstr + 1
  255.         mov     DI,OFFSET FCB1
  256.         mov     AL,01               ; scan past separators
  257.         mov     AH,29h
  258.         int     21h
  259. ;
  260. ; Parse second parameter
  261. ;
  262.         mov     DI,OFFSET FCB2
  263.         mov     AL,01               ; scan past separators
  264.         mov     AH,29h
  265.         int     21h
  266. ;
  267. ; Try to find target file
  268. ;
  269.         call    Find_File
  270.         jnc     redirect            ; jump if found it
  271. ;
  272. ; File not found, display msg and exit
  273. ;
  274.         mov     DI,OFFSET Filename
  275.         xor     AL,AL               ; find terminating <NULL>
  276.         mov     CX,0ffffh           ; there must be one in there somewhere
  277. repne   scasb
  278.         dec     DI
  279.         mov     AL,27h              ; closing quote
  280.         stosb
  281.         mov     AL,'$'              ; put string terminator for DOS function 09
  282.         stosb
  283. ;
  284.         mov     DX,OFFSET Findmsg   ; not found message
  285.         mov     AH,9
  286.         int     21h
  287. ;
  288.         mov     DX,OFFSET Filename  ; show filename we were looking for
  289.         mov     AH,9
  290.         int     21h
  291.         jmp     freemem
  292. ;
  293. ; Redirect INT 21h
  294. ;
  295. redirect:
  296.         push    ES
  297.         cli
  298.         mov     AX,0
  299.         mov     ES,AX
  300.         mov     AX,OFFSET New21
  301.         xchg    AX,ES:[INT21OFF]
  302.         mov     Save21,AX
  303.         mov     AX,CS
  304.         xchg    AX,ES:[INT21OFF+2]
  305.         mov     Save21+2,AX
  306.         sti
  307.         pop     ES
  308. ;
  309. ; Execute target program
  310. ;
  311.         mov     SP,OFFSET Tstack
  312.  
  313. IF TESTING
  314.         include test.asm
  315.         clc                         ; no error
  316. ELSE
  317.         mov     DX,OFFSET Filename
  318.         mov     BX,OFFSET Param_Block
  319.         mov     AH,4bh
  320.         mov     AL,0
  321.         int     21h
  322. ENDIF
  323. ;
  324.         cli
  325.         mov     AX,CS               ; restore segment registers
  326.         mov     DS,AX
  327.         mov     ES,AX
  328.         mov     SS,AX
  329.         mov     SP,OFFSET Pstack
  330.         jnc     execdn
  331. ;
  332. ; Failed to execute target program. Display message and quit
  333. ;
  334.         mov     DX,OFFSET Execmsg
  335.         mov     AH,9
  336.         int     21h
  337. ;
  338. ; Restore INT 21h vector
  339. ;
  340. execdn:
  341.         cli
  342.         mov     AX,0
  343.         mov     ES,AX
  344.         mov     AX,Save21
  345.         mov     ES:[INT21OFF],AX
  346.         mov     AX,Save21+2
  347.         mov     ES:[INT21OFF+2],AX
  348.         sti
  349. ;
  350. ; Free allocated memory from window save area
  351. ;
  352. freemem:
  353.         mov     ES,Winseg
  354.         mov     AH,49h
  355.         int     21h
  356. exit:
  357.         mov     AH,4ch              ; terminate process
  358.         mov     AL,00
  359.         int     21h                 ; won't return
  360.  
  361. ;
  362. ;
  363. ; Search for file. If no extention specified try both .COM and .EXE
  364. ;
  365. Find_File:
  366.         mov     DI,OFFSET Filename
  367.         mov     CX,FNsize           ; get program filename size
  368.         mov     AL,'.'
  369. repne   scasb                       ; check for '.' in target program filename
  370.         jz      fndext              ; jump if found extention
  371. ;
  372. ; No extention found, try appending '.COM'
  373. ;
  374.         mov     SI,OFFSET COMstr
  375.         mov     DI,OFFSET Filename
  376.         add     DI,FNsize
  377.         mov     CX,4
  378. rep     movsb
  379. ;
  380. ; See if the target program exists before we change the Int 21h vector
  381. ; and EXEC it.
  382. ;
  383.         mov     AH,4eh              ; find first filename
  384.         mov     CX,00               ; attribute code
  385.         mov     DX,OFFSET Filename
  386.         int     21h
  387.         jnc     fret                ; jump if file found
  388. ;
  389. ; FIND with '.COM' extention failed, try appending '.EXE'
  390. ;
  391.         mov     SI,OFFSET EXEstr
  392.         mov     DI,OFFSET Filename
  393.         add     DI,FNsize
  394.         mov     CX,4
  395. rep     movsb
  396. ;
  397. ; Try to find the '.EXE' version of the file
  398. ;
  399. fndext:
  400.         mov     AH,4eh
  401.         mov     CX,00               ; attribute code
  402.         mov     DX,OFFSET Filename
  403.         int     21h
  404. fret:
  405.         ret                         ; carry flag has error status
  406.  
  407. ;
  408. ; INT 21h will be redirected to here
  409. ;
  410. New21:
  411.         push    AX                  ; use USERS'S stack for first 3 words
  412.         push    DS
  413.         pushf                       ; push them but we don't need them here
  414. ;
  415.         cli
  416.         mov     AX,CS               ; now switch to internal stack
  417.         mov     DS,AX
  418.         mov     SSsave,SS
  419.         mov     SPsave,SP
  420.         mov     SS,AX
  421.         mov     SP,OFFSET Pstack
  422.         sti
  423. ;
  424.         push    ES
  425.         push    BP
  426.         push    SI
  427.         push    DI
  428.         push    DX
  429.         push    CX
  430.         push    BX
  431.         mov     BP,SP               ; save base pointer to display reg's
  432.         mov     ES,AX
  433.         mov     AL,Run_Flg
  434.         test    AL,0ffh             ; should we stop and display?
  435.         jz      norun               ; no, restore registers and leave
  436. ;
  437. ; Recover registers on USER'S stack
  438. ;
  439.         push    ES
  440.         les     BX,Ssave
  441.         mov     AX,ES:[BX+2]        ; get DS
  442.         mov     DSsave,AX
  443.         mov     AX,ES:[BX+4]        ; get AX
  444.         mov     AXsave,AX
  445.         mov     AX,ES:[BX+6]        ; get IP
  446.         mov     IPsave,AX
  447.         mov     AX,ES:[BX+8]        ; get CS
  448.         mov     CSsave,AX
  449.         mov     AX,ES:[BX+10]       ; get FLAGS on entry
  450.         mov     FLsave,AX
  451.         pop     ES
  452. ;
  453.         cld                         ; clear direction flag for string operations
  454.         mov     AL,Skip_Flg
  455.         test    AL,0ffh             ; skip certain functions?
  456.         jz      noskip              ; no, continue
  457.         mov     AX,AXsave           ; get USER's AX register with function code
  458.         cmp     AH,Skip_Typ         ; compare upper half to type to skip
  459.         jz      norun               ; don't want to break on this one again
  460.         mov     AL,00               ; skip flag was set but this is new
  461.         mov     Skip_Flg,AL         ;  function, so break from now on
  462. noskip:
  463.         call    Open_Window
  464.         call    Show_Regs
  465.         call    Show_Help
  466.         call    Disp_Text           ; Display description string of DOS function
  467. ;
  468.         call    Get_Key             ; wait for a key pressed
  469.         call    Disp_Key            ; dispatch to key handler
  470.         jc      noskip              ; if carry set, need to redisplay window
  471.         call    Close_Window
  472. norun:
  473.         pop     BX
  474.         pop     CX
  475.         pop     DX
  476.         pop     DI
  477.         pop     SI
  478.         pop     BP
  479.         pop     ES
  480.         cli
  481.         mov     SS,SSsave           ; switch back to user's stack
  482.         mov     SP,SPsave
  483. ;
  484.         mov     AX,FLsave           ; get original user's flags before INT 21h
  485.         push    AX                  ; sneak them into flag register
  486.         popf
  487. ;
  488.         pop     AX                  ; dummy pop to get flags off stack
  489.         pop     DS                  ; restore registers left on user's stack
  490.         pop     AX                  ; now get real AX
  491.  
  492. IFE TESTING
  493.         pushf
  494.         cli                         ; give interrupt code IF = 0 like normal
  495.         call    CS:[DWORD PTR Save21]
  496. ENDIF
  497.  
  498.         push    AX                  ; use USERS'S stack for first 3 words
  499.         push    DS
  500.         pushf                       ; they will get used this time
  501. ;
  502.         cli
  503.         mov     AX,CS               ; now switch to internal stack
  504.         mov     DS,AX
  505.         mov     SSsave,SS
  506.         mov     SPsave,SP
  507.         mov     SS,AX
  508.         mov     SP,OFFSET Pstack
  509.         sti
  510. ;
  511.         push    ES
  512.         push    BP
  513.         push    SI
  514.         push    DI
  515.         push    DX
  516.         push    CX
  517.         push    BX
  518.         mov     BP,SP               ; save base pointer to display reg's
  519.         mov     ES,AX
  520.         cld                         ; clear direction flag for string operations
  521. ;
  522. ; Recover registers on USER'S stack
  523. ;
  524.         push    ES
  525.         les     BX,Ssave
  526.         mov     AX,ES:[BX+0]        ; get FLAGS on exit
  527.         mov     FLsave,AX
  528.         mov     AX,ES:[BX+2]        ; get DS
  529.         mov     DSsave,AX
  530.         mov     AX,ES:[BX+4]        ; get AX
  531.         mov     AXsave,AX
  532.         mov     AX,ES:[BX+6]        ; get IP
  533.         mov     IPsave,AX
  534.         mov     AX,ES:[BX+8]        ; get CS
  535.         mov     CSsave,AX
  536.         pop     ES
  537. ;
  538.         xor     AL,AL
  539.         xchg    AL,Ret_Flg          ; read value and clear flag for next time
  540.         test    AL,0ffh             ; is flag set to display return value?
  541.         jz      nostop
  542. ;
  543.         call    Open_Window
  544.         call    Show_Regs
  545.         call    Disp_Ret            ; display return code in AX and flags
  546.         call    Get_Key             ; wait for a key pressed
  547.         call    Close_Window
  548. nostop:
  549.         pop     BX
  550.         pop     CX
  551.         pop     DX
  552.         pop     DI
  553.         pop     SI
  554.         pop     BP
  555.         pop     ES
  556.         cli
  557.         mov     SS,SSsave
  558.         mov     SP,SPsave
  559.         popf
  560.         pop     DS
  561.         pop     AX
  562.         retf    2
  563.  
  564. ;
  565. ; Display return code in AX, carry and zero flags
  566. ;
  567. Disp_Ret:
  568.         mov     DX,OFFSET RCStr
  569.         mov     DI,14
  570.         mov     AX,AXsave
  571.         call    OutWord
  572. ;
  573.         mov     DX,OFFSET CFStr
  574.         mov     DI,13
  575.         add     DI,DX
  576.         mov     AL,'0'
  577.         test    FLsave,0001         ; carry flag is least significant bit
  578.         jz      dcy
  579.         inc     AL                  ; carry was set so change to '1'
  580. dcy:
  581.         mov     [DI],AL             ; store it in string
  582.         add     CX,0015h            ; move cursor position
  583.         mov     BX,OFFSET W1
  584.         mov     AH,HIWHITE
  585.         call    WPrint
  586. ;
  587.         mov     DX,OFFSET ZFStr
  588.         mov     DI,12
  589.         add     DI,DX
  590.         mov     AL,'0'
  591.         test    FLsave,0040h        ; test zero flag
  592.         jz      dzf
  593.         inc     AL                  ; zero was set so change to '1'
  594. dzf:
  595.         mov     [DI],AL             ; store it in string
  596.         add     CX,0010h            ; move cursor position
  597.         mov     BX,OFFSET W1
  598.         mov     AH,HIWHITE
  599.         call    WPrint
  600. ;
  601.         mov     CX,0816h            ; display some help
  602.         mov     DX,OFFSET HlpStr5
  603.         mov     AH,YELLOW
  604.         call    WPrint
  605.         ret
  606.  
  607. ;
  608. ; Display register names in window
  609. ;
  610. Show_Regs:
  611.         mov     BX,OFFSET W1        ; window
  612.         mov     CX,0001h            ; cursor position - row, col
  613.         mov     DX,OFFSET RegStr1   ; message address
  614.         mov     AH,YELLOW           ; attribute
  615.         call    WPrint
  616. ;
  617.         add     CX,0100h            ; go down one row
  618.         mov     DX,OFFSET RegStr2
  619.         mov     AH,WHITE
  620.         call    WPrint
  621. ;
  622. ; Display register values
  623. ;
  624.         add     CX,0100h            ; down a row
  625.         mov     AX,AXsave           ; get user's AX
  626.         call    Whexwd              ; display hex word
  627. ;
  628.         push    BP                  ; save base pointer for string display
  629.         mov     DX,6                ; number of registers to show this loop
  630. disreg:
  631.         add     CX,0005h            ; move to next register field
  632.         mov     AX,[BP]
  633.         call    Whexwd              ; display hex word
  634.         add     BP,2
  635.         dec     DX
  636.         jnz     disreg
  637. ;
  638.         add     CX,0005h            ; move to next register field
  639.         mov     AX,SPsave           ; display SP
  640.         add     AX,6                ; add for 3 pushes we did
  641.         call    Whexwd
  642. ;
  643.         add     CX,0005h            ; move to next register field
  644.         mov     AX,DSsave           ; display DS
  645.         call    Whexwd
  646. ;
  647.         add     CX,0005h            ; display ES
  648.         mov     AX,[BP]
  649.         call    Whexwd
  650. ;
  651.         add     CX,0005h
  652.         mov     AX,SSsave           ; display SS
  653.         call    Whexwd
  654. ;
  655.         add     CX,0005h
  656.         mov     AX,CSsave           ; display CS
  657.         call    Whexwd
  658. ;
  659.         add     CX,0005h
  660.         mov     AX,IPsave           ; display IP
  661.         call    Whexwd
  662. ;
  663.         add     CX,0005h
  664.         mov     AX,FLsave           ; display FLAGS
  665.         call    Whexwd
  666.         pop     BP                  ; restore base pointer so display routines
  667.                                     ;  can use it
  668.         ret
  669.  
  670. ;
  671. ; Display HELP in Window
  672. ;
  673. Show_Help:
  674.         mov     CX,0802h            ; cursor position - row, col
  675.         mov     AH,LTRED            ; attribute for char
  676.         mov     AL,'S'
  677.         call    WChar               ; write one character with attribute
  678. ;
  679.         add     CX,0001h            ; add 1 to column number
  680.         mov     DX,OFFSET HlpStr1   ; message address
  681.         mov     AH,WHITE
  682.         call    WPrint
  683. ;
  684.         add     CX,0012h            ; move column number
  685.         mov     AH,LTRED            ; attribute for char
  686.         mov     AL,'R'
  687.         call    WChar               ; write one character with attribute
  688. ;
  689.         add     CX,0001h            ; move column number
  690.         mov     DX,OFFSET HlpStr2
  691.         mov     AH,WHITE
  692.         call    WPrint
  693. ;
  694.         add     CX,000ch
  695.         mov     AH,LTRED
  696.         mov     AL,'E'
  697.         call    WChar
  698. ;
  699.         add     CX,0001h
  700.         mov     AH,LTRED
  701.         mov     AL,'S'
  702.         call    WChar
  703. ;
  704.         add     CX,0001h
  705.         mov     AH,LTRED
  706.         mov     AL,'C'
  707.         call    WChar
  708. ;
  709.         add     CX,0001h
  710.         mov     DX,OFFSET HlpStr3
  711.         mov     AH,WHITE
  712.         call    WPrint
  713. ;
  714.         add     CX,000dh
  715.         mov     AH,LTRED
  716.         mov     AL,18h              ; up arrow
  717.         call    WChar
  718. ;
  719.         add     CX,0001h
  720.         mov     AH,LTRED
  721.         mov     AL,19h              ; down arrow
  722.         call    WChar
  723. ;
  724.         add     CX,0001h
  725.         mov     AH,LTRED
  726.         mov     AL,1bh              ; left arrow
  727.         call    WChar
  728. ;
  729.         add     CX,0001h
  730.         mov     AH,LTRED
  731.         mov     AL,1ah              ; right arrow
  732.         call    WChar
  733. ;
  734.         add     CX,0001h
  735.         mov     DX,OFFSET HlpStr4
  736.         mov     AH,WHITE
  737.         call    WPrint
  738.         ret
  739.  
  740. ;
  741. ; HextoDec converts a word in AX to an ASCII string
  742. ; Entry:
  743. ;      AX = word to convert
  744. ; Exit:
  745. ;      SI = Pointer to last two character of ASCII string in 'Astr'
  746. ;
  747. HextoDec:
  748.          push   AX
  749.          push   CX
  750.          push   DX
  751.          push   DI
  752. ;
  753.          mov    DI,OFFSET Astr
  754.          mov    CX,10000
  755.          xor    DX,DX
  756.          div    CX                  ; num / 10000
  757.          add    AL,'0'
  758.          stosb
  759.          mov    AX,DX
  760.          mov    CX,1000
  761.          xor    DX,DX
  762.          div    CX                  ; num / 1000
  763.          add    AL,'0'
  764.          stosb
  765.          mov    AX,DX
  766.          mov    CX,100
  767.          xor    DX,DX
  768.          div    CX                  ; num / 100
  769.          add    AL,'0'
  770.          stosb
  771.          mov    AX,DX
  772.          mov    CX,10
  773.          xor    DX,DX
  774.          div    CX                  ; num / 10
  775.          add    AL,'0'
  776.          stosb
  777.          mov    AX,DX
  778.          add    AL,'0'
  779.          stosb
  780.          xor    AL,AL               ; <NULL> terminator in string
  781.          stosb
  782.          sub    DI,3                ; back up pointer
  783.          mov    SI,DI
  784. ;
  785.          pop    DI
  786.          pop    DX
  787.          pop    CX
  788.          pop    AX
  789.          ret
  790.  
  791. ;
  792. ; Display the text description of the current DOS function code
  793. ;
  794. Disp_Text:
  795.         mov     AX,AXsave           ; get user's function code
  796.         cmp     AH,63h              ; is it in range?
  797.         jnb     not_fnd             ; jump if no
  798.         mov     DI,OFFSET FCtbl
  799.         mov     CX,LENFC / 6        ; number of entries
  800. cmpdt:
  801.         cmp     AH,[DI+1]           ; is this the right function?
  802.         jz      dtexec
  803.         add     DI,6                ; no, point to next
  804.         loop    cmpdt
  805. not_fnd:
  806.         mov     DX,OFFSET STRUN
  807.         call    Disp_Str
  808.         ret
  809.  
  810. dtexec:
  811.         mov     DX,[DI+2]           ; get pointer to string
  812.         call    [WORD PTR DI+4]     ; go to display routine
  813.         ret
  814.  
  815. ;
  816. ; Display string of DOS function code description
  817. ;
  818. ; Entry:
  819. ;       DX = pointer to string
  820. ;
  821. Disp_Str:
  822.         mov     CX,0501h
  823.         mov     BX,OFFSET W1
  824.         mov     AH,HIWHITE
  825.         call    WPrint
  826.         ret
  827.  
  828. ;
  829. ; Only one string must be inserted.
  830. ; It is pointed to by user's DS:DX.
  831. ; Entry:
  832. ;      DX = text string containing description of function call
  833. ;      DI = offset within local string (DX) to put user's (DS:DX)
  834. ;      CX = max length before you will hit right side of Window
  835. ;
  836. One_String:
  837.         add     DI,DX
  838.         push    DS
  839.         mov     DS,DSsave
  840.         mov     SI,[BP+REGDX]       ; get USER's DS:DX value
  841. rep     movsb                       ; copy user's memory to text string
  842.         pop     DS
  843.         call    Disp_Str
  844.         ret
  845.  
  846. ;
  847. ; Convert users's DS and DX to ASCII, imbed them in target string
  848. ; Entry:
  849. ;      DX = pointer to string
  850. ;      DI = offset where to put converted DS:DX
  851. ;
  852. OutDSDX:
  853.         add     DI,DX
  854.         mov     AX,DSsave           ; get user's DS
  855.         call    Shexwrd
  856.         inc     DI                  ; skip past ':'
  857.         mov     AX,[BP+REGDX]       ; get user's DX
  858.         call    Shexwrd
  859.         call    Disp_Str
  860.         ret
  861.  
  862. ;
  863. ; Convert word in AX to ASCII, imbed it in target string
  864. ; Entry:
  865. ;      AX = word to convert
  866. ;      DX = pointer to string
  867. ;      DI = offset where to put converted AX
  868. ;
  869. OutWord:
  870.         add     DI,DX
  871.         call    Shexwrd
  872.         call    Disp_Str
  873.         ret
  874.  
  875. ;
  876. ; Convert 'AL' to ASCII and imbed it in target string
  877. ; Entry:
  878. ;      DX = target string
  879. ;      DI = offset to put converted 'AL'
  880. ;      AL = value to convert
  881. ;
  882. OutByte:
  883.         add     DI,DX
  884.         call    Shexbyt
  885.         call    Disp_Str
  886.         ret
  887.  
  888. ;
  889. ; Routines to build string for display - some values need to be filled in
  890. ;
  891. ; Entry:
  892. ;       DX = pointer to string
  893. ;
  894. Disp_02:
  895. Disp_04:
  896. Disp_05:
  897.         mov     DI,DX
  898.         add     DI,22               ; offset this many into string
  899.         mov     AX,[BP+REGDX]       ; DL register has char to output
  900.         call    Shexbyt             ; convert it to ASCII
  901.         mov     [DI+8],AL           ; show hex byte
  902.         call    Disp_Str
  903.         ret
  904.  
  905. ;
  906. ; Direct Keyboard/Display I/O
  907. ;
  908. Disp_06:
  909.         call    Disp_Str
  910.         mov     AX,[BP+REGDX]       ; DL register has I/O type
  911.         mov     DX,OFFSET STR06I
  912.         cmp     AL,0ffh             ; input character?
  913.         jz      d06io
  914.         mov     DX,OFFSET STR02     ; no, output character in 'DL'
  915.         mov     DI,DX
  916.         add     DI,22               ; offset this many into string
  917.         call    Shexbyt             ; convert it to ASCII
  918.         mov     [DI+8],AL           ; show hex byte
  919. d06io:
  920.         add     CX,0015h
  921.         mov     BX,OFFSET W1
  922.         mov     AH,HIWHITE
  923.         call    WPrint
  924.         ret
  925.  
  926. ;
  927. ; Display String
  928. ; Entry:
  929. ;      DX = pointer to string
  930. ;
  931. Disp_09:
  932.         mov     DI,18               ; offset where (DS:DX) goes within string
  933.         add     DI,DX
  934.         mov     cx,52               ; max number of char's to fit in window
  935.         push    DS
  936.         mov     DS,DSsave
  937.         mov     SI,[BP+REGDX]       ; get USER's DS:DX value
  938. rep     movsb                       ; copy user's memory to text string
  939.         pop     DS
  940.         mov     DI,18
  941.         add     DI,DX
  942.         mov     CX,52               ; max # of char's we care about
  943.         mov     AL,'$'              ; search for '$' terminator
  944. repne   scasb
  945.         jnz     d09                 ; jump if '$' not in first 52 chars
  946.         dec     DI
  947.         mov     BYTE PTR [DI],00    ; replace with <NULL> terminator
  948. d09:
  949.         call    Disp_Str
  950.         ret
  951.  
  952. Disp_39:
  953. Disp_3a:
  954. Disp_3b:
  955. Disp_3c:
  956. Disp_3d:
  957. Disp_41:
  958. Disp_5a:
  959. Disp_5b:
  960.         mov     DI,18               ; offset where (DS:DX) goes within string
  961.         mov     cx,52               ; max number of char's to fit in window
  962.         call    One_String
  963.         ret
  964.  
  965. Disp_0a:
  966. Disp_23:
  967.         mov     DI,27
  968.         call    OutDSDX
  969.         ret
  970.  
  971. ;
  972. ; Clear Keyboard and Do Function
  973. ;
  974. Disp_0c:
  975.         mov     DI,31
  976.         mov     AX,AXsave           ; AL register has function number
  977.         call    OutByte
  978.         ret
  979.  
  980. ;
  981. ; Select Disk
  982. ;
  983. Disp_0e:
  984.         mov     DI,12
  985.         mov     AX,[BP+REGDX]       ; DL register has char to output
  986.         call    OutByte
  987.         ret
  988.  
  989. ;
  990. ; Open File Using FCB
  991. ;
  992. Disp_0f:
  993.         mov     DI,23
  994.         call    OutDSDX
  995.         ret
  996.  
  997. ;
  998. ; Close File Using FCB
  999. ;
  1000. Disp_10:
  1001.         mov     DI,24
  1002.         call    OutDSDX
  1003.         ret
  1004.  
  1005. ;
  1006. ; Search For First Matching File Using FCB
  1007. ;
  1008. Disp_11:
  1009.         mov     DI,44
  1010.         call    OutDSDX
  1011.         ret
  1012.  
  1013. ;
  1014. ; Search For Next Matching File Using FCB
  1015. ;
  1016. Disp_12:
  1017.         mov     DI,43
  1018.         call    OutDSDX
  1019.         ret
  1020.  
  1021. ;
  1022. ; Delete File Using FCB
  1023. ; Create File Using FCB
  1024. ; Rename File Using FCB
  1025. ;
  1026. Disp_13:
  1027. Disp_16:
  1028. Disp_17:
  1029.         mov     DI,25
  1030.         call    OutDSDX
  1031.         ret
  1032.  
  1033. ;
  1034. ; Read Sequential File Record Using FCB
  1035. ;
  1036. Disp_14:
  1037.         mov     DI,41
  1038.         call    OutDSDX
  1039.         ret
  1040.  
  1041. ;
  1042. ; Write Sequential File Record Using FCB
  1043. ;
  1044. Disp_15:
  1045.         mov     DI,42
  1046.         call    OutDSDX
  1047.         ret
  1048.  
  1049. ;
  1050. ; Set Disk Transfer Address
  1051. ;
  1052. Disp_1a:
  1053.         mov     DI,29
  1054.         call    OutDSDX
  1055.         ret
  1056.  
  1057. ;
  1058. ; Get FAT Information For Drive
  1059. ;
  1060. Disp_1c:
  1061.         mov     DI,30
  1062.         mov     AX,[BP+REGDX]       ; DL register has drive number
  1063.         call    OutByte
  1064.         ret
  1065.  
  1066.  
  1067. ;
  1068. ; Read Random File Record Using FCB
  1069. ; Set Random Record Field Using FCB
  1070. ;
  1071. Disp_21:
  1072. Disp_24:
  1073.         mov     DI,37
  1074.         call    OutDSDX
  1075.         ret
  1076.  
  1077. ;
  1078. ; Write Random File Record Using FCB
  1079. ;
  1080. Disp_22:
  1081.         mov     DI,38
  1082.         call    OutDSDX
  1083.         ret
  1084.  
  1085. ;
  1086. ; Set Interrupt Vector
  1087. ;
  1088. Disp_25:
  1089.         mov     DI,DX
  1090.         add     DI,21
  1091.         mov     AX,AXsave           ; AL has interrupt vector number
  1092.         call    Shexbyt
  1093.         mov     DI,28
  1094.         call    OutDSDX
  1095.         ret
  1096.  
  1097. ;
  1098. ; Create New Program Segment
  1099. ;
  1100. Disp_26:
  1101.         mov     DI,38
  1102.         mov     AX,[BP+REGDX]       ; get user's DX
  1103.         call    OutWord
  1104.         ret
  1105.  
  1106. ;
  1107. ; Read Random File Records
  1108. ;
  1109. Disp_27:
  1110.         mov     DI,DX
  1111.         add     DI,5
  1112.         mov     AX,[BP+REGCX]       ; CX register has record count
  1113.         call    Shexwrd
  1114.         mov     DI,44
  1115.         call    OutDSDX
  1116.         ret
  1117.  
  1118. ;
  1119. ; Write Random File Records
  1120. ;
  1121. Disp_28:
  1122.         mov     DI,DX
  1123.         add     DI,6
  1124.         mov     AX,[BP+REGCX]       ; CX register has record count
  1125.         call    Shexwrd
  1126.         mov     DI,45
  1127.         call    OutDSDX
  1128.         ret
  1129. ;
  1130. ; Parse Filename
  1131. ;
  1132. Disp_29:
  1133.         mov     DI,18               ; offset where (DS:SI) goes within string
  1134.         mov     cx,52               ; max number of char's to fit in window
  1135.         add     DI,DX
  1136.         push    DI                  ; save for scan later
  1137.         push    DS
  1138.         mov     DS,DSsave
  1139.         mov     SI,[BP+REGSI]       ; get USER's DS:SI value
  1140. rep     movsb                       ; copy user's memory to text string
  1141.         pop     DS
  1142. ;
  1143. ; look for <CR> in string and put <NULL> terminator there
  1144. ;
  1145.         pop     DI
  1146.         mov     AL,CR
  1147.         mov     cx,52
  1148. repne   scasb
  1149.         jnz     dpf
  1150.         dec     DI
  1151.         xor     AL,AL
  1152.         mov     [DI],AL
  1153. dpf:
  1154.         call    Disp_Str
  1155.         ret
  1156.  
  1157. ;
  1158. ; Set Date
  1159. ;
  1160. Disp_2b:
  1161.         mov     DI,DX
  1162.         add     DI,22
  1163.         mov     AX,[BP+REGDX]       ; DX register has month/day
  1164.         mov     AL,AH
  1165.         xor     AH,AH
  1166.         call    HextoDec            ; convert month
  1167.         movsb
  1168.         movsb
  1169.         inc     DI                  ; skip past '/'
  1170.         mov     AX,[BP+REGDX]
  1171.         xor     AH,AH
  1172.         call    HextoDec            ; convert day
  1173.         movsb
  1174.         movsb
  1175.         inc     DI                  ; skip past '/'
  1176.         mov     AX,[BP+REGCX]
  1177.         call    HextoDec            ; convert year
  1178.         movsb
  1179.         movsb
  1180.         call    Disp_Str
  1181.         ret
  1182.  
  1183. ;
  1184. ; Set Time
  1185. ;
  1186. Disp_2d:
  1187.         mov     DI,DX
  1188.         add     DI,33
  1189.         mov     AX,[BP+REGCX]       ; CX register has hours/minutes
  1190.         mov     AL,AH
  1191.         xor     AH,AH
  1192.         call    HextoDec            ; convert hours
  1193.         movsb
  1194.         movsb
  1195.         inc     DI                  ; skip past ':'
  1196.         mov     AX,[BP+REGCX]
  1197.         xor     AH,AH
  1198.         call    HextoDec            ; convert minutes
  1199.         movsb
  1200.         movsb
  1201.         inc     DI                  ; skip past ':'
  1202.         mov     AX,[BP+REGDX]       ; DX has seconds/hundreds of seconds
  1203.         mov     AL,AH
  1204.         xor     AH,AH
  1205.         call    HextoDec            ; convert seconds
  1206.         movsb
  1207.         movsb
  1208.         inc     DI                  ; skip past ':'
  1209.         mov     AX,[BP+REGDX]
  1210.         xor     AH,AH
  1211.         call    HextoDec            ; convert hundreds
  1212.         movsb
  1213.         movsb
  1214.         call    Disp_Str
  1215.         ret
  1216.  
  1217. ;
  1218. ; Set Disk Write Verification
  1219. ;
  1220. Disp_2e:
  1221.         mov     DI,DX
  1222.         add     DI,28
  1223.         mov     AX,AXsave           ; AL register has verify switch
  1224.         mov     SI,OFFSET OFFstr
  1225.         cmp     AL,00               ; AL = 0 means OFF
  1226.         jz      verptr
  1227.         mov     SI,OFFSET ONstr
  1228.         cmp     AL,01               ; AL = 1 means ON
  1229.         jz      verptr
  1230.         mov     SI,OFFSET Blanks3   ; unknown code
  1231. verptr:
  1232.         mov     CX,3
  1233. rep     movsb
  1234.         call    Disp_Str
  1235.         ret
  1236.  
  1237. ;
  1238. ; Get/Set Control-Break Status
  1239. ;
  1240. Disp_33:
  1241.         mov     AX,AXsave           ; AL register has get/set switch
  1242.         cmp     AL,01               ; AL = 1 for SET
  1243.         jz      setcbs
  1244.         cmp     AL,00               ; AL = 0 for GET
  1245.         jnz     unk33               ; jump if unknown code
  1246.         mov     DX,OFFSET STR33G
  1247. unk33:
  1248.         call    Disp_Str
  1249.         ret
  1250.  
  1251. setcbs:
  1252.         mov     DX,OFFSET STR33S    ; point to 'SET' string
  1253.         mov     DI,DX
  1254.         add     DI,25
  1255.         mov     AX,[BP+REGDX]       ; DL has set code
  1256.         mov     SI,OFFSET OFFstr
  1257.         cmp     AL,00               ; AL = 00 means OFF
  1258.         jz      gscbs
  1259.         mov     SI,OFFSET ONstr
  1260.         cmp     AL,01               ; AL = 01 means ON
  1261.         jz      gscbs
  1262.         mov     SI,OFFSET Blanks3
  1263. gscbs:
  1264.         mov     CX,3
  1265. rep     movsb
  1266.         call    Disp_Str
  1267.         ret
  1268.  
  1269. ;
  1270. ; Get Interrupt Vector
  1271. ;
  1272. Disp_35:
  1273.         mov     DI,21
  1274.         mov     AX,AXsave           ; AL has interrupt vector number
  1275.         call    OutByte
  1276.         ret
  1277.  
  1278. ;
  1279. ; Get Disk Free Space On Drive
  1280. ;
  1281. Disp_36:
  1282.         mov     DI,29
  1283.         mov     AX,[BP+REGDX]       ; DL register has drive code
  1284.         call    OutByte
  1285.         ret
  1286.  
  1287. ;
  1288. ; Close File Handle
  1289. ;
  1290. Disp_3e:
  1291.         mov     DI,18
  1292.         mov     AX,[BP+REGBX]       ; BX register has file handle
  1293.         call    OutWord
  1294.         ret
  1295.  
  1296. ;
  1297. ; Duplicate File Handle
  1298. ;
  1299. Disp_45:
  1300.         mov     DI,22
  1301.         mov     AX,[BP+REGBX]       ; BX register has file handle
  1302.         call    OutWord
  1303.         ret
  1304.  
  1305. ;
  1306. ; Read From File or Device
  1307. ;
  1308. Disp_3f:
  1309.         mov     DI,DX
  1310.         add     DI,5
  1311.         mov     AX,[BP+REGCX]       ; CX has number of bytes to read
  1312.         call    Shexwrd
  1313.         mov     DI,37
  1314.         mov     AX,[BP+REGBX]       ; BX has file handle
  1315.         call    OutWord
  1316.         ret
  1317.  
  1318. ;
  1319. ; Write To File or Device
  1320. ;
  1321. Disp_40:
  1322.         mov     DI,DX
  1323.         add     DI,6
  1324.         mov     AX,[BP+REGCX]       ; CX has number of bytes to read
  1325.         call    Shexwrd
  1326.         mov     DI,36
  1327.         mov     AX,[BP+REGBX]       ; BX has file handle
  1328.         call    OutWord
  1329.         ret
  1330.  
  1331. ;
  1332. ; Move File Pointer
  1333. ;
  1334. Disp_42:
  1335.         mov     DI,DX
  1336.         add     DI,17
  1337.         mov     AX,[BP+REGBX]       ; BX register has file handle
  1338.         call    Shexwrd
  1339.         add     DI,13
  1340.         mov     AX,[BP+REGCX]       ; CX has upper half of offset
  1341.         call    Shexwrd
  1342.         inc     DI                  ; skip past ':'
  1343.         mov     AX,[BP+REGDX]       ; CX has lower half of offset
  1344.         call    Shexwrd
  1345.         add     DI,7
  1346.         mov     AX,AXsave           ; AL has method code
  1347.         mov     SI,OFFSET BOFstr
  1348.         cmp     AL,00               ; beginning of file?
  1349.         jz      mvptr
  1350.         mov     SI,OFFSET CURstr
  1351.         cmp     AL,01               ; current location?
  1352.         jz      mvptr
  1353.         mov     SI,OFFSET EOFstr
  1354.         cmp     AL,02               ; end of file?
  1355.         jz      mvptr
  1356.         mov     SI,OFFSET Blanks17  ; unknown
  1357. mvptr:
  1358.         mov     cx,17               ; string length
  1359. rep     movsb
  1360.         call    Disp_Str
  1361.         ret
  1362.  
  1363. ;
  1364. ; Get/Set file attributes
  1365. ;
  1366. Disp_43:
  1367.         mov     AX,AXsave           ; user's AX has get/set flag
  1368.         cmp     AL,00               ; 'get' code?
  1369.         jz      fgptr
  1370.         cmp     AL,01               ; 'set' code?
  1371.         jz      fsptr
  1372.         call    Disp_Str            ; unknown code
  1373.         ret
  1374. fgptr:
  1375.         mov     DX,OFFSET STR43G    ; point to GET string
  1376.         jmp     SHORT faptr
  1377. ;
  1378. fsptr:
  1379.         mov     DX,OFFSET STR43S    ; point to SET string
  1380. faptr:
  1381.         mov     DI,18
  1382.         mov     cx,52               ; max number of char's to fit in window
  1383.         call    One_String
  1384.         ret
  1385.  
  1386. ;
  1387. ; I/O Control For Devices
  1388. ;
  1389. Disp_44:
  1390.         mov     AX,AXsave
  1391.         cmp     AL,00
  1392.         jz      jd440
  1393.         cmp     AL,01
  1394.         jz      jd441
  1395.         cmp     AL,02
  1396.         jz      jd442
  1397.         cmp     AL,03
  1398.         jz      jd443
  1399.         cmp     AL,04
  1400.         jz      jd444
  1401.         cmp     AL,05
  1402.         jz      jd445
  1403.         cmp     AL,06
  1404.         jz      jd446
  1405.         cmp     AL,07
  1406.         jz      jd447
  1407.         cmp     AL,08
  1408.         jz      jd448
  1409.         cmp     AL,11
  1410.         jz      jd4411
  1411.         call    Disp_Str            ; unknown code
  1412.         ret
  1413.  
  1414. jd440:  jmp     d440
  1415. jd441:  jmp     d441
  1416. jd442:  jmp     d442
  1417. jd443:  jmp     d443
  1418. jd444:  jmp     d444
  1419. jd445:  jmp     d445
  1420. jd446:  jmp     d446
  1421. jd447:  jmp     d447
  1422. jd448:  jmp     d448
  1423. jd4411: jmp     d4411
  1424.  
  1425. d440:
  1426.         mov     DX,OFFSET STR440    ; Get Info For Device
  1427.         mov     DI,20
  1428.         mov     AX,[BP+REGBX]       ; BX has file handle
  1429.         call    OutWord
  1430.         ret
  1431. ;
  1432. d441:
  1433.         mov     DX,OFFSET STR441    ; Set Info For Device
  1434.         mov     DI,DX
  1435.         add     DI,20
  1436.         mov     AX,[BP+REGBX]       ; BX has file handle
  1437.         call    Shexwrd
  1438.         mov     DI,29
  1439.         mov     AX,[BP+REGDX]       ; DX has device information
  1440.         call    OutWord
  1441.         ret
  1442. ;
  1443. d442:
  1444.         mov     DX,OFFSET STR442    ; Read From Drive Control Channel
  1445.         mov     DI,DX
  1446.         add     DI,5
  1447.         mov     AX,[BP+REGCX]       ; CX has byte count
  1448.         call    Shexwrd
  1449.         mov     DI,52
  1450.         mov     AX,[BP+REGBX]       ; BX has file handle
  1451.         call    OutWord
  1452.         ret
  1453. ;
  1454. d443:
  1455.         mov     DX,OFFSET STR443    ; Write To Drive Control Channel
  1456.         mov     DI,DX
  1457.         add     DI,6
  1458.         mov     AX,[BP+REGCX]       ; CX has byte count
  1459.         call    Shexwrd
  1460.         mov     DI,51
  1461.         mov     AX,[BP+REGBX]       ; BX has file handle
  1462.         call    OutWord
  1463.         ret
  1464. ;
  1465. d444:
  1466.         mov     DX,OFFSET STR444    ; Read From Control Channel of Drive
  1467.         mov     DI,DX
  1468.         add     DI,5
  1469.         mov     AX,[BP+REGCX]       ; CX has byte count
  1470.         call    Shexwrd
  1471.         mov     DI,47
  1472.         mov     AX,[BP+REGBX]       ; BL has drive
  1473.         call    OutByte
  1474.         ret
  1475. ;
  1476. d445:
  1477.         mov     DX,OFFSET STR445    ; Write To Control Channel of Drive
  1478.         mov     DI,DX
  1479.         add     DI,6
  1480.         mov     AX,[BP+REGCX]       ; CX has byte count
  1481.         call    Shexwrd
  1482.         mov     DI,46
  1483.         mov     AX,[BP+REGBX]       ; BL has drive
  1484.         call    OutByte
  1485.         ret
  1486. ;
  1487. d446:
  1488.         mov     DX,OFFSET STR446    ; Get Input Status of Device
  1489.         mov     DI,27
  1490.         mov     AX,[BP+REGBX]       ; BX has file handle
  1491.         call    OutWord
  1492.         ret
  1493. ;
  1494. d447:
  1495.         mov     DX,OFFSET STR447    ; Get Output Status of Device
  1496.         mov     DI,28
  1497.         mov     AX,[BP+REGBX]       ; BX has file handle
  1498.         call    OutWord
  1499.         ret
  1500. ;
  1501. d448:
  1502.         mov     DX,OFFSET STR448    ; Report Whether Device Has Removable Media
  1503.         mov     DI,22
  1504.         mov     AX,[BP+REGBX]       ; BX has file handle
  1505.         call    OutWord
  1506.         ret
  1507. ;
  1508. d4411:
  1509.         mov     DX,OFFSET STR4411   ; Set Retries For Device
  1510.         mov     DI,DX
  1511.         add     DI,23
  1512.         mov     AX,[BP+REGBX]       ; BX has file handle
  1513.         call    Shexwrd
  1514.         add     DI,5
  1515.         mov     AX,[BP+REGDX]       ; DX has retry count
  1516.         call    Shexwrd
  1517.         mov     DI,55
  1518.         mov     AX,[BP+REGCX]       ; CX has interval between tries
  1519.         call    OutWord
  1520.         ret
  1521.  
  1522. ;
  1523. ; Force Duplication of Handle
  1524. ;
  1525. Disp_46:
  1526.         mov     DI,DX
  1527.         add     DI,28
  1528.         mov     AX,[BP+REGBX]       ; BX has the existing file handle
  1529.         call    Shexwrd
  1530.         mov     DI,37
  1531.         mov     AX,[BP+REGCX]       ; CX has the second file handle
  1532.         call    OutWord
  1533.         ret
  1534.  
  1535. ;
  1536. ; Get Current Directory
  1537. ;
  1538. Disp_47:
  1539.         mov     DI,DX
  1540.         add     DI,31
  1541.         mov     AX,[BP+REGDX]       ; DL register has drive code
  1542.         call    Shexbyt
  1543.         add     DI,7
  1544.         mov     AX,DSsave
  1545.         call    Shexwrd
  1546.         inc     DI                  ; skip ':'
  1547.         mov     AX,[BP+REGSI]       ; get USER's DS:SI value
  1548.         call    Shexwrd
  1549.         call    Disp_Str
  1550.         ret
  1551.  
  1552. ;
  1553. ; Allocate Memory
  1554. ;
  1555. Disp_48:
  1556.         mov     DI,9
  1557.         mov     AX,[BP+REGBX]       ; BX has the memory requested in paragraphs
  1558.         call    OutWord
  1559.         ret
  1560.  
  1561. ;
  1562. ; Free Allocated Memory
  1563. ;
  1564. Disp_49:
  1565.         mov     DI,33
  1566.         mov     AX,[BP+REGES]       ; ES has the segment address
  1567.         call    OutWord
  1568.         ret
  1569.  
  1570. ;
  1571. ; Modify Memory Block
  1572. ;
  1573. Disp_4a:
  1574.         mov     DI,DX
  1575.         add     DI,31
  1576.         mov     AX,[BP+REGES]       ; ES has the segment address
  1577.         call    Shexwrd
  1578.         mov     DI,43
  1579.         mov     AX,[BP+REGBX]       ; BX has size in paragraphs
  1580.         call    OutWord
  1581.         ret
  1582.  
  1583. ;
  1584. ; Load or Exececute Program
  1585. ; Find First Matching File
  1586. ;
  1587. Disp_4b:
  1588. Disp_4e:
  1589.         mov     DI,29               ; offset where (DS:DX) goes within string
  1590.         mov     cx,41               ; max number of char's to fit in window
  1591.         call    One_String
  1592.         ret
  1593.  
  1594. ;
  1595. ; Terminate Process with Return Code
  1596. ;
  1597. Disp_4c:
  1598.         mov     DI,35
  1599.         mov     AX,Axsave           ; AL register return code
  1600.         call    OutByte
  1601.         ret
  1602.  
  1603. ;
  1604. ; Rename File
  1605. ;
  1606. Disp_56:
  1607.         mov     DI,29
  1608.         mov     cx,41
  1609.         call    One_String          ; display 'old' name
  1610. ;
  1611.         mov     DX,OFFSET STR56N
  1612.         mov     DI,DX
  1613.         add     DI,29
  1614.         push    DS
  1615.         mov     DS,[BP+REGES]
  1616.         mov     SI,[BP+REGDI]       ; get USER's ES:DI value
  1617.         mov     cx,41               ;  to display 'new' name
  1618. rep     movsb
  1619.         pop     DS
  1620.         mov     CX,0601h
  1621.         mov     BX,OFFSET W1
  1622.         mov     AH,HIWHITE
  1623.         call    WPrint
  1624.         ret
  1625.  
  1626. ;
  1627. ; Get Date and Time of File
  1628. ;
  1629. Disp_57:
  1630.         mov     AX,AXsave           ; user's AL has get/set indicator
  1631.         cmp     AL,00               ; is it GET?
  1632.         jz      gdtptr
  1633.         cmp     AL,01               ; is it SET?
  1634.         jz      sdtptr
  1635.         mov     DI,37               ; unknown function
  1636.         mov     AX,[BP+REGBX]       ; file handle
  1637.         call    OutWord
  1638.         ret
  1639. gdtptr:
  1640.         mov     DX,OFFSET STR57G
  1641.         jmp     SHORT ddtptr
  1642. ;
  1643. sdtptr:
  1644.         mov     DX,OFFSET STR57S
  1645. ddtptr:
  1646.         mov     DI,33
  1647.         mov     AX,[BP+REGBX]       ; BX register has file handle
  1648.         call    OutWord
  1649.         ret
  1650.  
  1651. ;
  1652. ; Lock/Unlock File
  1653. ;
  1654. Disp_5c:
  1655.         mov     AX,AXsave
  1656.         cmp     AL,00               ; 0 = Lock
  1657.         jz      dlck
  1658.         cmp     AL,01               ; 1 = Unlock
  1659.         jz      dunlck
  1660.         mov     DI,17
  1661.         mov     AX,[BP+REGBX]       ; BX has file handle
  1662.         call    OutWord
  1663.         ret
  1664. ;
  1665. dlck:
  1666.         mov     DX,OFFSET STR5c0
  1667.         mov     DI,10
  1668.         mov     AX,[BP+REGBX]
  1669.         call    OutWord
  1670.         ret
  1671. ;
  1672. dunlck:
  1673.         mov     DX,OFFSET STR5c1
  1674.         mov     DI,12
  1675.         mov     AX,[BP+REGBX]
  1676.         call    OutWord
  1677.         ret
  1678.  
  1679.  
  1680. ;
  1681. ; Table of function codes.
  1682. ; (1st) word is DOS function code (AH),
  1683. ; (2nd) word is pointer to string to display,
  1684. ; (3rd) word is subroutine address to handle display of this type function.
  1685. ;
  1686. FCtbl:
  1687.         dw      0000h, STR00, Disp_Str
  1688.         dw      0100h, STR01, Disp_Str
  1689.         dw      0200h, STR02, Disp_02
  1690.         dw      0300h, STR03, Disp_Str
  1691.         dw      0400h, STR04, Disp_04
  1692.         dw      0500h, STR05, Disp_05
  1693.         dw      0600h, STR06, Disp_06
  1694.         dw      0700h, STR07, Disp_Str
  1695.         dw      0800h, STR08, Disp_Str
  1696.         dw      0900h, STR09, Disp_09
  1697.         dw      0a00h, STR0a, Disp_0a
  1698.         dw      0b00h, STR0b, Disp_Str
  1699.         dw      0c00h, STR0c, Disp_0c
  1700.         dw      0d00h, STR0d, Disp_Str
  1701.         dw      0e00h, STR0e, Disp_0e
  1702.         dw      0f00h, STR0f, Disp_0f
  1703.         dw      1000h, STR10, Disp_10
  1704.         dw      1100h, STR11, Disp_11
  1705.         dw      1200h, STR12, Disp_12
  1706.         dw      1300h, STR13, Disp_13
  1707.         dw      1400h, STR14, Disp_14
  1708.         dw      1500h, STR15, Disp_15
  1709.         dw      1600h, STR16, Disp_16
  1710.         dw      1700h, STR17, Disp_17
  1711.         dw      1800h, STRUN, Disp_Str
  1712.         dw      1900h, STR19, Disp_Str
  1713.         dw      1a00h, STR1a, Disp_1a
  1714.         dw      1b00h, STR1b, Disp_Str
  1715.         dw      1c00h, STR1c, Disp_1c
  1716.         dw      1d00h, STRUN, Disp_Str
  1717.         dw      1e00h, STRUN, Disp_Str
  1718.         dw      1f00h, STRUN, Disp_Str
  1719.         dw      2000h, STRUN, Disp_Str
  1720.         dw      2100h, STR21, Disp_21
  1721.         dw      2200h, STR22, Disp_22
  1722.         dw      2300h, STR23, Disp_23
  1723.         dw      2400h, STR24, Disp_24
  1724.         dw      2500h, STR25, Disp_25
  1725.         dw      2600h, STR26, Disp_26
  1726.         dw      2700h, STR27, Disp_27
  1727.         dw      2800h, STR28, Disp_28
  1728.         dw      2900h, STR29, Disp_29
  1729.         dw      2a00h, STR2a, Disp_Str
  1730.         dw      2b00h, STR2b, Disp_2b
  1731.         dw      2c00h, STR2c, Disp_Str
  1732.         dw      2d00h, STR2d, Disp_2d
  1733.         dw      2e00h, STR2e, Disp_2e
  1734.         dw      2f00h, STR2f, Disp_Str
  1735.         dw      3000h, STR30, Disp_Str
  1736.         dw      3100h, STR31, Disp_Str
  1737.         dw      3200h, STRUN, Disp_Str
  1738.         dw      3300h, STR33, Disp_33
  1739.         dw      3400h, STRUN, Disp_Str
  1740.         dw      3500h, STR35, Disp_35
  1741.         dw      3600h, STR36, Disp_36
  1742.         dw      3700h, STR37, Disp_Str
  1743.         dw      3800h, STR38, Disp_Str
  1744.         dw      3900h, STR39, Disp_39
  1745.         dw      3a00h, STR3a, Disp_3a
  1746.         dw      3b00h, STR3b, Disp_3b
  1747.         dw      3c00h, STR3c, Disp_3c
  1748.         dw      3d00h, STR3d, Disp_3d
  1749.         dw      3e00h, STR3e, Disp_3e
  1750.         dw      3f00h, STR3f, Disp_3f
  1751.         dw      4000h, STR40, Disp_40
  1752.         dw      4100h, STR41, Disp_41
  1753.         dw      4200h, STR42, Disp_42
  1754.         dw      4300h, STR43, Disp_43
  1755.         dw      4400h, STR44, Disp_44
  1756.         dw      4500h, STR45, Disp_45
  1757.         dw      4600h, STR46, Disp_46
  1758.         dw      4700h, STR47, Disp_47
  1759.         dw      4800h, STR48, Disp_48
  1760.         dw      4900h, STR49, Disp_49
  1761.         dw      4a00h, STR4a, Disp_4a
  1762.         dw      4b00h, STR4b, Disp_4b
  1763.         dw      4c00h, STR4c, Disp_4c
  1764.         dw      4d00h, STR4d, Disp_Str
  1765.         dw      4e00h, STR4e, Disp_4e
  1766.         dw      4f00h, STR4f, Disp_Str
  1767.         dw      5000h, STRUN, Disp_Str
  1768.         dw      5100h, STRUN, Disp_Str
  1769.         dw      5200h, STRUN, Disp_Str
  1770.         dw      5300h, STRUN, Disp_Str
  1771.         dw      5400h, STR54, Disp_Str
  1772.         dw      5500h, STRUN, Disp_Str
  1773.         dw      5600h, STR56, Disp_56
  1774.         dw      5700h, STR57, Disp_57
  1775.         dw      5800h, STRUN, Disp_Str
  1776.         dw      5900h, STR59, Disp_Str
  1777.         dw      5a00h, STR5a, Disp_5a
  1778.         dw      5b00h, STR5b, Disp_5b
  1779.         dw      5c00h, STR5c, Disp_5c
  1780.         dw      5d00h, STRUN, Disp_Str
  1781.         dw      5e00h, STRUN, Disp_Str
  1782.         dw      5f00h, STRUN, Disp_Str
  1783.         dw      6000h, STRUN, Disp_Str
  1784.         dw      6100h, STRUN, Disp_Str
  1785.         dw      6200h, STR62, Disp_Str
  1786. LENFC   EQU     $ - FCtbl
  1787.  
  1788. ;
  1789. ; The XX's are just place holders for help in alignment during debugging
  1790. ;
  1791. STR00   db      'Terminate Program'
  1792.         db      0
  1793.  
  1794. STR01   db      'Keyboard Input With Echo'
  1795.         db      0
  1796.  
  1797. STR02   db      'Output Character  Hex XX  ASCII X'
  1798.         db      0
  1799.  
  1800. STR03   db      'Serial Input'
  1801.         db      0
  1802.  
  1803. STR04   db      'Serial Output     Hex XX  ASCII X'
  1804.         db      0
  1805.  
  1806. STR05   db      'Printer Output    Hex XX  ASCII X'
  1807.         db      0
  1808.  
  1809. STR06   db      'Direct Console I/O - '
  1810.         db      0
  1811.  
  1812. STR06I  db      'Input Character'
  1813.         db      0
  1814.  
  1815. STR07   db      'Direct Console Input Without Echo'
  1816.         db      0
  1817.  
  1818. STR08   db      'Console Input Without Echo'
  1819.         db      0
  1820.  
  1821. STR09   db      'Display String -->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1822.         db      'XXXXXXXXXXXL'
  1823.         db      0
  1824.  
  1825. STR0a   db      'Buffered Keyboard Input To XXXX:XXXXH'
  1826.         db      0
  1827.  
  1828. STR0b   db      'Check Standard Input Status'
  1829.         db      0
  1830.  
  1831. STR0c   db      'Clear Keyboard and Do Function XXH'
  1832.         db      0
  1833.  
  1834. STR0d   db      'Reset Disk'
  1835.         db      0
  1836.  
  1837. STR0e   db      'Select Disk XXH'
  1838.         db      0
  1839.  
  1840. STR0f   db      'Open File Using FCB at XXXX:XXXXH'
  1841.         db      0
  1842.  
  1843. STR10   db      'Close File Using FCB at XXXX:XXXXH'
  1844.         db      0
  1845.  
  1846. STR11   db      'Search For First Matching File Using FCB at XXXX:XXXXH'
  1847.         db      0
  1848.  
  1849. STR12   db      'Search For Next Matching File Using FCB at XXXX:XXXXH'
  1850.         db      0
  1851.  
  1852. STR13   db      'Delete File Using FCB at XXXX:XXXXH'
  1853.         db      0
  1854.  
  1855. STR14   db      'Read Sequential File Record Using FCB at XXXX:XXXXH'
  1856.         db      0
  1857.  
  1858. STR15   db      'Write Sequential File Record Using FCB at XXXX:XXXXH'
  1859.         db      0
  1860.  
  1861. STR16   db      'Create File Using FCB at XXXX:XXXXH'
  1862.         db      0
  1863.  
  1864. STR17   db      'Rename File Using FCB at XXXX:XXXXH'
  1865.         db      0
  1866.  
  1867. STR19   db      'Report Current Drive'
  1868.         db      0
  1869.  
  1870. STR1a   db      'Set Disk Transfer Address To XXXX:XXXXH'
  1871.         db      0
  1872.  
  1873. STR1b   db      'Get FAT Information For Default Drive'
  1874.         db      0
  1875.  
  1876. STR1c   db      'Get FAT Information For Drive XXH'
  1877.         db      0
  1878.  
  1879. STR21   db      'Read Random File Record Using FCB at XXXX:XXXXH'
  1880.         db      0
  1881.  
  1882. STR22   db      'Write Random File Record Using FCB at XXXX:XXXXH'
  1883.         db      0
  1884.  
  1885. STR23   db      'Get File Size Using FCB at XXXX:XXXXH'
  1886.         db      0
  1887.  
  1888. STR24   db      'Set Random Record Field Using FCB at XXXX:XXXXH'
  1889.         db      0
  1890.  
  1891. STR25   db      'Set Interrupt Vector XXH to XXXX:XXXXH'
  1892.         db      0
  1893.  
  1894. STR26   db      'Create New Program Segment At Segment XXXXH'
  1895.         db      0
  1896.  
  1897. STR27   db      'Read XXXXH Random File Records Using FCB at XXXX:XXXXH'
  1898.         db      0
  1899.  
  1900. STR28   db      'Write XXXXH Random File Records Using FCB at XXXX:XXXXH'
  1901.         db      0
  1902.  
  1903. STR29   db      'Parse Filename -->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1904.         db      'XXXXXXXXXXXL'
  1905.         db      0
  1906.  
  1907. STR2a   db      'Get Date'
  1908.         db      0
  1909.  
  1910. STR2b   db      'Set Date To mm/dd/yy  XX/XX/XX'
  1911.         db      0
  1912.  
  1913. STR2c   db      'Get Time'
  1914.         db      0
  1915.  
  1916. STR2d   db      'Set Time To Hrs:Mins:Secs:Hunds  XX:XX:XX:XX'
  1917.         db      0
  1918.  
  1919. STR2e   db      'Set Disk Write Verification XXX'
  1920.         db      0
  1921.  
  1922. STR2f   db      'Get Disk Transfer Address'
  1923.         db      0
  1924.  
  1925. STR30   db      'Get DOS Version Number'
  1926.         db      0
  1927.  
  1928. STR31   db      'Terminate Process and Remain Resident'
  1929.         db      0
  1930.  
  1931. STR33   db      'Get/Set Control-Break Status'
  1932.         db      0
  1933.  
  1934. STR33G  db      'Get Control-Break Status'
  1935.         db      0
  1936.  
  1937. STR33S  db      'Set Control-Break Status XXX'
  1938.         db      0
  1939.  
  1940. STR35   db      'Get Interrupt Vector XXH'
  1941.         db      0
  1942.  
  1943. STR36   db      'Get Disk Free Space On Drive XXH'
  1944.         db      0
  1945.  
  1946. STR37   db      'Get DOS Switch Character'
  1947.         db      0
  1948.  
  1949. STR38   db      'Get/Set Country Dependent Information'
  1950.         db      0
  1951.  
  1952. STR39   db      'Create Subdir --->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1953.         db      'XXXXXXXXXXXL'
  1954.         db      0
  1955.  
  1956. STR3a   db      'Remove Subdir --->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1957.         db      'XXXXXXXXXXXL'
  1958.         db      0
  1959.  
  1960. STR3b   db      'Change Dir To --->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1961.         db      'XXXXXXXXXXXL'
  1962.         db      0
  1963.  
  1964. STR3c   db      'Create File ----->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1965.         db      'XXXXXXXXXXXL'
  1966.         db      0
  1967.  
  1968. STR3d   db      'Open File ------->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1969.         db      'XXXXXXXXXXXL'
  1970.         db      0
  1971.  
  1972. STR3e   db      'Close File Handle XXXXH'
  1973.         db      0
  1974.  
  1975. STR3f   db      'Read XXXXH Bytes From File or Device XXXXH'
  1976.         db      0
  1977.  
  1978. STR40   db      'Write XXXXH Bytes To File or Device XXXXH'
  1979.         db      0
  1980.  
  1981. STR41   db      'Delete File ----->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1982.         db      'XXXXXXXXXXXL'
  1983.         db      0
  1984.  
  1985. STR42   db      'Move File Handle XXXXH Pointer By XXXX:XXXXH From '
  1986.         db      'XXXXXXXXXXXXXXXXX'
  1987.         db      0
  1988.  
  1989. STR43   db      'Get/Set File Attributes'
  1990.         db      0
  1991.  
  1992. STR43G  db      'Get File Attrib ->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1993.         db      'XXXXXXXXXXXX'
  1994.         db      0
  1995.  
  1996. STR43S  db      'Set File Attrib ->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1997.         db      'XXXXXXXXXXXX'
  1998.         db      0
  1999.  
  2000. STR44   db      'I/O Control For Devices'
  2001.         db      0
  2002.  
  2003. STR440  db      'Get Info For Device XXXXH'
  2004.         db      0
  2005.  
  2006. STR441  db      'Set Info For Device XXXXH to XXXXH'
  2007.         db      0
  2008.  
  2009. STR442  db      'Read XXXXH Bytes From Drive Control Channel of File XXXXH'
  2010.         db      0
  2011.  
  2012. STR443  db      'Write XXXXH Bytes To Drive Control Channel of File XXXXH'
  2013.         db      0
  2014.  
  2015. STR444  db      'Read XXXXH Bytes From Control Channel of Drive XXH'
  2016.         db      0
  2017.  
  2018. STR445  db      'Write XXXXH Bytes To Control Channel of Drive XXH'
  2019.         db      0
  2020.  
  2021. STR446  db      'Get Input Status of Device XXXXH'
  2022.         db      0
  2023.  
  2024. STR447  db      'Get Output Status of Device XXXXH'
  2025.         db      0
  2026.  
  2027. STR448  db      'Report Whether Device XXXXH Has Removable Media'
  2028.         db      0
  2029.  
  2030. STR4411 db      'Set Retries For Device XXXXH to XXXXH With Interval of XXXXH'
  2031.         db      0
  2032.  
  2033. STR45   db      'Duplicate File Handle XXXXH'
  2034.         db      0
  2035.  
  2036. STR46   db      'Force Duplication of Handle XXXXH to XXXXH'
  2037.         db      0
  2038.  
  2039. STR47   db      'Get Current Directory of Drive XXH into XXXX:XXXXH'
  2040.         db      0
  2041.  
  2042. STR48   db      'Allocate XXXXH Paragraphs of Memory'
  2043.         db      0
  2044.  
  2045. STR49   db      'Free Allocated Memory at Segment XXXXH'
  2046.         db      0
  2047.  
  2048. STR4a   db      'Modify Memory Block at Segment XXXXH to be XXXXH Paragraphs'
  2049.         db      0
  2050.  
  2051. STR4b   db      'Load or Execute Program ---->XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  2052.         db      'XXXXXXXXXXXX'
  2053.         db      0
  2054.  
  2055. STR4c   db      'Terminate Process With Return Code XXH'
  2056.         db      0
  2057.  
  2058. STR4d   db      'Get Return Code of Subprocess'
  2059.         db      0
  2060.  
  2061. STR4e   db      'Find First Matching File --->XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  2062.         db      'XXXXXXXXXXXX'
  2063.         db      0
  2064.  
  2065. STR4f   db      'Find Next Matching File'
  2066.         db      0
  2067.  
  2068. STR54   db      'Get Verify State'
  2069.         db      0
  2070.  
  2071. STR56   db      'Rename File   Old Name ----->XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  2072.         db      'XXXXXXXXXXXX'
  2073.         db      0
  2074.  
  2075. STR56N  db      '              New Name ----->XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  2076.         db      'XXXXXXXXXXXX'
  2077.         db      0
  2078.  
  2079. STR57   db      'Get/Set Date and Time of File Handle XXXXH'
  2080.         db      0
  2081.  
  2082. STR57G  db      'Get Date and Time of File Handle XXXXH'
  2083.         db      0
  2084.  
  2085. STR57S  db      'Set Date and Time of File Handle XXXXH'
  2086.         db      0
  2087.  
  2088. STR59   db      'Get Extended Error Code'
  2089.         db      0
  2090.  
  2091. STR5a   db      'Create Temp File  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  2092.         db      'XXXXXXXXXXXL'
  2093.         db      0
  2094.  
  2095. STR5b   db      'Create New File   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  2096.         db      'XXXXXXXXXXXL'
  2097.         db      0
  2098.  
  2099. STR5c   db      'Lock/Unlock File XXXXH'
  2100.         db      0
  2101.  
  2102. STR5c0  db      'Lock File XXXXH'
  2103.         db      0
  2104.  
  2105. STR5c1  db      'Unlock File XXXXH'
  2106.         db      0
  2107.  
  2108. STR62   db      'Get PSP Address'
  2109.         db      0
  2110.  
  2111. STRUN   db      '** Undocumented Function Code **'
  2112.         db      0
  2113.  
  2114. ;
  2115. ; Don't change the size of the following strings
  2116. ;
  2117. Blanks3  db      '   '
  2118. Blanks17 db      '                 '
  2119. ONstr    db      'ON '
  2120. OFFstr   db      'OFF'
  2121. BOFstr   db      'Beginning of File'
  2122. CURstr   db      'Current Location '
  2123. EOFstr   db      'End of File      '
  2124.  
  2125. RCStr   db      'Return Code = XXXXH'
  2126.         db      0
  2127.  
  2128. CFStr   db      'Carry Flag = X'
  2129.         db      0
  2130.  
  2131. ZFStr   db      'Zero Flag = X'
  2132.         db      0
  2133.  
  2134.  
  2135. Open_Window:
  2136.         push    BP
  2137.         push    ES
  2138. ;
  2139. ; Calculate current page offset each time since it can change at any time
  2140. ;
  2141.         mov     AH,0fh              ; get current video state
  2142.         int     10h
  2143.         mov     CL,BH               ; returns BH = active page #
  2144.         xor     CH,CH
  2145.         mov     AX,0100h            ; page length in paragraphs
  2146.         mul     cx
  2147.         add     AX,Scrseg           ; add base segment of screen
  2148.         mov     Pageseg,AX
  2149. ;
  2150. ; Save current contents of window area
  2151. ;
  2152.         mov     BX,OFFSET W1        ; window parameters
  2153.         mov     SI,[BX].startmem    ; screen addr of start of window
  2154.         mov     DX,[BX].height
  2155.         mov     ES,Winseg           ; point to allocated memory block
  2156.         mov     DI,0000
  2157. saverow:
  2158.         push    DS
  2159.         mov     CX,[BX].xwidth
  2160.         mov     DS,Pageseg          ; get screen segment
  2161.         push    SI                  ; save screen offset
  2162. rep     movsw                       ; do word to get char and attribute
  2163.         pop     SI
  2164.         pop     DS
  2165.         add     SI,BytesPL          ; next row down
  2166.         dec     DX
  2167.         jnz     saverow
  2168. ;
  2169. ; Draw window
  2170. ;
  2171.         mov     ES,Pageseg          ; get screen segment
  2172.         mov     DI,[BX].startmem    ; physical addr of start of window
  2173.         mov     AH,HIWHITE
  2174. ;
  2175. ; Draw top border
  2176. ;
  2177.         push    DI
  2178.         mov     AL,ULC              ; write upper left corner
  2179.         stosw
  2180.         mov     CX,[BX].xwidth
  2181.         sub     CX,2
  2182.         mov     AL,BRDROW
  2183. rep     stosw
  2184.         mov     AL,URC              ; write upper right corner
  2185.         stosw
  2186.         pop     DI
  2187.         add     DI,BytesPL          ; next row down
  2188. ;
  2189. ; Draw middle of window
  2190. ;
  2191.         mov     DX,[BX].height
  2192.         sub     DX,2
  2193. winrows:
  2194.         push    DI
  2195.         mov     AL,BRDCOL           ; left border column
  2196.         stosw
  2197.         mov     CX,[BX].xwidth
  2198.         sub     CX,2
  2199.         mov     AL,BLANK
  2200. rep     stosw
  2201.         mov     AL,BRDCOL           ; right border column
  2202.         stosw
  2203.         pop     DI
  2204.         add     DI,BytesPL          ; next row down
  2205.         dec     DX
  2206.         jnz     winrows
  2207. ;
  2208. ; Draw bottom border
  2209. ;
  2210.         push    DI
  2211.         mov     AL,LLC              ; write lower left corner
  2212.         stosw
  2213.         mov     CX,[BX].xwidth
  2214.         sub     CX,2
  2215.         mov     AL,BRDROW
  2216. rep     stosw
  2217.         mov     AL,LRC              ; write lower right corner
  2218.         stosw
  2219.         pop     DI
  2220. ;
  2221.         pop     ES
  2222.         pop     BP
  2223.         ret
  2224.  
  2225.  
  2226. Close_Window:
  2227.         push    ES
  2228.         mov     BX,OFFSET W1
  2229.         mov     DI,[BX].startmem    ; physical addr of screen area
  2230.         mov     ES,Pageseg          ; point to allocated memory block
  2231.         mov     SI,0000             ; start of save memory block
  2232.         mov     DX,[BX].height
  2233. resrow:
  2234.         push    DS
  2235.         mov     CX,[BX].xwidth
  2236.         mov     DS,Winseg           ; get saved memory segment
  2237.         push    DI                  ; save screen offset
  2238. rep     movsw                       ; do word to get char and attribute
  2239.         pop     DI
  2240.         pop     DS
  2241.         add     DI,BytesPL          ; next row down
  2242.         dec     DX
  2243.         jnz     resrow
  2244.         pop     ES
  2245.         ret
  2246.  
  2247. ;
  2248. ; Print a string in window.
  2249. ; Entry:
  2250. ;        CX = Row, Col position relative to start of window
  2251. ;        BX = Window pointer
  2252. ;        AH = Attribute
  2253. ;        DX = addr of string
  2254. ;
  2255. WPrint:
  2256.         push    ES
  2257.         call    GetRC               ; convert to row, col in DI
  2258.         mov     ES,Pageseg
  2259.         mov     SI,DX               ; move string address
  2260. wpwrt:
  2261.         cmp     BYTE PTR [SI],00    ; test for string terminator <NULL>
  2262.         jz      wpexit
  2263.         lodsb
  2264.         stosw
  2265.         jmp     wpwrt
  2266. wpexit:
  2267.         pop     ES
  2268.         ret
  2269.  
  2270. ;
  2271. ; Write one character and attribute to window
  2272. ;
  2273. ; Entry:
  2274. ;        CX = Row, Col position relative to start of window
  2275. ;        BX = Window pointer
  2276. ;        AH = attr
  2277. ;        AL = char
  2278. ;
  2279. WChar:
  2280.         push    ES
  2281.         call    GetRC               ; convert to row, col in DI
  2282.         mov     ES,Pageseg
  2283.         stosw
  2284.         pop     ES
  2285.         ret
  2286.  
  2287. ;
  2288. ; Convert row, col in CX to physical addr in DI
  2289. ;
  2290. GetRC:
  2291.         push    AX
  2292.         push    DX
  2293.         mov     DI,[BX].startmem    ; physical start of window memory
  2294.         add     DI,BytesPL          ; go down a row
  2295.         add     DI,2                ; go in one char, this is 0,0
  2296.         mov     AL,CH
  2297.         xor     AH,AH               ; AX = relative row number
  2298.         mul     BytesPL             ; this clobbers DX
  2299.         add     DI,AX
  2300.         mov     AX,CX               ; restore coordinates
  2301.         xor     AH,AH               ; AX = relative col number
  2302.         shl     AX,1                ; times 2 for attribute
  2303.         add     DI,AX
  2304.         pop     DX
  2305.         pop     AX
  2306.         ret
  2307.  
  2308. ;
  2309. ; WRITE HEX WORD
  2310. ; Convert a hex word to an ASCII string and display it
  2311. ; Entry:
  2312. ;        CX = Row, Col position relative to start of window
  2313. ;        BX = Window pointer
  2314. ;        AX = Word to convert
  2315. ;
  2316. Whexwd:
  2317.         push    AX
  2318.         push    BX
  2319.         push    CX
  2320.         push    DX
  2321. ;
  2322.         push    BX                  ; save window pointer
  2323.         push    CX                  ;  and row, col
  2324.         mov     DI,OFFSET Astr
  2325.         xchg    AH,AL
  2326.         call    Shexbyt
  2327.         xchg    AH,AL
  2328.         call    Shexbyt
  2329.         xor     AL,AL
  2330.         stosb                       ; make sure of terminating NULL
  2331.         mov     DX,OFFSET Astr
  2332.         pop     CX                  ; get row, col
  2333.         pop     BX                  ;  and Window ptr
  2334.         mov     AH,HIWHITE          ; set attribute
  2335.         call    WPrint
  2336. ;
  2337.         pop     DX
  2338.         pop     CX
  2339.         pop     BX
  2340.         pop     AX
  2341.         ret
  2342.  
  2343. ;
  2344. ; STORE HEX WORD
  2345. ; Convert a hex word to ASCII and store it in destination string
  2346. ; Entry:
  2347. ;        AX = Word to convert
  2348. ;        DI = destination pointer
  2349. ;
  2350. Shexwrd:
  2351.         xchg    AL,AH               ; convert upper half first
  2352.         call    Shexbyt
  2353.         xchg    AL,AH               ; convert lower half
  2354.         call    Shexbyt
  2355.         ret
  2356.  
  2357. ;
  2358. ; STORE HEX BYTE
  2359. ; Convert a hex byte to ASCII and store it in destination string
  2360. ; Entry:
  2361. ;        AL = Byte to convert
  2362. ;        DI = destination pointer
  2363. ;
  2364. Shexbyt:
  2365.         push    AX
  2366.         mov     AH,AL               ; save temporarily
  2367.         shr     AL,1
  2368.         shr     AL,1
  2369.         shr     AL,1
  2370.         shr     AL,1
  2371.         cmp     AL,10
  2372.         jb      wh1
  2373.         add     AL,07
  2374. wh1:
  2375.         add     AL,'0'
  2376.         stosb
  2377.         mov     AL,AH
  2378.         and     AL,0fh
  2379.         cmp     AL,10
  2380.         jb      wh2
  2381.         add     AL,07
  2382. wh2:
  2383.         add     AL,'0'
  2384.         stosb
  2385.         pop     AX
  2386.         ret
  2387.  
  2388. ;
  2389. ; Check if key pressed requires special handling
  2390. ;
  2391. ; Entry:
  2392. ;      AX = key pressed
  2393. ;
  2394. Disp_Key:
  2395.         mov     DI,OFFSET Keytbl    ; keys and subroutine addresses
  2396.         mov     CX,LENKTAB / 4      ; number of entries
  2397. cmpdk:
  2398.         cmp     AX,[DI]             ; is key in table?
  2399.         jz      dkexec
  2400.         add     DI,4                ; no, point to next key value
  2401.         loop    cmpdk
  2402.         clc                         ; carry clear means exit upon return
  2403.         ret
  2404. dkexec:
  2405.         add     DI,2
  2406.         call    [WORD PTR DI]
  2407.         ret
  2408.  
  2409. ;
  2410. ; Table of keys to watch for followed by the address of the routine to execute
  2411. ;
  2412. Keytbl  dw      ESCAPE,     DO_Esc
  2413.         dw      BIGS,       Do_Skey
  2414.         dw      SMALLS,     Do_Skey
  2415.         dw      BIGR,       Do_Rkey
  2416.         dw      SMALLR,     Do_Rkey
  2417.         dw      UPARROW,    Do_Up
  2418.         dw      DOWNARROW,  Do_Down
  2419.         dw      LEFTARROW,  Do_Left
  2420.         dw      RIGHTARROW, Do_Right
  2421. LENKTAB EQU     $ - Keytbl
  2422.  
  2423. ;
  2424. ; If ESC key, clear 'running flag' so Int 21h will not be stopped each time
  2425. ;
  2426. Do_Esc:
  2427.         mov     AL,00
  2428.         mov     Run_Flg,AL
  2429.         clc                         ; carry clear means exit upon return
  2430.         ret
  2431.  
  2432. ;
  2433. ; 'S' key - skip successive functions of current type.
  2434. ; Return to intercepting calls when something new comes along.
  2435. ; This is so you don't have to sit through dozens if Function '2' calls
  2436. ; while the target program outputs a string to the display.
  2437. ;
  2438. Do_Skey:
  2439.         mov     AL,0ffh
  2440.         mov     Skip_Flg,AL         ; set flag to show we should skip something
  2441.         mov     AX,AXsave           ; get current function code
  2442.         mov     Skip_Typ,AH         ; save it
  2443.         clc                         ; carry clear means exit upon return
  2444.         ret
  2445.  
  2446. ;
  2447. ; 'R' key - stop after INT 21h call and let user see result registers
  2448. ;
  2449. Do_Rkey:
  2450.         mov     AL,0ffh
  2451.         mov     Ret_Flg,AL          ; set flag
  2452.         clc                         ; carry clear means exit upon return
  2453.         ret
  2454.  
  2455. ;
  2456. ; DO_Up - move window up one line
  2457. ;
  2458. Do_Up:
  2459.         mov     BX,OFFSET W1
  2460.         call    Close_Window
  2461.         mov     AX,[BX].leftrow
  2462.         or      AX,AX               ; already at top of screen?
  2463.         jz      upexit
  2464.         dec     [BX].leftrow
  2465.         dec     [BX].rightrow
  2466.         call    Window_Parms        ; recalculate parameters
  2467. upexit:
  2468.         stc                         ; don't exit upon return
  2469.         ret
  2470.  
  2471. ;
  2472. ; DO_Down - move window down one line
  2473. ;
  2474. Do_Down:
  2475.         mov     BX,OFFSET W1
  2476.         call    Close_Window
  2477.         mov     AX,[BX].rightrow
  2478.         cmp     AX,24               ; already at bottom of screen?
  2479.         jz      dnexit
  2480.         inc     [BX].leftrow
  2481.         inc     [BX].rightrow
  2482.         call    Window_Parms        ; recalculate parameters
  2483. dnexit:
  2484.         stc                         ; don't exit upon return
  2485.         ret
  2486.  
  2487. ;
  2488. ; DO_Left - move window left one column
  2489. ;
  2490. Do_Left:
  2491.         mov     BX,OFFSET W1
  2492.         call    Close_Window
  2493.         mov     AX,[BX].leftcol
  2494.         or      AX,AX               ; already at left of screen?
  2495.         jz      lfexit
  2496.         dec     [BX].leftcol
  2497.         dec     [BX].rightcol
  2498.         call    Window_Parms        ; recalculate parameters
  2499. lfexit:
  2500.         stc                         ; don't exit upon return
  2501.         ret
  2502.  
  2503. ;
  2504. ; DO_right - move window right one column
  2505. ;
  2506. Do_Right:
  2507.         mov     BX,OFFSET W1
  2508.         call    Close_Window
  2509.         mov     AX,[BX].rightcol
  2510.         cmp     AX,79               ; already at right of screen?
  2511.         jz      rtexit
  2512.         inc     [BX].leftcol
  2513.         inc     [BX].rightcol
  2514.         call    Window_Parms        ; recalculate parameters
  2515. rtexit:
  2516.         stc                         ; don't exit upon return
  2517.         ret
  2518.  
  2519. ;
  2520. ; Wait for any key pressed
  2521. ;
  2522. Get_Key:
  2523.         push    BP                  ; just in case
  2524.         mov     AH,00
  2525.         int     16h
  2526.         pop     BP
  2527.         ret
  2528.  
  2529. ;
  2530. ; Calculate window parameters:
  2531. ;      1) Physical starting address of window
  2532. ;      2) Width of window in characters
  2533. ;      3) Height of window
  2534. ;
  2535. ; Entry:
  2536. ;      BX = window pointer
  2537. ; Exit:
  2538. ;      AX = Number of bytes contained in window
  2539. ;
  2540. Window_Parms:
  2541.         mov     AX,[BX].leftrow
  2542.         mul     BytesPL             ; multiply by bytes per line
  2543.         mov     CX,[BX].leftcol
  2544.         shl     CX,1                ; times 2 for attribute byte
  2545.         add     AX,CX
  2546.         mov     SI,AX               ; starting physical address of window
  2547.         mov     [BX].startmem,AX    ; save it for later
  2548. ;
  2549. ; Calculate size of window in bytes to allocate memory
  2550. ;
  2551.         mov     AX,[BX].rightcol
  2552.         inc     AX
  2553.         sub     AX,[BX].leftcol
  2554.         mov     [BX].xwidth,AX
  2555.         mov     CX,[BX].rightrow
  2556.         inc     CX
  2557.         sub     CX,[BX].leftrow
  2558.         mov     [BX].height,CX
  2559.         mul     CL                  ; AX = nbr of bytes of screen area
  2560.         shl     AX,1                ; times 2 to get attributes also
  2561.         ret
  2562.  
  2563. ;
  2564. ; Define format of WINDOW structure
  2565. ;
  2566. Window  STRUC
  2567.    leftrow   dw     ?
  2568.    leftcol   dw     ?
  2569.    rightrow  dw     ?
  2570.    rightcol  dw     ?
  2571.    xwidth    dw     ?
  2572.    height    dw     ?
  2573.    startmem  dw     ?
  2574. Window  ENDS
  2575.  
  2576. ;
  2577. ; Allocate and initialize WINDOW parameters
  2578. ;
  2579. W1       Window     <8, 2, 18, 74, 0, 0, 0>
  2580.  
  2581. Winseg    dw     0000                ; store segment of allocated memory
  2582.                                      ;  for saving screen data
  2583. Scrseg    dw     0000                ; base segment for screen memory
  2584. Pageseg   dw     0000                ; segment after page offset factored in
  2585. BytesPL   dw     80*2                ; number of bytes per line (char + attr)
  2586. Run_Flg   db     0ffh                ; 'running' flag
  2587. Ret_Flg   db     00                  ; 'stop on return' flag
  2588. Sw_Char   db     '/'                 ; DOS switch character
  2589. ;
  2590. ; The following two variables are initialized the way they are to skip
  2591. ; the first Int 21 call generated by 'STEPDOS' to EXEC the target program.
  2592. ;
  2593. Skip_Typ db     4bh                 ; type of function call to skip temporarily
  2594. Skip_Flg db     0ffh                ; set if function should be skipped
  2595.  
  2596. Save21   dw     ?                   ; save original Int21 vector here, IP
  2597.          dw     ?                   ;  and SEG
  2598.  
  2599. Ssave    LABEL  DWORD
  2600. SPsave   dw     ?                   ; save some of the user's registers here
  2601. SSsave   dw     ?                   ;  others will be on local stack
  2602.  
  2603. AXsave   dw     ?                   ; these will have been left on user's
  2604. DSsave   dw     ?                   ;  stack instead of local stack
  2605. CSsave   dw     ?
  2606. IPsave   dw     ?
  2607. FLsave   dw     ?
  2608. ;
  2609. ; Parameter block that will be passed to the EXEC function call (4bh) of DOS
  2610. ;
  2611. Param_Block     LABEL  WORD
  2612. SegEnv   dw     ?                   ; segment addr of environment string
  2613. SegCmd   dw     ?                   ; segmented ptr to command line
  2614.          dw     ?
  2615. FCBptr1  dw     ?                   ; segmented ptr to first FCB
  2616.          dw     ?
  2617. FCBptr2  dw     ?                   ; segmented ptr to second FCB
  2618.          dw     ?
  2619.  
  2620. ;
  2621. ; File name that will be passed to the EXEC function call of DOS
  2622. ;
  2623. Filename db     128 dup (0)
  2624. FNsize   dw     0
  2625. ;
  2626. ; Command line from PSP:80h will be copied here to work from
  2627. ;
  2628. PSPstr   db     128 dup (0)
  2629.  
  2630. ;
  2631. ; Command Line that will be passed to the EXEC function call of DOS
  2632. ;
  2633. CLstr    db     128 dup (0)
  2634.  
  2635. ;
  2636. ; Two FCB's that will be passed to the EXEC function call of DOS
  2637. ;
  2638. FCB1     db     0
  2639.          db     11 dup (' ')
  2640.          db     0, 0, 0, 0
  2641.  
  2642. FCB2     db     0
  2643.          db     11 dup (' ')
  2644.          db     0, 0, 0, 0
  2645.  
  2646. COMstr  db      '.COM'
  2647. EXEstr  db      '.EXE'
  2648. ;
  2649. INITmsg  db     'STEPDOS Version 1.1'
  2650.          db     CR
  2651.          db     LF
  2652.          db     '$'
  2653.  
  2654. Memerr   db     CR
  2655.          db     LF
  2656.          db     'Error Allocating Window Memory$'
  2657.  
  2658. Execmsg  db     CR
  2659.          db     LF
  2660.          db     'Unable to execute target program$'
  2661.  
  2662. Findmsg  db     CR
  2663.          db     LF
  2664.          db     'Unable to find target program '
  2665.          db     27h                 ; opening quote
  2666.          db     '$'
  2667.  
  2668. Umsg     db     CR
  2669.          db     LF
  2670.          db     'Usage: STEPDOS filename$'
  2671.  
  2672. RegStr1  db     ' AX   BX   CX   DX   DI   SI   BP   SP'
  2673.          db     '   DS   ES   SS   CS   IP   FL'
  2674.          db     0
  2675.  
  2676. RegStr2  db     '---- ---- ---- ---- ---- ---- ---- ----'
  2677.          db     ' ---- ---- ---- ---- ---- ----'
  2678.          db     0
  2679.  
  2680. HlpStr1  db     'kip Current Func'
  2681.          db     0
  2682.  
  2683. HlpStr2  db     'eturn Code'
  2684.          db     0
  2685.  
  2686. HlpStr3  db     ' - Non Stop'
  2687.          db     0
  2688.  
  2689. HlpStr4  db     ' - Move Window'
  2690.          db     0
  2691.  
  2692. HlpStr5  db     'Press Any Key To Continue'
  2693.          db     0
  2694.  
  2695. Astr     db     32 dup (0)          ; string for converting ASCII characters
  2696.  
  2697. ;
  2698. ; Local Program Stack Area
  2699. ;
  2700.          db     128 dup (?)
  2701. Pstack   EQU    $
  2702.  
  2703. ;
  2704. ; Target Stack Area
  2705. ;
  2706.          db     128 dup (?)
  2707. Tstack   EQU    $
  2708.  
  2709.  
  2710. IF TESTING
  2711.  
  2712. Istr     db     128 dup (' ')
  2713.  
  2714. Ostr     db     'Output String'
  2715.          db     0
  2716. ENDIF
  2717.  
  2718.  
  2719. PRSIZE  EQU     $
  2720.  
  2721. Code    ENDS
  2722.  
  2723.         END     Main
  2724.  
  2725.