home *** CD-ROM | disk | FTP | other *** search
- ;
- ; ***********************************************************
- ; * *
- ; * S T E P D O S *
- ; * *
- ; * Rev 1.0 *
- ; * *
- ; * Nov 7, 1987 *
- ; * *
- ; * Mike Parker - CIS 70270,161 *
- ; * *
- ; * This program allows you to step through the execution *
- ; * of another program by intercepting all calls to DOS *
- ; * INT 21H. A window will pop up displaying all register *
- ; * values and a short description of the DOS function *
- ; * being called. Program execution will continue when *
- ; * you press a key. You can optionally break again after *
- ; * the DOS function completes so you can see the result *
- ; * code in the AX register along with important flags. *
- ; * *
- ; ***********************************************************
- ;
- ; To run, type STEPDOS <filename>
- ; where <filename> is the full pathname of an EXE or COM file.
- ;
-
- PAGE 60,132
- TITLE 'Step DOS Calls'
- NAME STEPDOS
-
-
- TESTING EQU 0
-
- BG EQU 10H ; BG sets background color (10h = BLUE)
-
- BLACK EQU 00H + BG
- BLUE EQU 01H + BG
- GREEN EQU 02H + BG
- CYAN EQU 03H + BG
- RED EQU 04H + BG
- MAGENTA EQU 05H + BG
- BROWN EQU 06H + BG
- WHITE EQU 07H + BG
- GRAY EQU 08H + BG
- LTBLUE EQU 09H + BG
- LTGREEN EQU 0AH + BG
- LTCYAN EQU 0BH + BG
- LTRED EQU 0CH + BG
- LTMAGENTA EQU 0DH + BG
- YELLOW EQU 0EH + BG
- HIWHITE EQU 0FH + BG
- ;
- CR EQU 13
- LF EQU 10
- BIGR EQU 1352H ; 'R' key
- SMALLR EQU 1372H ; 'r'
- BIGS EQU 1F53H ; 'S' key
- SMALLS EQU 1F73H ; 's'
- ESCAPE EQU 011BH
- HOME EQU 4700H
- UPARROW EQU 4800H
- PGUP EQU 4900H
- LEFTARROW EQU 4B00H
- RIGHTARROW EQU 4D00H
- XEND EQU 4F00H
- DOWNARROW EQU 5000H
- PGDN EQU 5100H
- ;
- BLANK EQU 32
- BRDROW EQU 205
- BRDCOL EQU 186
- ULC EQU 201
- URC EQU 187
- LLC EQU 200
- LRC EQU 188
- ;
- REGBX EQU 00 ; offsets on saved register stack
- REGCX EQU 02
- REGDX EQU 04
- REGDI EQU 06
- REGSI EQU 08
- REGBP EQU 10
- REGES EQU 12
- REGFL EQU 14
- ;
- IF TESTING
- INT21OFF EQU 0e0h*4 ; during testing an unused INT is used
- ELSE
- INT21OFF EQU 21h*4
- ENDIF
-
- Code SEGMENT PUBLIC PARA 'CODE'
-
- ASSUME CS:Code, DS:Code
-
- Main: ; starting point
- mov DI,DS
- mov BX,2
- mov SI,[BX] ; paragraphs of memory in system from PSP
- sub SI,DI ; paragraphs beyond segment
- cmp SI,1000h ; more than 64K available ?
- jb main_1
- mov SI,1000h ; yes, only use 64K
- main_1:
- add SI,DI ; si = DS + number paragraphs in DS
- mov BX,ES ; bx = PSP base
- sub BX,SI
- neg BX ; bx = number of paragraphs needed
- mov AH,4ah ; modify memory block size
- int 21h
- ;
- ; Copy command line from PSP to local area
- ;
- mov AX,CS
- mov ES,AX ; change ES to be local area
- ;
- mov SI,80h
- mov CL,[SI] ; get command line character count
- or CL,CL ; zero char count in cmd line?
- jnz notzcl
- mov AX,CS
- mov DS,AX
- mov DX,OFFSET Umsg
- mov AH,9
- int 21h
- jmp exit
- notzcl:
- xor CH,CH
- inc SI
- mov DI,OFFSET PSPstr
- rep movsb ; copy command line
- xor AL,AL
- stosb ; <NULL> terminator at end
- ;
- mov BX,002ch
- mov BX,[BX] ; get segment addr of environment from PSP
- ;
- mov AX,CS
- mov DS,AX
- mov SegEnv,BX ; save in EXEC control block
- ;
- mov DX,OFFSET INITmsg
- mov AH,9
- int 21h
- ;
- ; Calculate starting address on screen for window
- ;
- mov BX,OFFSET W1 ; window parameters
- mov AX,[BX].leftrow
- mul BytesPL ; multiply by bytes per line
- mov CX,[BX].leftcol
- shl CX,1 ; times 2 for attribute byte
- add AX,CX
- mov SI,AX ; starting physical address of window
- mov [BX].startmem,AX ; save it for later
- ;
- ; Calculate size of window in bytes to allocate memory
- ;
- mov AX,[BX].rightcol
- inc AX
- sub AX,[BX].leftcol
- mov [BX].xwidth,AX
- mov CX,[BX].rightrow
- inc CX
- sub CX,[BX].leftrow
- mov [BX].height,CX
- mul CL ; AX = nbr of bytes of screen area
- shl AX,1 ; times 2 to get attributes also
- ;
- ; Do DOS call to allocate memory
- ;
- mov CL,4
- shr AX,CL ; divide by 16 to get # paragraphs
- inc AX ; handle any remainder
- mov BX,AX
- mov AH,48h ; 'allocate memory' DOS call
- int 21h
- mov Winseg,AX ; save returned segment
- jnc cpynam
- mov DX,OFFSET Memerr ; ERROR - display string
- mov AH,9
- int 21h
- jmp exit ; and terminate
- ;
- ; Copy target program name
- ;
- cpynam:
- mov SI,OFFSET PSPstr + 1
- mov DI,OFFSET Filename
- xor CX,CX ; zero char count
- fnlp:
- cmp BYTE PTR [SI],' ' ; look for <SP>
- jz fndn
- cmp BYTE PTR [SI],00 ; or <NULL> terminator
- jz fndn
- movsb
- inc CX ; count number of filename char's
- jmp fnlp
- fndn:
- or CX,CX
- jnz gotfn
- mov DX,OFFSET Findmsg ; error if zero filename length
- mov AH,9
- int 21h
- jmp freemem
- gotfn:
- xor AL,AL
- stosb
- mov FNsize,CX
- ;
- ; Copy command line string
- ; SI -> first parameter after filename
- ;
- mov DI,OFFSET CLstr + 1
- xor CX,CX ; zero char count
- cllp:
- cmp BYTE PTR [SI],00 ; look for <NULL> terminator
- jz dncl
- movsb
- inc CX ; count number of cmd line char's
- jmp cllp
- dncl:
- xor AL,AL ; store <NULL>
- stosb
- mov AL,CR ; and <CR>
- stosb
- mov CLstr,CL ; store cmd line count
- ;
- ; Build EXEC control block
- ;
- mov SegCmd,OFFSET CLstr
- mov SegCmd+2,DS
- mov FCBptr1,OFFSET FCB1
- mov FCBptr1+2,DS
- mov FCBptr2,OFFSET FCB2
- mov FCBptr2+2,DS
- ;
- ; Parse first parameter
- ;
- mov SI,OFFSET CLstr + 1
- mov DI,OFFSET FCB1
- mov AL,01 ; scan past separators
- mov AH,29h
- int 21h
- ;
- ; Parse second parameter
- ;
- mov DI,OFFSET FCB2
- mov AL,01 ; scan past separators
- mov AH,29h
- int 21h
- ;
- ; Check for '.' in target program filename
- ;
- mov DI,OFFSET Filename
- mov CX,FNsize ; get program filename size
- mov AL,'.'
- repne scasb
- jz fndext
- ;
- ; No extention found, try appending '.COM'
- ;
- mov SI,OFFSET COMstr
- mov DI,OFFSET Filename
- add DI,FNsize
- mov CX,4
- rep movsb
- ;
- ; Try to OPEN the target program to see if it exists before we change
- ; the Int 21h vector and EXEC it.
- ;
- mov AH,3dh
- mov AL,00 ; access code
- mov DX,OFFSET Filename
- int 21h
- jnc clsfile ; jump if file found
- ;
- ; OPEN with '.COM' extention failed, try appending '.EXE'
- ;
- mov SI,OFFSET EXEstr
- mov DI,OFFSET Filename
- add DI,FNsize
- mov CX,4
- rep movsb
- ;
- ; Try to OPEN the '.EXE' version of the file
- ;
- fndext:
- mov AH,3dh
- mov AL,00 ; access code
- mov DX,OFFSET Filename
- int 21h
- jnc clsfile
- mov DX,OFFSET Findmsg ; not found
- mov AH,9
- int 21h
- jmp freemem
- ;
- ; Found the file, now close it and do EXEC function
- ;
- clsfile:
- mov BX,AX ; move file handle
- mov AH,3eh
- int 21h
- ;
- ; Redirect INT 21h
- ;
- redirect:
- push ES
- cli
- mov AX,0
- mov ES,AX
- mov AX,OFFSET New21
- xchg AX,ES:[INT21OFF]
- mov Save21,AX
- mov AX,CS
- xchg AX,ES:[INT21OFF+2]
- mov Save21+2,AX
- sti
- pop ES
- ;
- ; Execute target program
- ;
- mov DX,OFFSET Filename
- mov BX,OFFSET Param_Block
- mov AH,4bh
- mov AL,0
- mov SP,OFFSET Tstack
- int 21h
- jnc execdn
- ;
- ; Failed to execute target program. Display message and quit
- ;
- mov AX,CS
- mov DS,AX
- mov DX,OFFSET Execmsg
- mov AH,9
- int 21h
- ;
- execdn:
- mov AX,CS ; restore segment registers
- mov DS,AX
- mov ES,AX
- mov SS,AX
- mov SP,OFFSET Pstack
- ;
- ; Restore INT 21h vector
- ;
- cli
- mov AX,0
- mov ES,AX
- mov AX,Save21
- mov ES:[INT21OFF],AX
- mov AX,Save21+2
- mov ES:[INT21OFF+2],AX
- sti
- ;
- ; Free allocated memory from window save area
- ;
- freemem:
- mov ES,Winseg
- mov AH,49h
- int 21h
- exit:
- mov AH,4ch ; terminate process
- mov AL,00
- int 21h ; won't return
-
- ;
- ; INT 21h will be redirected to here
- ;
- New21:
- push AX ; use USERS'S stack for first 2 words
- push DS
- ;
- mov AX,CS ; now switch to internal stack
- mov DS,AX
- mov SSsave,SS
- mov SPsave,SP
- mov SS,AX
- mov SP,OFFSET Pstack
- ;
- pushf
- push ES
- push BP
- push SI
- push DI
- push DX
- push CX
- push BX
- mov BP,SP ; save base pointer to display reg's
- mov ES,AX
- mov AL,Run_Flg
- test AL,0ffh ; should we stop and display?
- jnz runit
- jmp norun ; no, restore registers and leave
- runit:
- cld ; clear direction flag for string operations
- call Get_User_Regs ; recover registers left on user's stack
- ;
- mov AL,Skip_Flg
- test AL,0ffh ; skip certain functions?
- jz noskip ; no, continue
- mov AX,AXsave ; get USER's AX register with function code
- cmp AH,Skip_Typ ; compare upper half to type to skip
- jnz clrskip
- jmp norun ; don't want to break on this one again
- clrskip:
- mov AL,00 ; skip flag was set but this is new
- mov Skip_Flg,AL ; function, so break from now on
- noskip:
- call Open_Window
- call Show_Regs
- call Show_Help
- call Disp_Text ; Display description string of DOS function
- ;
- call Get_Key ; wait for a key pressed
- call Disp_Key ; dispatch to key handler
- call Close_Window
- norun:
- pop BX
- pop CX
- pop DX
- pop DI
- pop SI
- pop BP
- pop ES
- popf
- mov SP,SPsave
- mov SS,SSsave
- pop DS
- pop AX
-
- IFE TESTING
- pushf
- call CS:[DWORD PTR Save21]
- ENDIF
-
- push AX ; use USERS'S stack for first 2 words
- push DS
- ;
- mov AX,CS ; now switch to internal stack
- mov DS,AX
- mov SSsave,SS
- mov SPsave,SP
- mov SS,AX
- mov SP,OFFSET Pstack
- ;
- pushf
- push ES
- push BP
- push SI
- push DI
- push DX
- push CX
- push BX
- mov BP,SP ; save base pointer to display reg's
- mov ES,AX
- cld ; clear direction flag for string operations
- call Get_User_Regs ; recover registers left on user's stack
- xor AL,AL
- xchg AL,Ret_Flg ; read value and clear flag for next time
- test AL,0ffh ; is flag set to display return value?
- jz nostop
- ;
- call Open_Window
- call Show_Regs
- call Disp_Ret ; display return code in AX and flags
- call Get_Key ; wait for a key pressed
- call Close_Window
- nostop:
- pop BX
- pop CX
- pop DX
- pop DI
- pop SI
- pop BP
- pop ES
- popf
- mov SP,SPsave
- mov SS,SSsave
- pop DS
- pop AX
- retf 2
-
- ;
- ; Display return code in AX, carry and zero flags
- ;
- Disp_Ret:
- mov DX,OFFSET RCStr
- mov DI,14
- mov AX,AXsave
- call OutWord
- ;
- mov DX,OFFSET CFStr
- mov DI,13
- add DI,DX
- mov AL,'0'
- test FLsave,0001 ; carry flag is least significant bit
- jz dcy
- inc AL ; carry was set so change to '1'
- dcy:
- mov [DI],AL ; store it in string
- add CX,0015h ; move cursor position
- mov BX,OFFSET W1
- mov AH,HIWHITE
- call WPrint
- ;
- mov DX,OFFSET ZFStr
- mov DI,12
- add DI,DX
- mov AL,'0'
- test FLsave,0040h ; test zero flag
- jz dzf
- inc AL ; zero was set so change to '1'
- dzf:
- mov [DI],AL ; store it in string
- add CX,0010h ; move cursor position
- mov BX,OFFSET W1
- mov AH,HIWHITE
- call WPrint
- ;
- mov CX,0816h ; display some help
- mov DX,OFFSET HlpStr4
- mov AH,YELLOW
- call WPrint
- ret
-
- RCStr db 'Return Code = XXXXH'
- db 0
-
- CFStr db 'Carry Flag = X'
- db 0
-
- ZFStr db 'Zero Flag = X'
- db 0
-
- ;
- ; Recover registers on USER'S stack
- ;
- Get_User_Regs:
- push ES
- les BX,Ssave
- mov AX,ES:[BX] ; get DS
- mov DSsave,AX
- mov AX,ES:[BX+2] ; get AX
- mov AXsave,AX
- mov AX,ES:[BX+4] ; get IP
- mov IPsave,AX
- mov AX,ES:[BX+6] ; get CS
- mov CSsave,AX
- mov AX,[BP+REGFL] ; get FLAGS off local stack
- mov FLsave,AX
- pop ES
- ret
-
- ;
- ; Display register names in window
- ;
- Show_Regs:
- mov BX,OFFSET W1 ; window
- mov CX,0001h ; cursor position - row, col
- mov DX,OFFSET RegStr1 ; message address
- mov AH,YELLOW ; attribute
- call WPrint
- ;
- add CX,0100h ; go down one row
- mov DX,OFFSET RegStr2
- mov AH,WHITE
- call WPrint
- ;
- ; Display register values
- ;
- add CX,0100h ; down a row
- mov AX,AXsave ; get user's AX
- call Whexwd ; display hex word
- ;
- push BP ; save base pointer for string display
- mov DX,6 ; number of registers to show this loop
- disreg:
- add CX,0005h ; move to next register field
- mov AX,[BP]
- call Whexwd ; display hex word
- add BP,2
- dec DX
- jnz disreg
- ;
- add CX,0005h ; move to next register field
- mov AX,SPsave ; display SP
- add AX,4 ; add for 2 pushes we did
- call Whexwd
- ;
- add CX,0005h ; move to next register field
- mov AX,DSsave ; display DS
- call Whexwd
- ;
- add CX,0005h ; display ES
- mov AX,[BP]
- call Whexwd
- ;
- add CX,0005h
- mov AX,SSsave ; display SS
- call Whexwd
- ;
- add CX,0005h
- mov AX,CSsave ; display CS
- call Whexwd
- ;
- add CX,0005h
- mov AX,IPsave ; display IP
- call Whexwd
- ;
- add CX,0005h
- mov AX,FLsave ; display FLAGS
- call Whexwd
- pop BP ; restore base pointer so display routines
- ; can use it
- ret
-
- ;
- ; Display HELP in Window
- ;
- Show_Help:
- mov CX,0801h ; cursor position - row, col
- mov AH,LTRED ; attribute for char
- mov AL,'S'
- call WChar ; write one character with attribute
- ;
- add CX,0001h ; add 1 to column number
- mov DX,OFFSET HlpStr1 ; message address
- mov AH,WHITE
- call WPrint
- ;
- add CX,0017h ; move column number
- mov AH,LTRED ; attribute for char
- mov AL,'R'
- call WChar ; write one character with attribute
- ;
- add CX,0001h ; move column number
- mov DX,OFFSET HlpStr2
- mov AH,WHITE
- call WPrint
- ;
- add CX,000dh
- mov AH,LTRED
- mov AL,'E'
- call WChar
- ;
- add CX,0001h
- mov AH,LTRED
- mov AL,'S'
- call WChar
- ;
- add CX,0001h
- mov AH,LTRED
- mov AL,'C'
- call WChar
- ;
- add CX,0001h
- mov DX,OFFSET HlpStr3
- mov AH,WHITE
- call WPrint
- ret
-
- ;
- ; HextoDec converts a word in AX to an ASCII string
- ; Entry:
- ; AX = word to convert
- ; Exit:
- ; SI = Pointer to last two character of ASCII string in 'Astr'
- ;
- HextoDec:
- push AX
- push CX
- push DX
- push DI
- ;
- mov DI,OFFSET Astr
- mov CX,10000
- xor DX,DX
- div CX ; num / 10000
- add AL,'0'
- stosb
- mov AX,DX
- mov CX,1000
- xor DX,DX
- div CX ; num / 1000
- add AL,'0'
- stosb
- mov AX,DX
- mov CX,100
- xor DX,DX
- div CX ; num / 100
- add AL,'0'
- stosb
- mov AX,DX
- mov CX,10
- xor DX,DX
- div CX ; num / 10
- add AL,'0'
- stosb
- mov AX,DX
- add AL,'0'
- stosb
- xor AL,AL ; <NULL> terminator in string
- stosb
- sub DI,3 ; back up pointer
- mov SI,DI
- ;
- pop DI
- pop DX
- pop CX
- pop AX
- ret
-
- ;
- ; Display the text description of the current DOS function code
- ;
- Disp_Text:
- mov AX,AXsave ; get user's function code
- cmp AH,63h ; is it in range?
- jnb not_fnd ; jump if no
- mov DI,OFFSET FCtbl
- mov CX,LENFC / 6 ; number of entries
- cmpdt:
- cmp AH,[DI+1] ; is this the right function?
- jz dtexec
- add DI,6 ; no, point to next
- loop cmpdt
- not_fnd:
- mov DX,OFFSET STRUN
- call Disp_Str
- ret
-
- dtexec:
- mov DX,[DI+2] ; get pointer to string
- call [WORD PTR DI+4] ; go to display routine
- ret
-
- ;
- ; Display string of DOS function code description
- ;
- ; Entry:
- ; DX = pointer to string
- ;
- Disp_Str:
- mov CX,0501h
- mov BX,OFFSET W1
- mov AH,HIWHITE
- call WPrint
- ret
-
- ;
- ; Only one string must be inserted.
- ; It is pointed to by user's DS:DX.
- ; Entry:
- ; DX = text string containing description of function call
- ; DI = offset within local string (DX) to put user's (DS:DX)
- ; CX = max length before you will hit right side of Window
- ;
- One_String:
- add DI,DX
- push DS
- mov DS,DSsave
- mov SI,[BP+REGDX] ; get USER's DS:DX value
- rep movsb ; copy user's memory to text string
- pop DS
- call Disp_Str
- ret
-
- ;
- ; Convert users's DS and DX to ASCII, imbed them in target string
- ; Entry:
- ; DX = pointer to string
- ; DI = offset where to put converted DS:DX
- ;
- OutDSDX:
- add DI,DX
- mov AX,DSsave ; get user's DS
- call Shexwrd
- inc DI ; skip past ':'
- mov AX,[BP+REGDX] ; get user's DX
- call Shexwrd
- call Disp_Str
- ret
-
- ;
- ; Convert word in AX to ASCII, imbed it in target string
- ; Entry:
- ; AX = word to convert
- ; DX = pointer to string
- ; DI = offset where to put converted AX
- ;
- OutWord:
- add DI,DX
- call Shexwrd
- call Disp_Str
- ret
-
- ;
- ; Convert 'AL' to ASCII and imbed it in target string
- ; Entry:
- ; DX = target string
- ; DI = offset to put converted 'AL'
- ; AL = value to convert
- ;
- OutByte:
- add DI,DX
- call Shexbyt
- call Disp_Str
- ret
-
- ;
- ; Routines to build string for display - some values need to be filled in
- ;
- ; Entry:
- ; DX = pointer to string
- ;
- Disp_02:
- Disp_04:
- Disp_05:
- mov DI,DX
- add DI,22 ; offset this many into string
- mov AX,[BP+REGDX] ; DL register has char to output
- call Shexbyt ; convert it to ASCII
- mov [DI+8],AL ; show hex byte
- call Disp_Str
- ret
-
- ;
- ; Direct Keyboard/Display I/O
- ;
- Disp_06:
- call Disp_Str
- mov AX,[BP+REGDX] ; DL register has I/O type
- mov DX,OFFSET STR06I
- cmp AL,0ffh ; input character?
- jz d06io
- mov DX,OFFSET STR02 ; no, output character in 'DL'
- mov DI,DX
- add DI,22 ; offset this many into string
- call Shexbyt ; convert it to ASCII
- mov [DI+8],AL ; show hex byte
- d06io:
- add CX,0015h
- mov BX,OFFSET W1
- mov AH,HIWHITE
- call WPrint
- ret
-
- ;
- ; Display String
- ; Entry:
- ; DX = pointer to string
- ;
- Disp_09:
- Disp_39:
- Disp_3a:
- Disp_3b:
- Disp_3c:
- Disp_3d:
- Disp_41:
- Disp_5a:
- Disp_5b:
- mov DI,18 ; offset where (DS:DX) goes within string
- mov cx,52 ; max number of char's to fit in window
- call One_String
- ret
-
- Disp_0a:
- Disp_23:
- mov DI,27
- call OutDSDX
- ret
-
- ;
- ; Clear Keyboard and Do Function
- ;
- Disp_0c:
- mov DI,31
- mov AX,AXsave ; AL register has function number
- call OutByte
- ret
-
- ;
- ; Select Disk
- ;
- Disp_0e:
- mov DI,12
- mov AX,[BP+REGDX] ; DL register has char to output
- call OutByte
- ret
-
- ;
- ; Open File Using FCB
- ;
- Disp_0f:
- mov DI,23
- call OutDSDX
- ret
-
- ;
- ; Close File Using FCB
- ;
- Disp_10:
- mov DI,24
- call OutDSDX
- ret
-
- ;
- ; Search For First Matching File Using FCB
- ;
- Disp_11:
- mov DI,44
- call OutDSDX
- ret
-
- ;
- ; Search For Next Matching File Using FCB
- ;
- Disp_12:
- mov DI,43
- call OutDSDX
- ret
-
- ;
- ; Delete File Using FCB
- ; Create File Using FCB
- ; Rename File Using FCB
- ;
- Disp_13:
- Disp_16:
- Disp_17:
- mov DI,25
- call OutDSDX
- ret
-
- ;
- ; Read Sequential File Record Using FCB
- ;
- Disp_14:
- mov DI,41
- call OutDSDX
- ret
-
- ;
- ; Write Sequential File Record Using FCB
- ;
- Disp_15:
- mov DI,42
- call OutDSDX
- ret
-
- ;
- ; Set Disk Transfer Address
- ;
- Disp_1a:
- mov DI,29
- call OutDSDX
- ret
-
- ;
- ; Get FAT Information For Drive
- ;
- Disp_1c:
- mov DI,30
- mov AX,[BP+REGDX] ; DL register has drive number
- call OutByte
- ret
-
-
- ;
- ; Read Random File Record Using FCB
- ; Set Random Record Field Using FCB
- ;
- Disp_21:
- Disp_24:
- mov DI,37
- call OutDSDX
- ret
-
- ;
- ; Write Random File Record Using FCB
- ;
- Disp_22:
- mov DI,38
- call OutDSDX
- ret
-
- ;
- ; Set Interrupt Vector
- ;
- Disp_25:
- mov DI,DX
- add DI,21
- mov AX,AXsave ; AL has interrupt vector number
- call Shexbyt
- mov DI,28
- call OutDSDX
- ret
-
- ;
- ; Create New Program Segment
- ;
- Disp_26:
- mov DI,38
- mov AX,[BP+REGDX] ; get user's DX
- call OutWord
- ret
-
- ;
- ; Read Random File Records
- ;
- Disp_27:
- mov DI,DX
- add DI,5
- mov AX,[BP+REGCX] ; CX register has record count
- call Shexwrd
- mov DI,44
- call OutDSDX
- ret
-
- ;
- ; Write Random File Records
- ;
- Disp_28:
- mov DI,DX
- add DI,6
- mov AX,[BP+REGCX] ; CX register has record count
- call Shexwrd
- mov DI,45
- call OutDSDX
- ret
- ;
- ; Parse Filename
- ;
- Disp_29:
- mov DI,18 ; offset where (DS:SI) goes within string
- mov cx,52 ; max number of char's to fit in window
- add DI,DX
- push DI ; save for scan later
- push DS
- mov DS,DSsave
- mov SI,[BP+REGSI] ; get USER's DS:SI value
- rep movsb ; copy user's memory to text string
- pop DS
- ;
- ; look for <CR> in string and put <NULL> terminator there
- ;
- pop DI
- mov AL,CR
- mov cx,52
- repne scasb
- jnz dpf
- dec DI
- xor AL,AL
- mov [DI],AL
- dpf:
- call Disp_Str
- ret
-
- ;
- ; Set Date
- ;
- Disp_2b:
- mov DI,DX
- add DI,22
- mov AX,[BP+REGDX] ; DX register has month/day
- mov AL,AH
- xor AH,AH
- call HextoDec ; convert month
- movsb
- movsb
- inc DI ; skip past '/'
- mov AX,[BP+REGDX]
- xor AH,AH
- call HextoDec ; convert day
- movsb
- movsb
- inc DI ; skip past '/'
- mov AX,[BP+REGCX]
- call HextoDec ; convert year
- movsb
- movsb
- call Disp_Str
- ret
-
- ;
- ; Set Time
- ;
- Disp_2d:
- mov DI,DX
- add DI,33
- mov AX,[BP+REGCX] ; CX register has hours/minutes
- mov AL,AH
- xor AH,AH
- call HextoDec ; convert hours
- movsb
- movsb
- inc DI ; skip past ':'
- mov AX,[BP+REGCX]
- xor AH,AH
- call HextoDec ; convert minutes
- movsb
- movsb
- inc DI ; skip past ':'
- mov AX,[BP+REGDX] ; DX has seconds/hundreds of seconds
- mov AL,AH
- xor AH,AH
- call HextoDec ; convert seconds
- movsb
- movsb
- inc DI ; skip past ':'
- mov AX,[BP+REGDX]
- xor AH,AH
- call HextoDec ; convert hundreds
- movsb
- movsb
- call Disp_Str
- ret
-
- ;
- ; Set Disk Write Verification
- ;
- Disp_2e:
- mov DI,DX
- add DI,28
- mov AX,AXsave ; AL register has verify switch
- mov SI,OFFSET OFFstr
- cmp AL,00 ; AL = 0 means OFF
- jz verptr
- mov SI,OFFSET ONstr
- cmp AL,01 ; AL = 1 means ON
- jz verptr
- mov SI,OFFSET Blanks3 ; unknown code
- verptr:
- mov CX,3
- rep movsb
- call Disp_Str
- ret
-
- ;
- ; Get/Set Control-Break Status
- ;
- Disp_33:
- mov AX,AXsave ; AL register has get/set switch
- cmp AL,01 ; AL = 1 for SET
- jz setcbs
- cmp AL,00 ; AL = 0 for GET
- jnz unk33 ; jump if unknown code
- mov DX,OFFSET STR33G
- unk33:
- call Disp_Str
- ret
-
- setcbs:
- mov DX,OFFSET STR33S ; point to 'SET' string
- mov DI,DX
- add DI,25
- mov AX,[BP+REGDX] ; DL has set code
- mov SI,OFFSET OFFstr
- cmp AL,00 ; AL = 00 means OFF
- jz gscbs
- mov SI,OFFSET ONstr
- cmp AL,01 ; AL = 01 means ON
- jz gscbs
- mov SI,OFFSET Blanks3
- gscbs:
- mov CX,3
- rep movsb
- call Disp_Str
- ret
-
- ;
- ; Get Interrupt Vector
- ;
- Disp_35:
- mov DI,21
- mov AX,AXsave ; AL has interrupt vector number
- call OutByte
- ret
-
- ;
- ; Get Disk Free Space On Drive
- ;
- Disp_36:
- mov DI,29
- mov AX,[BP+REGDX] ; DL register has drive code
- call OutByte
- ret
-
- ;
- ; Close File Handle
- ;
- Disp_3e:
- mov DI,18
- mov AX,[BP+REGBX] ; BX register has file handle
- call OutWord
- ret
-
- ;
- ; Duplicate File Handle
- ;
- Disp_45:
- mov DI,22
- mov AX,[BP+REGBX] ; BX register has file handle
- call OutWord
- ret
-
- ;
- ; Read From File or Device
- ;
- Disp_3f:
- mov DI,DX
- add DI,5
- mov AX,[BP+REGCX] ; CX has number of bytes to read
- call Shexwrd
- mov DI,37
- mov AX,[BP+REGBX] ; BX has file handle
- call OutWord
- ret
-
- ;
- ; Write To File or Device
- ;
- Disp_40:
- mov DI,DX
- add DI,6
- mov AX,[BP+REGCX] ; CX has number of bytes to read
- call Shexwrd
- mov DI,36
- mov AX,[BP+REGBX] ; BX has file handle
- call OutWord
- ret
-
- ;
- ; Move File Pointer
- ;
- Disp_42:
- mov DI,DX
- add DI,17
- mov AX,[BP+REGBX] ; BX register has file handle
- call Shexwrd
- add DI,13
- mov AX,[BP+REGCX] ; CX has upper half of offset
- call Shexwrd
- inc DI ; skip past ':'
- mov AX,[BP+REGDX] ; CX has lower half of offset
- call Shexwrd
- add DI,7
- mov AX,AXsave ; AL has method code
- mov SI,OFFSET BOFstr
- cmp AL,00 ; beginning of file?
- jz mvptr
- mov SI,OFFSET CURstr
- cmp AL,01 ; current location?
- jz mvptr
- mov SI,OFFSET EOFstr
- cmp AL,02 ; end of file?
- jz mvptr
- mov SI,OFFSET Blanks17 ; unknown
- mvptr:
- mov cx,17 ; string length
- rep movsb
- call Disp_Str
- ret
-
- ;
- ; Get/Set file attributes
- ;
- Disp_43:
- mov AX,AXsave ; user's AX has get/set flag
- cmp AL,00 ; 'get' code?
- jz fgptr
- cmp AL,01 ; 'set' code?
- jz fsptr
- call Disp_Str ; unknown code
- ret
- fgptr:
- mov DX,OFFSET STR43G ; point to GET string
- jmp SHORT faptr
- ;
- fsptr:
- mov DX,OFFSET STR43S ; point to SET string
- faptr:
- mov DI,18
- mov cx,52 ; max number of char's to fit in window
- call One_String
- ret
-
- ;
- ; I/O Control For Devices
- ;
- Disp_44:
- mov AX,AXsave
- cmp AL,00
- jz jd440
- cmp AL,01
- jz jd441
- cmp AL,02
- jz jd442
- cmp AL,03
- jz jd443
- cmp AL,04
- jz jd444
- cmp AL,05
- jz jd445
- cmp AL,06
- jz jd446
- cmp AL,07
- jz jd447
- cmp AL,08
- jz jd448
- cmp AL,11
- jz jd4411
- call Disp_Str ; unknown code
- ret
-
- jd440: jmp d440
- jd441: jmp d441
- jd442: jmp d442
- jd443: jmp d443
- jd444: jmp d444
- jd445: jmp d445
- jd446: jmp d446
- jd447: jmp d447
- jd448: jmp d448
- jd4411: jmp d4411
-
- d440:
- mov DX,OFFSET STR440 ; Get Info For Device
- mov DI,20
- mov AX,[BP+REGBX] ; BX has file handle
- call OutWord
- ret
- ;
- d441:
- mov DX,OFFSET STR441 ; Set Info For Device
- mov DI,DX
- add DI,20
- mov AX,[BP+REGBX] ; BX has file handle
- call Shexwrd
- mov DI,29
- mov AX,[BP+REGDX] ; DX has device information
- call OutWord
- ret
- ;
- d442:
- mov DX,OFFSET STR442 ; Read From Drive Control Channel
- mov DI,DX
- add DI,5
- mov AX,[BP+REGCX] ; CX has byte count
- call Shexwrd
- mov DI,52
- mov AX,[BP+REGBX] ; BX has file handle
- call OutWord
- ret
- ;
- d443:
- mov DX,OFFSET STR443 ; Write To Drive Control Channel
- mov DI,DX
- add DI,6
- mov AX,[BP+REGCX] ; CX has byte count
- call Shexwrd
- mov DI,51
- mov AX,[BP+REGBX] ; BX has file handle
- call OutWord
- ret
- ;
- d444:
- mov DX,OFFSET STR444 ; Read From Control Channel of Drive
- mov DI,DX
- add DI,5
- mov AX,[BP+REGCX] ; CX has byte count
- call Shexwrd
- mov DI,47
- mov AX,[BP+REGBX] ; BL has drive
- call OutByte
- ret
- ;
- d445:
- mov DX,OFFSET STR445 ; Write To Control Channel of Drive
- mov DI,DX
- add DI,6
- mov AX,[BP+REGCX] ; CX has byte count
- call Shexwrd
- mov DI,46
- mov AX,[BP+REGBX] ; BL has drive
- call OutByte
- ret
- ;
- d446:
- mov DX,OFFSET STR446 ; Get Input Status of Device
- mov DI,27
- mov AX,[BP+REGBX] ; BX has file handle
- call OutWord
- ret
- ;
- d447:
- mov DX,OFFSET STR447 ; Get Output Status of Device
- mov DI,28
- mov AX,[BP+REGBX] ; BX has file handle
- call OutWord
- ret
- ;
- d448:
- mov DX,OFFSET STR448 ; Report Whether Device Has Removable Media
- mov DI,22
- mov AX,[BP+REGBX] ; BX has file handle
- call OutWord
- ret
- ;
- d4411:
- mov DX,OFFSET STR4411 ; Set Retries For Device
- mov DI,DX
- add DI,23
- mov AX,[BP+REGBX] ; BX has file handle
- call Shexwrd
- add DI,5
- mov AX,[BP+REGDX] ; DX has retry count
- call Shexwrd
- mov DI,55
- mov AX,[BP+REGCX] ; CX has interval between tries
- call OutWord
- ret
-
- ;
- ; Force Duplication of Handle
- ;
- Disp_46:
- mov DI,DX
- add DI,28
- mov AX,[BP+REGBX] ; BX has the existing file handle
- call Shexwrd
- mov DI,37
- mov AX,[BP+REGCX] ; CX has the second file handle
- call OutWord
- ret
-
- ;
- ; Get Current Directory
- ;
- Disp_47:
- mov DI,DX
- add DI,31
- mov AX,[BP+REGDX] ; DL register has drive code
- call Shexbyt
- add DI,7
- mov AX,DSsave
- call Shexwrd
- inc DI ; skip ':'
- mov AX,[BP+REGSI] ; get USER's DS:SI value
- call Shexwrd
- call Disp_Str
- ret
-
- ;
- ; Allocate Memory
- ;
- Disp_48:
- mov DI,9
- mov AX,[BP+REGBX] ; BX has the memory requested in paragraphs
- call OutWord
- ret
-
- ;
- ; Free Allocated Memory
- ;
- Disp_49:
- mov DI,33
- mov AX,[BP+REGES] ; ES has the segment address
- call OutWord
- ret
-
- ;
- ; Modify Memory Block
- ;
- Disp_4a:
- mov DI,DX
- add DI,31
- mov AX,[BP+REGES] ; ES has the segment address
- call Shexwrd
- mov DI,43
- mov AX,[BP+REGBX] ; BX has size in paragraphs
- call OutWord
- ret
-
- ;
- ; Load or Exececute Program
- ; Find First Matching File
- ;
- Disp_4b:
- Disp_4e:
- mov DI,29 ; offset where (DS:DX) goes within string
- mov cx,41 ; max number of char's to fit in window
- call One_String
- ret
-
- ;
- ; Terminate Process with Return Code
- ;
- Disp_4c:
- mov DI,35
- mov AX,Axsave ; AL register return code
- call OutByte
- ret
-
- ;
- ; Rename File
- ;
- Disp_56:
- mov DI,29
- mov cx,41
- call One_String ; display 'old' name
- ;
- mov DX,OFFSET STR56N
- mov DI,DX
- add DI,29
- push DS
- mov DS,[BP+REGES]
- mov SI,[BP+REGDI] ; get USER's ES:DI value
- mov cx,41 ; to display 'new' name
- rep movsb
- pop DS
- mov CX,0601h
- mov BX,OFFSET W1
- mov AH,HIWHITE
- call WPrint
- ret
-
- ;
- ; Get Date and Time of File
- ;
- Disp_57:
- mov AX,AXsave ; user's AL has get/set indicator
- cmp AL,00 ; is it GET?
- jz gdtptr
- cmp AL,01 ; is it SET?
- jz sdtptr
- mov DI,37 ; unknown function
- mov AX,[BP+REGBX] ; file handle
- call OutWord
- ret
- gdtptr:
- mov DX,OFFSET STR57G
- jmp SHORT ddtptr
- ;
- sdtptr:
- mov DX,OFFSET STR57S
- ddtptr:
- mov DI,33
- mov AX,[BP+REGBX] ; BX register has file handle
- call OutWord
- ret
-
- ;
- ; Lock/Unlock File
- ;
- Disp_5c:
- mov AX,AXsave
- cmp AL,00 ; 0 = Lock
- jz dlck
- cmp AL,01 ; 1 = Unlock
- jz dunlck
- mov DI,17
- mov AX,[BP+REGBX] ; BX has file handle
- call OutWord
- ret
- ;
- dlck:
- mov DX,OFFSET STR5c0
- mov DI,10
- mov AX,[BP+REGBX]
- call OutWord
- ret
- ;
- dunlck:
- mov DX,OFFSET STR5c1
- mov DI,12
- mov AX,[BP+REGBX]
- call OutWord
- ret
-
-
- ;
- ; Table of function codes.
- ; (1st) word is DOS function code (AH),
- ; (2nd) word is pointer to string to display,
- ; (3rd) word is subroutine address to handle display of this type function.
- ;
- FCtbl:
- dw 0000h, STR00, Disp_Str
- dw 0100h, STR01, Disp_Str
- dw 0200h, STR02, Disp_02
- dw 0300h, STR03, Disp_Str
- dw 0400h, STR04, Disp_04
- dw 0500h, STR05, Disp_05
- dw 0600h, STR06, Disp_06
- dw 0700h, STR07, Disp_Str
- dw 0800h, STR08, Disp_Str
- dw 0900h, STR09, Disp_09
- dw 0a00h, STR0a, Disp_0a
- dw 0b00h, STR0b, Disp_Str
- dw 0c00h, STR0c, Disp_0c
- dw 0d00h, STR0d, Disp_Str
- dw 0e00h, STR0e, Disp_0e
- dw 0f00h, STR0f, Disp_0f
- dw 1000h, STR10, Disp_10
- dw 1100h, STR11, Disp_11
- dw 1200h, STR12, Disp_12
- dw 1300h, STR13, Disp_13
- dw 1400h, STR14, Disp_14
- dw 1500h, STR15, Disp_15
- dw 1600h, STR16, Disp_16
- dw 1700h, STR17, Disp_17
- dw 1800h, STRUN, Disp_Str
- dw 1900h, STR19, Disp_Str
- dw 1a00h, STR1a, Disp_1a
- dw 1b00h, STR1b, Disp_Str
- dw 1c00h, STR1c, Disp_1c
- dw 1d00h, STRUN, Disp_Str
- dw 1e00h, STRUN, Disp_Str
- dw 1f00h, STRUN, Disp_Str
- dw 2000h, STRUN, Disp_Str
- dw 2100h, STR21, Disp_21
- dw 2200h, STR22, Disp_22
- dw 2300h, STR23, Disp_23
- dw 2400h, STR24, Disp_24
- dw 2500h, STR25, Disp_25
- dw 2600h, STR26, Disp_26
- dw 2700h, STR27, Disp_27
- dw 2800h, STR28, Disp_28
- dw 2900h, STR29, Disp_29
- dw 2a00h, STR2a, Disp_Str
- dw 2b00h, STR2b, Disp_2b
- dw 2c00h, STR2c, Disp_Str
- dw 2d00h, STR2d, Disp_2d
- dw 2e00h, STR2e, Disp_2e
- dw 2f00h, STR2f, Disp_Str
- dw 3000h, STR30, Disp_Str
- dw 3100h, STR31, Disp_Str
- dw 3200h, STRUN, Disp_Str
- dw 3300h, STR33, Disp_33
- dw 3400h, STRUN, Disp_Str
- dw 3500h, STR35, Disp_35
- dw 3600h, STR36, Disp_36
- dw 3700h, STR37, Disp_Str
- dw 3800h, STR38, Disp_Str
- dw 3900h, STR39, Disp_39
- dw 3a00h, STR3a, Disp_3a
- dw 3b00h, STR3b, Disp_3b
- dw 3c00h, STR3c, Disp_3c
- dw 3d00h, STR3d, Disp_3d
- dw 3e00h, STR3e, Disp_3e
- dw 3f00h, STR3f, Disp_3f
- dw 4000h, STR40, Disp_40
- dw 4100h, STR41, Disp_41
- dw 4200h, STR42, Disp_42
- dw 4300h, STR43, Disp_43
- dw 4400h, STR44, Disp_44
- dw 4500h, STR45, Disp_45
- dw 4600h, STR46, Disp_46
- dw 4700h, STR47, Disp_47
- dw 4800h, STR48, Disp_48
- dw 4900h, STR49, Disp_49
- dw 4a00h, STR4a, Disp_4a
- dw 4b00h, STR4b, Disp_4b
- dw 4c00h, STR4c, Disp_4c
- dw 4d00h, STR4d, Disp_Str
- dw 4e00h, STR4e, Disp_4e
- dw 4f00h, STR4f, Disp_Str
- dw 5000h, STRUN, Disp_Str
- dw 5100h, STRUN, Disp_Str
- dw 5200h, STRUN, Disp_Str
- dw 5300h, STRUN, Disp_Str
- dw 5400h, STR54, Disp_Str
- dw 5500h, STRUN, Disp_Str
- dw 5600h, STR56, Disp_56
- dw 5700h, STR57, Disp_57
- dw 5800h, STRUN, Disp_Str
- dw 5900h, STR59, Disp_Str
- dw 5a00h, STR5a, Disp_5a
- dw 5b00h, STR5b, Disp_5b
- dw 5c00h, STR5c, Disp_5c
- dw 5d00h, STRUN, Disp_Str
- dw 5e00h, STRUN, Disp_Str
- dw 5f00h, STRUN, Disp_Str
- dw 6000h, STRUN, Disp_Str
- dw 6100h, STRUN, Disp_Str
- dw 6200h, STR62, Disp_Str
- LENFC EQU $ - FCtbl
-
- ;
- ; The XX's are just place holders for help in alignment during debugging
- ;
- STR00 db 'Terminate Program'
- db 0
-
- STR01 db 'Keyboard Input With Echo'
- db 0
-
- STR02 db 'Output Character Hex XX ASCII X'
- db 0
-
- STR03 db 'Serial Input'
- db 0
-
- STR04 db 'Serial Output Hex XX ASCII X'
- db 0
-
- STR05 db 'Printer Output Hex XX ASCII X'
- db 0
-
- STR06 db 'Direct Console I/O - '
- db 0
-
- STR06I db 'Input Character'
- db 0
-
- STR07 db 'Direct Console Input Without Echo'
- db 0
-
- STR08 db 'Console Input Without Echo'
- db 0
-
- STR09 db 'Display String -->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXL'
- db 0
-
- STR0a db 'Buffered Keyboard Input To XXXX:XXXXH'
- db 0
-
- STR0b db 'Check Standard Input Status'
- db 0
-
- STR0c db 'Clear Keyboard and Do Function XXH'
- db 0
-
- STR0d db 'Reset Disk'
- db 0
-
- STR0e db 'Select Disk XXH'
- db 0
-
- STR0f db 'Open File Using FCB at XXXX:XXXXH'
- db 0
-
- STR10 db 'Close File Using FCB at XXXX:XXXXH'
- db 0
-
- STR11 db 'Search For First Matching File Using FCB at XXXX:XXXXH'
- db 0
-
- STR12 db 'Search For Next Matching File Using FCB at XXXX:XXXXH'
- db 0
-
- STR13 db 'Delete File Using FCB at XXXX:XXXXH'
- db 0
-
- STR14 db 'Read Sequential File Record Using FCB at XXXX:XXXXH'
- db 0
-
- STR15 db 'Write Sequential File Record Using FCB at XXXX:XXXXH'
- db 0
-
- STR16 db 'Create File Using FCB at XXXX:XXXXH'
- db 0
-
- STR17 db 'Rename File Using FCB at XXXX:XXXXH'
- db 0
-
- STR19 db 'Report Current Drive'
- db 0
-
- STR1a db 'Set Disk Transfer Address To XXXX:XXXXH'
- db 0
-
- STR1b db 'Get FAT Information For Default Drive'
- db 0
-
- STR1c db 'Get FAT Information For Drive XXH'
- db 0
-
- STR21 db 'Read Random File Record Using FCB at XXXX:XXXXH'
- db 0
-
- STR22 db 'Write Random File Record Using FCB at XXXX:XXXXH'
- db 0
-
- STR23 db 'Get File Size Using FCB at XXXX:XXXXH'
- db 0
-
- STR24 db 'Set Random Record Field Using FCB at XXXX:XXXXH'
- db 0
-
- STR25 db 'Set Interrupt Vector XXH to XXXX:XXXXH'
- db 0
-
- STR26 db 'Create New Program Segment At Segment XXXXH'
- db 0
-
- STR27 db 'Read XXXXH Random File Records Using FCB at XXXX:XXXXH'
- db 0
-
- STR28 db 'Write XXXXH Random File Records Using FCB at XXXX:XXXXH'
- db 0
-
- STR29 db 'Parse Filename -->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXL'
- db 0
-
- STR2a db 'Get Date'
- db 0
-
- STR2b db 'Set Date To mm/dd/yy XX/XX/XX'
- db 0
-
- STR2c db 'Get Time'
- db 0
-
- STR2d db 'Set Time To Hrs:Mins:Secs:Hunds XX:XX:XX:XX'
- db 0
-
- STR2e db 'Set Disk Write Verification XXX'
- db 0
-
- STR2f db 'Get Disk Transfer Address'
- db 0
-
- STR30 db 'Get DOS Version Number'
- db 0
-
- STR31 db 'Terminate Process and Remain Resident'
- db 0
-
- STR33 db 'Get/Set Control-Break Status'
- db 0
-
- STR33G db 'Get Control-Break Status'
- db 0
-
- STR33S db 'Set Control-Break Status XXX'
- db 0
-
- STR35 db 'Get Interrupt Vector XXH'
- db 0
-
- STR36 db 'Get Disk Free Space On Drive XXH'
- db 0
-
- STR37 db 'Get DOS Switch Character'
- db 0
-
- STR38 db 'Get/Set Country Dependent Information'
- db 0
-
- STR39 db 'Create Subdir --->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXL'
- db 0
-
- STR3a db 'Remove Subdir --->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXL'
- db 0
-
- STR3b db 'Change Dir To --->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXL'
- db 0
-
- STR3c db 'Create File ----->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXL'
- db 0
-
- STR3d db 'Open File ------->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXL'
- db 0
-
- STR3e db 'Close File Handle XXXXH'
- db 0
-
- STR3f db 'Read XXXXH Bytes From File or Device XXXXH'
- db 0
-
- STR40 db 'Write XXXXH Bytes To File or Device XXXXH'
- db 0
-
- STR41 db 'Delete File ----->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXL'
- db 0
-
- STR42 db 'Move File Handle XXXXH Pointer By XXXX:XXXXH From '
- db 'XXXXXXXXXXXXXXXXX'
- db 0
-
- STR43 db 'Get/Set File Attributes'
- db 0
-
- STR43G db 'Get File Attrib ->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXX'
- db 0
-
- STR43S db 'Set File Attrib ->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXX'
- db 0
-
- STR44 db 'I/O Control For Devices'
- db 0
-
- STR440 db 'Get Info For Device XXXXH'
- db 0
-
- STR441 db 'Set Info For Device XXXXH to XXXXH'
- db 0
-
- STR442 db 'Read XXXXH Bytes From Drive Control Channel of File XXXXH'
- db 0
-
- STR443 db 'Write XXXXH Bytes To Drive Control Channel of File XXXXH'
- db 0
-
- STR444 db 'Read XXXXH Bytes From Control Channel of Drive XXH'
- db 0
-
- STR445 db 'Write XXXXH Bytes To Control Channel of Drive XXH'
- db 0
-
- STR446 db 'Get Input Status of Device XXXXH'
- db 0
-
- STR447 db 'Get Output Status of Device XXXXH'
- db 0
-
- STR448 db 'Report Whether Device XXXXH Has Removable Media'
- db 0
-
- STR4411 db 'Set Retries For Device XXXXH to XXXXH With Interval of XXXXH'
- db 0
-
- STR45 db 'Duplicate File Handle XXXXH'
- db 0
-
- STR46 db 'Force Duplication of Handle XXXXH to XXXXH'
- db 0
-
- STR47 db 'Get Current Directory of Drive XXH into XXXX:XXXXH'
- db 0
-
- STR48 db 'Allocate XXXXH Paragraphs of Memory'
- db 0
-
- STR49 db 'Free Allocated Memory at Segment XXXXH'
- db 0
-
- STR4a db 'Modify Memory Block at Segment XXXXH to be XXXXH Paragraphs'
- db 0
-
- STR4b db 'Load or Execute Program ---->XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXX'
- db 0
-
- STR4c db 'Terminate Process With Return Code XXH'
- db 0
-
- STR4d db 'Get Return Code of Subprocess'
- db 0
-
- STR4e db 'Find First Matching File --->XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXX'
- db 0
-
- STR4f db 'Find Next Matching File'
- db 0
-
- STR54 db 'Get Verify State'
- db 0
-
- STR56 db 'Rename File Old Name ----->XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXX'
- db 0
-
- STR56N db ' New Name ----->XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXX'
- db 0
-
- STR57 db 'Get/Set Date and Time of File Handle XXXXH'
- db 0
-
- STR57G db 'Get Date and Time of File Handle XXXXH'
- db 0
-
- STR57S db 'Set Date and Time of File Handle XXXXH'
- db 0
-
- STR59 db 'Get Extended Error Code'
- db 0
-
- STR5a db 'Create Temp File XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXL'
- db 0
-
- STR5b db 'Create New File XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- db 'XXXXXXXXXXXL'
- db 0
-
- STR5c db 'Lock/Unlock File XXXXH'
- db 0
-
- STR5c0 db 'Lock File XXXXH'
- db 0
-
- STR5c1 db 'Unlock File XXXXH'
- db 0
-
- STR62 db 'Get PSP Address'
- db 0
-
- STRUN db '** Undocumented Function Code **'
- db 0
-
- ;
- ; Don't change the size of the following strings
- ;
- Blanks3 db ' '
- Blanks17 db ' '
- ONstr db 'ON '
- OFFstr db 'OFF'
- BOFstr db 'Beginning of File'
- CURstr db 'Current Location '
- EOFstr db 'End of File '
-
-
- Open_Window:
- push ES
- mov BX,OFFSET W1 ; window parameters
- ;
- ; Save current contents of window area
- ;
- mov SI,[BX].startmem ; screen addr of start of window
- mov DX,[BX].height
- mov ES,Winseg ; point to allocated memory block
- mov DI,0000
- saverow:
- push DS
- mov CX,[BX].xwidth
- mov DS,Scrseg ; get screen segment
- push SI ; save screen offset
- rep movsw ; do word to get char and attribute
- pop SI
- pop DS
- add SI,BytesPL ; next row down
- dec DX
- jnz saverow
- ;
- ; Draw window
- ;
- mov ES,Scrseg ; get screen segment
- mov DI,[BX].startmem ; physical addr of start of window
- mov AH,HIWHITE
- ;
- ; Draw top border
- ;
- push DI
- mov AL,ULC ; write upper left corner
- stosw
- mov CX,[BX].xwidth
- sub CX,2
- mov AL,BRDROW
- rep stosw
- mov AL,URC ; write upper right corner
- stosw
- pop DI
- add DI,BytesPL ; next row down
- ;
- ; Draw middle of window
- ;
- mov DX,[BX].height
- sub DX,2
- winrows:
- push DI
- mov AL,BRDCOL ; left border column
- stosw
- mov CX,[BX].xwidth
- sub CX,2
- mov AL,BLANK
- rep stosw
- mov AL,BRDCOL ; right border column
- stosw
- pop DI
- add DI,BytesPL ; next row down
- dec DX
- jnz winrows
- ;
- ; Draw bottom border
- ;
- push DI
- mov AL,LLC ; write lower left corner
- stosw
- mov CX,[BX].xwidth
- sub CX,2
- mov AL,BRDROW
- rep stosw
- mov AL,LRC ; write lower right corner
- stosw
- pop DI
- pop ES
- ret
-
-
- Close_Window:
- mov BX,OFFSET W1
- mov DI,[BX].startmem ; physical addr of screen area
- mov ES,Scrseg ; point to allocated memory block
- mov SI,0000 ; start of save memory block
- mov DX,[BX].height
- resrow:
- push DS
- mov CX,[BX].xwidth
- mov DS,Winseg ; get saved memory segment
- push DI ; save screen offset
- rep movsw ; do word to get char and attribute
- pop DI
- pop DS
- add DI,BytesPL ; next row down
- dec DX
- jnz resrow
- ret
-
- ;
- ; Print a string in window.
- ; Entry:
- ; CX = Row, Col position relative to start of window
- ; BX = Window pointer
- ; AH = Attribute
- ; DX = addr of string
- ;
- WPrint:
- push ES
- call GetRC ; convert to row, col in DI
- mov ES,Scrseg
- mov SI,DX ; move string address
- wpwrt:
- cmp BYTE PTR [SI],00 ; test for string terminator <NULL>
- jz wpexit
- lodsb
- stosw
- jmp wpwrt
- wpexit:
- pop ES
- ret
-
- ;
- ; Write one character and attribute to window
- ;
- ; Entry:
- ; CX = Row, Col position relative to start of window
- ; BX = Window pointer
- ; AH = attr
- ; AL = char
- ;
- WChar:
- push ES
- call GetRC ; convert to row, col in DI
- mov ES,Scrseg
- stosw
- pop ES
- ret
-
- ;
- ; Convert row, col in CX to physical addr in DI
- ;
- GetRC:
- push AX
- push DX
- mov DI,[BX].startmem ; physical start of window memory
- add DI,BytesPL ; go down a row
- add DI,2 ; go in one char, this is 0,0
- mov AL,CH
- xor AH,AH ; AX = relative row number
- mul BytesPL ; this clobbers DX
- add DI,AX
- mov AX,CX ; restore coordinates
- xor AH,AH ; AX = relative col number
- shl AX,1 ; times 2 for attribute
- add DI,AX
- pop DX
- pop AX
- ret
-
- ;
- ; WRITE HEX WORD
- ; Convert a hex word to an ASCII string and display it
- ; Entry:
- ; CX = Row, Col position relative to start of window
- ; BX = Window pointer
- ; AX = Word to convert
- ;
- Whexwd:
- push AX
- push BX
- push CX
- push DX
- ;
- push BX ; save window pointer
- push CX ; and row, col
- mov DI,OFFSET Astr
- xchg AH,AL
- call Shexbyt
- xchg AH,AL
- call Shexbyt
- xor AL,AL
- stosb ; make sure of terminating NULL
- mov DX,OFFSET Astr
- pop CX ; get row, col
- pop BX ; and Window ptr
- mov AH,HIWHITE ; set attribute
- call WPrint
- ;
- pop DX
- pop CX
- pop BX
- pop AX
- ret
-
- ;
- ; STORE HEX WORD
- ; Convert a hex word to ASCII and store it in destination string
- ; Entry:
- ; AX = Word to convert
- ; DI = destination pointer
- ;
- Shexwrd:
- xchg AL,AH ; convert upper half first
- call Shexbyt
- xchg AL,AH ; convert lower half
- call Shexbyt
- ret
-
- ;
- ; STORE HEX BYTE
- ; Convert a hex byte to ASCII and store it in destination string
- ; Entry:
- ; AL = Byte to convert
- ; DI = destination pointer
- ;
- Shexbyt:
- push AX
- mov AH,AL ; save temporarily
- shr AL,1
- shr AL,1
- shr AL,1
- shr AL,1
- cmp AL,10
- jb wh1
- add AL,07
- wh1:
- add AL,'0'
- stosb
- mov AL,AH
- and AL,0fh
- cmp AL,10
- jb wh2
- add AL,07
- wh2:
- add AL,'0'
- stosb
- pop AX
- ret
-
- ;
- ; Check if key pressed requires special handling
- ;
- ; Entry:
- ; AX = key pressed
- ;
- Disp_Key:
- mov DI,OFFSET Keytbl ; keys and subroutine addresses
- mov CX,LENKTAB / 4 ; number of entries
- cmpdk:
- cmp AX,[DI] ; is key in table?
- jz dkexec
- add DI,4 ; no, point to next key value
- loop cmpdk
- ret
- dkexec:
- add DI,2
- call [WORD PTR DI]
- ret
-
- ;
- ; Table of keys to watch for followed by the address of the routine to execute
- ;
- Keytbl dw ESCAPE, DO_Esc
- dw BIGS, Do_Skey
- dw SMALLS, Do_Skey
- dw BIGR, Do_Rkey
- dw SMALLR, Do_Rkey
- LENKTAB EQU $ - Keytbl
-
- ;
- ; If ESC key, clear 'running flag' so Int 21h will not be stopped each time
- ;
- Do_Esc:
- mov AL,00
- mov Run_Flg,AL
- ret
-
- ;
- ; 'S' key - skip successive functions of current type.
- ; Return to intercepting calls when something new comes along.
- ; This is so you don't have to sit through dozens if Function '2' calls
- ; while the target program outputs a string to the display.
- ;
- Do_Skey:
- mov AL,0ffh
- mov Skip_Flg,AL ; set flag to show we should skip something
- mov AX,AXsave ; get current function code
- mov Skip_Typ,AH ; save it
- ret
-
- ;
- ; 'R' key - stop after INT 21h call and let user see result registers
- ;
- Do_Rkey:
- mov AL,0ffh
- mov Ret_Flg,AL ; set flag
- ret
-
- ;
- ; Wait for any key pressed
- ;
- Get_Key:
- mov AH,00
- int 16h
- ret
-
- XTest:
- mov AH,02 ; write char
- mov DL,07 ; <BELL>
- int 21h
- iret
-
- ;
- ; Define format of WINDOW structure
- ;
- Window STRUC
- leftrow dw ?
- leftcol dw ?
- rightrow dw ?
- rightcol dw ?
- xwidth dw ?
- height dw ?
- startmem dw ?
- Window ENDS
-
- ;
- ; Allocate and intialize WINDOW parameters
- ;
- W1 Window <8, 2, 18, 74, 0, 0, 0>
-
- Winseg dw 0000 ; store segment of allocated memory
- ; for saving screen data
- Scrseg dw 0b800h ; segment where screen memory can be found
- BytesPL dw 80*2 ; number of bytes per line (char + attr)
- Run_Flg db 0ffh ; 'running' flag
- Ret_Flg db 00 ; 'stop on return' flag
- ;
- ; The following two variables are initialized the way they are to skip
- ; the first Int 21 call generated by 'STEPDOS' to EXEC the target program.
- ;
- Skip_Typ db 4bh ; type of function call to skip temporarily
- Skip_Flg db 0ffh ; set if function should be skipped
-
- Save21 dw ? ; save original Int21 vector here, IP
- dw ? ; and SEG
-
- Ssave LABEL DWORD
- SPsave dw ? ; save some of the user's registers here
- SSsave dw ? ; others will be on local stack
-
- AXsave dw ? ; these will have been left on user's
- DSsave dw ? ; stack instead of local stack
- CSsave dw ?
- IPsave dw ?
- FLsave dw ?
- ;
- ; Parameter block that will be passed to the EXEC function call (4bh) of DOS
- ;
- Param_Block LABEL WORD
- SegEnv dw ? ; segment addr of environment string
- SegCmd dw ? ; segmented ptr to command line
- dw ?
- FCBptr1 dw ? ; segmented ptr to first FCB
- dw ?
- FCBptr2 dw ? ; segmented ptr to second FCB
- dw ?
-
- ;
- ; File name that will be passed to the EXEC function call of DOS
- ;
- Filename db 128 dup (0)
- FNsize dw 0
- ;
- ; Command line from PSP:80h will be copied to here work from
- ;
- PSPstr db 128 dup (0)
-
- ;
- ; Command Line that will be passed to the EXEC function call of DOS
- ;
- CLstr db 128 dup (0)
-
- ;
- ; Two FCB's that will be passed to the EXEC function call of DOS
- ;
- FCB1 db 0
- db 11 dup (' ')
- db 0, 0, 0, 0
-
- FCB2 db 0
- db 11 dup (' ')
- db 0, 0, 0, 0
-
- COMstr db '.COM'
- EXEstr db '.EXE'
- ;
- INITmsg db 'STEPDOS Version 1.0'
- db CR
- db LF
- db '$'
-
- Memerr db CR
- db LF
- db 'Error Allocating Window Memory$'
-
- Execmsg db CR
- db LF
- db 'Unable to execute target program$'
-
- Findmsg db CR
- db LF
- db 'Unable to find target program$'
-
- Umsg db CR
- db LF
- db 'Usage: STEPDOS <filename>$'
-
- RegStr1 db ' AX BX CX DX DI SI BP SP'
- db ' DS ES SS CS IP FL'
- db 0
-
- RegStr2 db '---- ---- ---- ---- ---- ---- ---- ----'
- db ' ---- ---- ---- ---- ---- ----'
- db 0
-
- HlpStr1 db 'kip Current Function'
- db 0
-
- HlpStr2 db 'eturn Code'
- db 0
-
- HlpStr3 db ' - Non Stop'
- db 0
-
- HlpStr4 db 'Press Any Key To Continue'
- db 0
-
- Astr db 32 dup (0) ; string for converting ASCII characters
-
- ;
- ; Local Program Stack Area
- ;
- db 128 dup (?)
- Pstack EQU $
-
- ;
- ; Target Stack Area
- ;
- db 128 dup (?)
- Tstack EQU $
-
-
- IF TESTING
-
- Istr db 128 dup (' ')
-
- Ostr db 'Output String'
- db 0
- ENDIF
-
-
- IF TESTING
- cli
- mov AX,0
- mov ES,AX
- mov AX,OFFSET XTest
- mov ES:[INT21OFF],AX
- mov ES:[INT21OFF+2],CS
- sti
- ENDIF
-
- IF TESTING
- include test.asm
- jmp execdn
- ELSE
- int 21h
- ENDIF
-
- Code ENDS
-
- END Main
-