Added files

This commit is contained in:
Broken Pipe
2025-10-03 12:48:30 +10:00
parent 2421383299
commit 124d0e882e
96 changed files with 43187 additions and 4 deletions
+2 -2
View File
@@ -1,2 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
# Treat all files as binary so we don't screw them up
* binary
+371
View File
@@ -0,0 +1,371 @@
;
; xenix memory calls for MSDOS
;
; CAUTION: The following routines rely on the fact that arena_signature and
; arena_owner_system are all equal to zero and are contained in DI.
;
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
TITLE ALLOC.ASM - memory arena manager
NAME Alloc
SUBTTL memory allocation utility routines
PAGE
;
; arena data
;
i_need arena_head,WORD ; seg address of start of arena
i_need CurrentPDB,WORD ; current process data block addr
i_need FirstArena,WORD ; first free block found
i_need BestArena,WORD ; best free block found
i_need LastArena,WORD ; last free block found
i_need AllocMethod,BYTE ; how to alloc first(best)last
;
; arena_free_process
; input: BX - PID of process
; output: free all blocks allocated to that PID
;
procedure arena_free_process,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV DI,arena_signature
MOV AX,[arena_head]
CALL Check_Signature ; ES <- AX, check for valid block
arena_free_process_loop:
retc
PUSH ES
POP DS
CMP DS:[arena_owner],BX ; is block owned by pid?
JNZ arena_free_next ; no, skip to next
MOV DS:[arena_owner],DI ; yes... free him
arena_free_next:
CMP BYTE PTR DS:[DI],arena_signature_end
; end of road, Jack?
retz ; never come back no more
CALL arena_next ; next item in ES/AX carry set if trash
JMP arena_free_process_loop
arena_free_process ENDP
;
; arena_next
; input: DS - pointer to block head
; output: AX,ES - pointers to next head
; carry set if trashed arena
;
procedure arena_next,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV AX,DS ; AX <- current block
ADD AX,DS:[arena_size] ; AX <- AX + current block length
INC AX ; remember that header!
;
; fall into check_signature and return
;
; CALL check_signature ; ES <- AX, carry set if error
; RET
arena_next ENDP
;
; check_signature
; input: AX - address of block header
; output: ES=AX, carry set if signature is bad
;
procedure check_signature,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV ES,AX ; ES <- AX
CMP BYTE PTR ES:[DI],arena_signature_normal
; IF next signature = not_end THEN
JZ check_signature_ok ; GOTO ok
CMP BYTE PTR ES:[DI],arena_signature_end
; IF next signature = end then
JZ check_signature_ok ; GOTO ok
STC ; set error
return
check_signature_ok:
CLC
return
Check_signature ENDP
;
; Coalesce - combine free blocks ahead with current block
; input: DS - pointer to head of free block
; output: updated head of block, AX is next block
; carry set -> trashed arena
;
procedure Coalesce,NEAR
ASSUME DS:NOTHING,ES:NOTHING
CMP BYTE PTR DS:[DI],arena_signature_end
; IF current signature = END THEN
retz ; GOTO ok
CALL arena_next ; ES, AX <- next block, Carry set if error
retc ; IF no error THEN GOTO check
coalesce_check:
CMP ES:[arena_owner],DI
retnz ; IF next block isnt free THEN return
MOV CX,ES:[arena_size] ; CX <- next block size
INC CX ; CX <- CX + 1 (for header size)
ADD DS:[arena_size],CX ; current size <- current size + CX
MOV CL,ES:[DI] ; move up signature
MOV DS:[DI],CL
JMP coalesce ; try again
Coalesce ENDP
SUBTTL $Alloc - allocate space in memory
PAGE
;
; Assembler usage:
; MOV BX,size
; MOV AH,Alloc
; INT 21h
; AX:0 is pointer to allocated memory
; BX is max size if not enough memory
;
; Description:
; Alloc returns a pointer to a free block of
; memory that has the requested size in paragraphs.
;
; Error return:
; AX = error_not_enough_memory
; = error_arena_trashed
;
procedure $ALLOC,NEAR
ASSUME DS:NOTHING,ES:NOTHING
XOR AX,AX
MOV DI,AX
MOV [FirstArena],AX ; init the options
MOV [BestArena],AX
MOV [LastArena],AX
PUSH AX ; alloc_max <- 0
MOV AX,[arena_head] ; AX <- beginning of arena
CALL Check_signature ; ES <- AX, carry set if error
JC alloc_err ; IF error THEN GOTO err
alloc_scan:
PUSH ES
POP DS ; DS <- ES
CMP DS:[arena_owner],DI
JZ alloc_free ; IF current block is free THEN examine
alloc_next:
CMP BYTE PTR DS:[DI],arena_signature_end
; IF current block is last THEN
JZ alloc_end ; GOTO end
CALL arena_next ; AX, ES <- next block, Carry set if error
JNC alloc_scan ; IF no error THEN GOTO scan
alloc_err:
POP AX
alloc_trashed:
error error_arena_trashed
alloc_end:
CMP [FirstArena],0
JNZ alloc_do_split
alloc_fail:
invoke get_user_stack
POP BX
MOV [SI].user_BX,BX
error error_not_enough_memory
alloc_free:
CALL coalesce ; add following free block to current
JC alloc_err ; IF error THEN GOTO err
MOV CX,DS:[arena_size]
POP DX ; check for max found size
CMP CX,DX
JNA alloc_test
MOV DX,CX
alloc_test:
PUSH DX
CMP BX,CX ; IF BX > size of current block THEN
JA alloc_next ; GOTO next
CMP [FirstArena],0
JNZ alloc_best
MOV [FirstArena],DS ; save first one found
alloc_best:
CMP [BestArena],0
JZ alloc_make_best ; initial best
PUSH ES
MOV ES,[BestArena]
CMP ES:[arena_size],CX ; is size of best larger than found?
POP ES
JBE alloc_last
alloc_make_best:
MOV [BestArena],DS ; assign best
alloc_last:
MOV [LastArena],DS ; assign last
JMP alloc_next
;
; split the block high
;
alloc_do_split_high:
MOV DS,[LastArena]
MOV CX,DS:[arena_size]
SUB CX,BX
MOV DX,DS
JE alloc_set_owner ; sizes are equal, no split
ADD DX,CX ; point to next block
MOV ES,DX ; no decrement!
DEC CX
XCHG BX,CX ; bx has size of lower block
JMP alloc_set_sizes ; cx has upper (requested) size
;
; we have scanned memory and have found all appropriate blocks
; check for the type of allocation desired; first and best are identical
; last must be split high
;
alloc_do_split:
CMP BYTE PTR [AllocMethod], 1
JA alloc_do_split_high
MOV DS,[FirstArena]
JB alloc_get_size
MOV DS,[BestArena]
alloc_get_size:
MOV CX,DS:[arena_size]
SUB CX,BX ; get room left over
MOV AX,DS
MOV DX,AX ; save for owner setting
JE alloc_set_owner ; IF BX = size THEN (don't split)
ADD AX,BX
INC AX ; remember the header
MOV ES,AX ; ES <- DS + BX (new header location)
DEC CX ; CX <- size of split block
alloc_set_sizes:
MOV DS:[arena_size],BX ; current size <- BX
MOV ES:[arena_size],CX ; split size <- CX
MOV BL,arena_signature_normal
XCHG BL,DS:[DI] ; current signature <- 4D
MOV ES:[DI],BL ; new block sig <- old block sig
MOV ES:[arena_owner],DI
alloc_set_owner:
MOV DS,DX
MOV AX,[CurrentPDB]
MOV DS:[arena_owner],AX
MOV AX,DS
INC AX
POP BX
transfer SYS_RET_OK
$alloc ENDP
SUBTTL $SETBLOCK - change size of an allocated block (if possible)
PAGE
;
; Assembler usage:
; MOV ES,block
; MOV BX,newsize
; MOV AH,setblock
; INT 21h
; if setblock fails for growing, BX will have the maximum
; size possible
; Error return:
; AX = error_invalid_block
; = error_arena_trashed
; = error_not_enough_memory
; = error_invalid_function
;
procedure $SETBLOCK,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV DI,arena_signature
MOV AX,ES
DEC AX
CALL check_signature
JNC setblock_grab
setblock_bad:
JMP alloc_trashed
setblock_grab:
MOV DS,AX
CALL coalesce
JC setblock_bad
MOV CX,DS:[arena_size]
PUSH CX
CMP BX,CX
JBE alloc_get_size
JMP alloc_fail
$setblock ENDP
SUBTTL $DEALLOC - free previously allocated piece of memory
PAGE
;
; Assembler usage:
; MOV ES,block
; MOV AH,dealloc
; INT 21h
;
; Error return:
; AX = error_invalid_block
; = error_arena_trashed
;
procedure $DEALLOC,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV DI,arena_signature
MOV AX,ES
DEC AX
CALL check_signature
JC dealloc_err
MOV ES:[arena_owner],DI
transfer SYS_RET_OK
dealloc_err:
error error_invalid_block
$DEALLOC ENDP
SUBTTL $AllocOper - get/set allocation mechanism
PAGE
;
; Assembler usage:
; MOV AH,AllocOper
; MOV BX,method
; MOV AL,func
; INT 21h
;
; Error return:
; AX = error_invalid_function
;
procedure $AllocOper,NEAR
ASSUME DS:NOTHING,ES:NOTHING
CMP AL,1
JB AllocOperGet
JZ AllocOperSet
error error_invalid_function
AllocOperGet:
MOV AL,BYTE PTR [AllocMethod]
XOR AH,AH
transfer SYS_RET_OK
AllocOperSet:
MOV [AllocMethod],BL
transfer SYS_RET_OK
$AllocOper ENDP
do_ext
CODE ENDS
END
+508
View File
@@ -0,0 +1,508 @@
;
; buffer management for MSDOS
;
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
i_need BuffHead,DWORD
i_need PreRead,WORD
i_need LastBuffer,DWORD
i_need CurBuf,DWORD
i_need WPErr,BYTE
SUBTTL SETVISIT,SKIPVISIT -- MANAGE BUFFER SCANS
PAGE
procedure SETVISIT,near
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Set up a scan of I/O buffers
; Outputs:
; All visit flags = 0
; NOTE: This pre-scan is needed because a hard disk error
; may cause a scan to stop in the middle leaving some
; visit flags set, and some not set.
; DS:DI Points to [BUFFHEAD]
; No other registers altered
LDS DI,[BUFFHEAD]
PUSH AX
XOR AX,AX
SETLOOP:
MOV [DI.VISIT],AL
LDS DI,[DI.NEXTBUF]
CMP DI,-1
JNZ SETLOOP
LDS DI,[BUFFHEAD]
POP AX
return
entry SKIPVISIT
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DI Points to a buffer
; Function:
; Skip visited buffers
; Outputs:
; DS:DI Points to next unvisited buffer
; Zero is set if skip to LAST buffer
; No other registers altered
CMP DI,-1
retz
CMP [DI.VISIT],1
retnz
LDS DI,[DI.NEXTBUF]
JMP SHORT SKIPVISIT
return
SetVisit ENDP
SUBTTL SCANPLACE, PLACEBUF -- PUT A BUFFER BACK IN THE POOL
PAGE
procedure ScanPlace,near
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; Same as PLACEBUF
; Function:
; Save scan location and call PLACEBUF
; Outputs:
; DS:DI Points to saved scan location
; SI destroyed, other registers unchanged
PUSH ES
LES SI,[DI.NEXTBUF] ; Save scan location
CALL PLACEBUF
PUSH ES
POP DS ; Restore scan location
MOV DI,SI
POP ES
return
ScanPlace ENDP
NRETJ: JMP SHORT NRET
procedure PLACEBUF,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Input:
; DS:DI points to buffer
; Function:
; Remove buffer from queue and re-insert it in proper place.
; If buffer doesn't go at end, and isn't free, decrement
; priorities.
; NO registers altered
;
; DS:SI -- Curbuf, current buffer in list
; ES:DI -- Buf, buffer passed as argument
; BP:CX -- Pointsave, saved Buf.nextbuf
; DX:BX -- Lastbuf, previous buffer in list
; AL -- Inserted, Buf has been inserted
; AH -- Removed, Buf has been removed
IF IBM
IF NOT IBM
invoke save_world
XOR AX,AX ; Inserted = Removed = FALSE
LES CX,[DI.NEXTBUF]
MOV BP,ES ; Pointsave = Buf.nextbuf
MOV SI,DS
MOV ES,SI ; Buf is ES:DI
LDS SI,[BUFFHEAD] ; Curbuf = HEAD
CALL POINTCOMP ; Buf == HEAD?
JNZ TNEWHEAD
CMP CX,-1 ; Buf is LAST?
JZ NRETJ ; Only one buffer, nothing to do
MOV WORD PTR [BUFFHEAD],CX
MOV WORD PTR [BUFFHEAD+2],BP ; HEAD = Pointsave
INC AH ; Removed = TRUE
MOV DS,BP
MOV SI,CX ; Curbuf = HEAD
TNEWHEAD:
MOV BL,ES:[DI.BUFPRI]
CMP BL,[SI.BUFPRI]
JGE BUFLOOP
NEWHEAD: ; If Buf.pri < HEAD.pri
MOV WORD PTR ES:[DI.NEXTBUF],SI
MOV WORD PTR ES:[DI.NEXTBUF+2],DS ; Buf.nextbuf = HEAD
MOV WORD PTR [BUFFHEAD],DI
MOV WORD PTR [BUFFHEAD+2],ES ; HEAD = Buf
INC AL ; Inserted = TRUE
OR AH,AH
JNZ NRET ; If Removed == TRUE
BUFLOOP:
PUSH DS
PUSH SI
LDS SI,[SI.NEXTBUF]
CALL POINTCOMP
POP SI
POP DS
JNZ TESTINS
MOV WORD PTR [SI.NEXTBUF],CX ; If Curbuf.nextbuf == buf
MOV WORD PTR [SI.NEXTBUF+2],BP ; Curbuf.nextbuf = Pointsave
INC AH ; Removed = TRUE
OR AL,AL
JNZ SHUFFLE ; If Inserted == TRUE
TESTINS:
OR AL,AL
JNZ LOOKBUF
PUSH CX ; If NOT Inserted
MOV CL,ES:[DI.BUFPRI]
CMP CL,[SI.BUFPRI]
POP CX
JGE LOOKBUF
PUSH DS ; If Buf.pri < Curbuf.pri
MOV DS,DX
MOV WORD PTR [BX.NEXTBUF],DI
MOV WORD PTR [BX.NEXTBUF+2],ES ; Lastbuf.nextbuf = Buf
POP DS
MOV WORD PTR ES:[DI.NEXTBUF],SI
MOV WORD PTR ES:[DI.NEXTBUF+2],DS ; Buf.nextbuf = Curbuf
INC AL ; Inserted = TRUE
OR AH,AH
JNZ SHUFFLE ; If Removed == TRUE
LOOKBUF:
MOV BX,SI
MOV DX,DS ; Lastbuf = Curbuf
CMP WORD PTR [SI.NEXTBUF],-1
JZ ISLAST
LDS SI,[SI.NEXTBUF] ; Curbuf = Curbuf.nextbuf
JMP SHORT BUFLOOP
ISLAST: ; If Curbuf is LAST
MOV WORD PTR [SI.NEXTBUF],DI
MOV WORD PTR [SI.NEXTBUF+2],ES ; Curbuf.nextbuf = Buf
MOV WORD PTR ES:[DI.NEXTBUF],-1
MOV WORD PTR ES:[DI.NEXTBUF+2],-1 ; Buf is LAST
NRET:
invoke restore_world
return
SHUFFLE:
LDS DI,[BUFFHEAD]
DECLOOP:
CMP [DI.BUFPRI],FREEPRI
JZ NODEC
DEC [DI.BUFPRI]
NODEC:
LDS DI,[DI.NEXTBUF]
CMP DI,-1
JNZ DECLOOP
JMP SHORT NRET
ENDIF
ENDIF
invoke save_world
LES CX,[DI.NEXTBUF]
CMP CX,-1 ; Buf is LAST?
JZ NRET ; Buffer already last
MOV BP,ES ; Pointsave = Buf.nextbuf
PUSH DS
POP ES ; Buf is ES:DI
LDS SI,[BUFFHEAD] ; Curbuf = HEAD
CALL POINTCOMP ; Buf == HEAD?
JNZ BUFLOOP
MOV WORD PTR [BUFFHEAD],CX
MOV WORD PTR [BUFFHEAD+2],BP ; HEAD = Pointsave
JMP SHORT LOOKEND
BUFLOOP:
PUSH DS
PUSH SI
LDS SI,[SI.NEXTBUF]
CALL POINTCOMP
JZ GOTTHEBUF
POP AX
POP AX
JMP SHORT BUFLOOP
GOTTHEBUF:
POP SI
POP DS
MOV WORD PTR [SI.NEXTBUF],CX ; If Curbuf.nextbuf == buf
MOV WORD PTR [SI.NEXTBUF+2],BP ; Curbuf.nextbuf = Pointsave
LOOKEND:
PUSH DS
PUSH SI
LDS SI,[SI.NEXTBUF]
CMP SI,-1
JZ GOTHEEND
POP AX
POP AX
JMP SHORT LOOKEND
GOTHEEND:
POP SI
POP DS
MOV WORD PTR [SI.NEXTBUF],DI
MOV WORD PTR [SI.NEXTBUF+2],ES ; Curbuf.nextbuf = Buf
MOV WORD PTR ES:[DI.NEXTBUF],-1
MOV WORD PTR ES:[DI.NEXTBUF+2],-1 ; Buf is LAST
NRET:
invoke restore_world
return
PLACEBUF ENDP
procedure PLACEHEAD,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; SAME AS PLACEBUF except places buffer at head
invoke save_world
PUSH DS
POP ES
LDS SI,[BUFFHEAD]
MOV WORD PTR [BUFFHEAD],DI
MOV WORD PTR [BUFFHEAD+2],ES
MOV WORD PTR ES:[DI.NEXTBUF],SI
MOV WORD PTR ES:[DI.NEXTBUF+2],DS
LOOKEND2:
PUSH DS
PUSH SI
LDS SI,[SI.NEXTBUF]
CALL POINTCOMP
JZ GOTHEEND2
POP AX
POP AX
JMP SHORT LOOKEND2
GOTHEEND2:
POP SI
POP DS
MOV WORD PTR [SI.NEXTBUF],-1
MOV WORD PTR [SI.NEXTBUF+2],-1 ; Buf is LAST
JMP SHORT NRET
PLACEHEAD ENDP
SUBTTL POINTCOMP -- 20 BIT POINTER COMPARE
PAGE
procedure PointComp,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Compare DS:SI to ES:DI (or DS:DI to ES:SI) for equality
; DO NOT USE FOR < or >
; No Registers altered
CMP SI,DI
retnz
PUSH CX
PUSH DX
MOV CX,DS
MOV DX,ES
CMP CX,DX
POP DX
POP CX
return
PointComp ENDP
SUBTTL GETBUFFR -- GET A SECTOR INTO A BUFFER
PAGE
procedure GETBUFFR,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Input:
; AH = Priority buffer is to have
; AL = 0 means sector must be pre-read
; ELSE no pre-read
; DX = Desired physical sector number
; ES:BP = Pointer to drive parameters
; Function:
; Get the specified sector into one of the I/O buffers
; And shuffle the queue
; Output:
; [CURBUF] Points to the Buffer for the sector
; DX,ES:BP unchanged, all other registers destroyed
XOR SI,SI
entry GETBUFFRB
MOV [PREREAD],AX
MOV AL,ES:[BP.dpb_drive]
LDS DI,[LASTBUFFER]
ASSUME DS:NOTHING
CMP DI,-1 ; Recency pointer valid?
JZ SKBUF ; No
CMP DX,[DI.BUFSECNO]
JNZ SKBUF ; Wrong sector
CMP AL,[DI.BUFDRV]
JNZ SKBUF ; Wrong Drive
JMP SHORT JUSTBUF ; Just asked for same buffer
SKBUF:
LDS DI,[BUFFHEAD]
NXTBFF:
CMP DX,[DI.BUFSECNO]
JNZ BUMP
CMP AL,[DI.BUFDRV]
JNZ BUMP
JMP SHORT SETINF
BUMP:
LDS DI,[DI.NEXTBUF]
CMP DI,-1
JNZ NXTBFF
LDS DI,[BUFFHEAD]
PUSH SI
PUSH DX
PUSH BP
PUSH ES
CALL BUFWRITE ; Write out the dirty buffer
POP ES
POP BP
POP DX
POP SI
RDSEC: ; Read in the new sector
TEST BYTE PTR [PREREAD],-1
JNZ SETBUF
LEA BX,[DI.BufInSiz] ; Point at buffer
MOV CX,1
PUSH SI
PUSH DI
PUSH DX
OR SI,SI
JZ NORMSEC
invoke FATSECRD
JMP SHORT GOTTHESEC ; Buffer is marked free if read barfs
NORMSEC:
invoke DREAD ; Buffer is marked free if read barfs
GOTTHESEC:
POP DX
POP DI
POP SI
SETBUF:
MOV [DI.BUFSECNO],DX
MOV WORD PTR [DI.BUFDRVDP],BP
MOV WORD PTR [DI.BUFDRVDP+2],ES
XOR AH,AH
MOV AL,ES:[BP.dpb_drive]
MOV WORD PTR [DI.BUFDRV],AX
SETINF:
MOV AX,1 ; Default to not a FAT sector
OR SI,SI
JZ SETSTUFFOK
MOV AL,ES:[BP.dpb_FAT_count]
MOV AH,ES:[BP.dpb_FAT_size]
SETSTUFFOK:
MOV WORD PTR [DI.BUFWRTCNT],AX
CALL PLACEBUF
JUSTBUF:
MOV WORD PTR [CURBUF+2],DS
MOV WORD PTR [LASTBUFFER+2],DS
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV WORD PTR [CURBUF],DI
MOV WORD PTR [LASTBUFFER],DI
return
GETBUFFR ENDP
SUBTTL FLUSHBUF -- WRITE OUT DIRTY BUFFERS
PAGE
procedure FlushBuf,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Input:
; DS = DOSGROUP
; AL = Physical unit number
; = -1 for all units
; Function:
; Write out all dirty buffers for unit, and flag them as clean
; DS Preserved, all others destroyed (ES too)
LDS DI,[BUFFHEAD]
ASSUME DS:NOTHING
MOV AH,-1
NXTBUFF:
CMP [DI.BUFDRV],AH
JZ SKIPBFF ; Skip free buffers
CMP AH,AL
JZ DOBUFFER ; Do all dirty buffers
CMP AL,[DI.BUFDRV]
JNZ SKIPBFF ; Buffer not for this unit
DOBUFFER:
CMP BYTE PTR [DI.BUFDIRTY],0
JZ SKIPBFF ; Buffer not dirty
PUSH AX
PUSH WORD PTR [DI.BUFDRV]
CALL BUFWRITE
POP AX
XOR AH,AH ; Buffer is clean
CMP AL,BYTE PTR [WPERR]
JNZ NOZAP
MOV AL,0FFH ; Invalidate buffer, it is inconsistent
NOZAP:
MOV WORD PTR [DI.BUFDRV],AX
POP AX ; Search info
SKIPBFF:
LDS DI,[DI.NEXTBUF]
CMP DI,-1
JNZ NXTBUFF
PUSH SS
POP DS
return
FlushBuf ENDP
SUBTTL BUFWRITE -- WRITE OUT A BUFFER IF DIRTY
PAGE
procedure BufWrite,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Input:
; DS:DI Points to the buffer
; Function:
; Write out all the buffer if dirty.
; Output:
; Buffer marked free
; DS:DI Preserved, ALL others destroyed (ES too)
MOV AX,00FFH
XCHG AX,WORD PTR [DI.BUFDRV] ; Free, in case write barfs
CMP AL,0FFH
retz ; Buffer is free.
OR AH,AH
retz ; Buffer is clean.
CMP AL,BYTE PTR [WPERR]
retz ; If in WP error zap buffer
LES BP,[DI.BUFDRVDP]
LEA BX,[DI.BufInSiz] ; Point at buffer
MOV DX,[DI.BUFSECNO]
MOV CX,WORD PTR [DI.BUFWRTCNT]
MOV AL,CH ; [DI.BUFWRTINC]
XOR CH,CH
MOV AH,CH
PUSH DI
WRTAGAIN:
PUSH CX
PUSH AX
MOV CX,1
PUSH BX
PUSH DX
invoke DWRITE ; Write out the dirty buffer
POP DX
POP BX
POP AX
POP CX
ADD DX,AX
LOOP WRTAGAIN
POP DI
return
BufWrite ENDP
do_ext
CODE ENDS
END
+901
View File
@@ -0,0 +1,901 @@
TITLE CHKDSK - MS-DOS Disk consistancy checker
; CHKDSK Version 2.30
; Verifies and repairs MS-DOS disk directory.
; To build CHKDSK you need three modules:
; CHKDSK CHKPROC CHKMES
; They should be linked the that order as well.
; REVISION HISTORY
;REV 1.1
; 05/21/82 Added rev number
;REV 1.5
; Mod by NANCYP to report on extents
; Mod by AARONR to report volume ID
;REV 2.0
; Total rewrite for directories
;REV 2.1
; Added ^C and INT 24H handlers
;REV 2.2
; INTERNATIONAL support
;REV 2.3
; Split into two modules to allow assembly on a PC
; CHKDSK and CHKPROC
FALSE EQU 0
TRUE EQU NOT FALSE
DRVCHAR EQU ":"
;The following defines the ranges of DOS version numbers for which this CHKDSK
; is good
DOSVER_LOW EQU 0136H ;1.54 in hex
DOSVER_HIGH EQU 020BH ;2.11 in hex
INCLUDE DOSSYM.ASM
FCB EQU 5CH
;Drive parameter block from DOS header
SUBTTL Segments used in load order
CODE SEGMENT PUBLIC
CODE ENDS
CONST SEGMENT PUBLIC BYTE
CONST ENDS
DATA SEGMENT PUBLIC WORD
DATA ENDS
DG GROUP CODE,CONST,DATA
SUBTTL Initialized Data
PAGE
CONST SEGMENT PUBLIC BYTE
PUBLIC HECODE,SWITCHAR,NOISY,DOFIX,CONBUF,ORPHCNT,ORPHSIZ,DOFIX
PUBLIC HIDCNT,HIDSIZ,DIRCNT,DIRSIZ,FILCNT,FILSIZ,BADSIZ,LCLUS
PUBLIC DOTENT,HAVFIX,SECONDPASS,NUL,ALLFILE,PARSTR,ERRSUB,LCLUS
PUBLIC DIRTYFAT,BADSIZ,DDOTENT,CROSSCNT,ORPHFCB,ORPHEXT,ALLDRV
PUBLIC FRAGMENT,USERDIR,DIRBUF,USERDIR,FIXMFLG,DOTMES,DIRCHAR
EXTRN IDMES1:BYTE,IDPOST:BYTE,VNAME:BYTE,MONTAB:BYTE
EXTRN TCHAR:BYTE,BADREAD_PRE:BYTE,BADREAD_POST:BYTE
EXTRN CRLF:BYTE,BADVER:BYTE,BADSUBDIR:BYTE,CENTRY:BYTE
EXTRN BADDRV:BYTE,BADCD:BYTE,BADRDMES:BYTE,OPNERR:BYTE
EXTRN CONTAINS:BYTE,EXTENTS:BYTE,NOEXTENTS:BYTE
EXTRN BADDRVM:BYTE,BADDRVM2:BYTE,BADIDBYT:BYTE
DIRBUF LABEL BYTE ;Entry buffer for searches
VOLID DB -1,0,0,0,0,0,8 ;Volume ID FCB
VOLNAM DB 0,"???????????"
DB 25 DUP(0)
ALLFILE DB -1,0,0,0,0,0,1EH ;Extended FCB
ALLDRV DB 0,"???????????"
DB 25 DUP (?)
ORPHFCB DB 0,"FILE0000"
ORPHEXT DB "CHK"
DB 25 DUP (?)
;Non-message data
SWITCHAR DB "-"
ROOTSTR LABEL BYTE
DIRCHAR DB "/"
NUL DB 0
PARSTR DB "..",0
DOTMES DB ".",0
DOTENT DB ". "
DDOTENT DB ".. "
HECODE DB ?
FIXMFLG DB 0 ;Flag for printing fixmes
ERRSUB DW 0 ;Flag for bad subdir error
FRAGMENT DB 0 ;Flag for extent processing
DIRTYFAT DB 0 ;Dirty flag for FAT
DIRCNT DW 0 ;# directories
DIRSIZ DW 0 ;# alloc units in directories
FILCNT DW 0 ;# reg files
FILSIZ DW 0 ;# alloc units in reg files
HIDCNT DW 0 ;# hidden files
HIDSIZ DW 0 ;# alloc units in hidden files
BADSIZ DW 0 ;# alloc units in bad sectors
ORPHCNT DW 0 ;# orphan files made
ORPHSIZ DW 0 ;# alloc units in orphan files
LCLUS DW 0 ;# alloc units in lost clusters
DISPFLG DB 0 ;used by number routines
CROSSCNT DW 0 ;# crosslinked files (first pass)
SECONDPASS DB 0 ;Pass flag
HAVFIX DB 0 ;non zero if any fixes
DOFIX DB 0 ;flag for F switch
NOISY DB 0 ;flag for V switch
USERDIR DB "/",0 ;Users current dir for drive
DB (DIRSTRLEN-1) DUP (?)
CONBUF DB 15,0 ;Input buffer
DB 15 DUP (?)
CONST ENDS
SUBTTL Un-initialized Data
PAGE
DATA SEGMENT PUBLIC WORD
PUBLIC ZEROTRUNC,NAMBUF,MCLUS,THISDPB,STACKLIM,ERRCNT
PUBLIC SRFCBPT,ISCROSS,CSIZE,DSIZE,SSIZE,FAT,FATMAP
PUBLIC HARDCH,CONTCH,USERDEV,SECBUF,DOTSNOGOOD
HARDCH DD ? ;Pointer to real INT 24 handler
CONTCH DD ? ;Pointer to real INT 23 handler
THISDPB DD ? ;Pointer to drive DPB
USERDEV DB ? ;Users current device
CSIZE DB ? ;Sectors per cluster
SSIZE DW ? ;bytes per sector
DSIZE DW ? ;# alloc units on disk
MCLUS DW ? ;DSIZE + 1
NAMBUF DB 14 DUP (?) ;Buffer
DOTSNOGOOD DB ? ;. or .. error flag
ZEROTRUNC DB ? ;Trimming flag
ISCROSS DB ? ;Crosslink flag
OLDCLUS DW ?
SRFCBPT DW ?
FATMAP DW OFFSET DG:FAT ;Offset of FATMAP table
SECBUF DW ? ;Offset of sector buffer
ERRCNT DB ? ;Used by FATread and write
STACKLIM DW ? ;Stack growth limit
INTERNATVARS internat_block <>
DB (internat_block_max - ($ - INTERNATVARS)) DUP (?)
FAT LABEL WORD
DATA ENDS
SUBTTL Start of CHKDSK
CODE SEGMENT PUBLIC
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
PUBLIC SUBERRP,DOTCOMBMES,FIGREC,FCB_TO_ASCZ,PRTCHR,EPRINT
PUBLIC PRINT,DOCRLF,DISP16BITS,DISP32BITS,DISPCLUS,CHECKFILES
EXTRN RDSKERR:NEAR,SETSWITCH:NEAR,PROMPTYN:NEAR,REPORT:NEAR
EXTRN PRINTCURRDIRERR:NEAR,PRINTTHISEL2:NEAR,CHECKERR:NEAR
EXTRN INT_23:NEAR,INT_24:NEAR,FINDCHAIN:NEAR,DONE:NEAR,AMDONE:NEAR
EXTRN FATAL:NEAR,DIRPROC:NEAR,CHKMAP:NEAR,CHKCROSS:NEAR,UNPACK:NEAR
ORG 100H
CHKDSK:
JMP SHORT CHSTRT
HEADER DB "Ver 2.30"
CHSTRT:
;Code to print header.
; PUSH AX
; MOV DX,OFFSET DG:HEADER
; CALL PRINT
; POP AX
PUSH AX ;Save DRIVE validity info
MOV AH,GET_VERSION
INT 21H
XCHG AH,AL ;Turn it around to AH.AL
CMP AX,DOSVER_LOW
JB GOTBADDOS
CMP AX,DOSVER_HIGH
JBE OKDOS
GOTBADDOS:
MOV DX,OFFSET DG:BADVER
JMP CERROR
OKDOS:
POP AX ;Get back drive info
MOV BX,0FFF0H
MOV DX,SP
CMP DX,BX
JAE STACKOK ;Lots of stack
MOV DX,DS:[2] ;High break
MOV CX,CS
SUB DX,CX
CMP DX,0FFFH
JAE SETSTACK ;Lots to grab
MOV CX,4 ;Suck up more stack (blast command)
SHL DX,CL
MOV BX,DX
SETSTACK:
CLI
MOV SP,BX
STI
STACKOK:
PUSH AX
MOV AH,DISK_RESET ;Flush everything, and invalidate
INT 21H
POP AX
CMP AL,0FFH ;Illegal drive specifier?
JNZ FILECHK ;No -- check for filename
DRVERR:
MOV DX,OFFSET DG:BADDRV
CERROR:
PUSH CS ;Make sure DS is OK
POP DS
CALL PRINT ;Print error message
INT 20H
CERROR2:
PUSH DX
CALL DONE ;Reset users disk
POP DX
JMP SHORT CERROR
FILECHK:
MOV AX,(CHAR_OPER SHL 8)
INT 21H
MOV [SWITCHAR],DL
CMP DL,"/"
JNZ SLASHOK
MOV [DIRCHAR],"\"
MOV [USERDIR],"\"
SLASHOK:
CMP DS:(BYTE PTR FCB+1)," " ;Filename specified?
JZ DRVCHK ;No -- get the correct drive
MOV AL,[SWITCHAR]
CMP DS:(BYTE PTR FCB+1),AL ;Filename specified?
JZ DRVCHK ;No -- get the correct drive
MOV BYTE PTR [FRAGMENT],1 ;Set flag to perform fragment
;check on specified files
DRVCHK:
CALL SETSWITCH ;Look for switches
MOV AH,GET_DEFAULT_DRIVE ;Get current drive
INT 21H
MOV [USERDEV],AL ;Save for later
MOV AH,AL
INC AH ;A = 1
MOV BH,DS:(BYTE PTR FCB) ;See if drive specified
OR BH,BH
JZ SETDSK
MOV AL,BH
MOV AH,AL
DEC AL ;A = 0
SETDSK:
MOV [ALLDRV],AH ;Target drive
MOV [VOLNAM],AH ;A = 1
MOV [ORPHFCB],AH ;A = 1
ADD [BADDRVM],AL ;A = 0
ADD [BADDRVM2],AL ;A = 0
MOV DL,AH ;A = 1
MOV AH,GET_DPB ;Get the DPB
INT 21H
ASSUME DS:NOTHING
CMP AL,-1
JNZ DRVISOK ;Bad drive (should always be ok)
MOV DX,OFFSET DG:BADDRV
CERROR2J: JMP CERROR2
DRVISOK:
DEC DL ;A = 0
MOV AH,SET_DEFAULT_DRIVE ;Set Target
INT 21H
CMP [BX.dpb_current_dir],0
JZ CURRISROOT ;Save users current dir for target
MOV SI,BX
ADD SI,dpb_dir_text
MOV DI,OFFSET DG:USERDIR + 1
SETDIRLP:
LODSB
STOSB
OR AL,AL
JZ CURRISROOT
JMP SHORT SETDIRLP
CURRISROOT:
MOV WORD PTR [THISDPB+2],DS
PUSH CS
POP DS
ASSUME DS:DG
MOV WORD PTR [THISDPB],BX
MOV AX,(GET_INTERRUPT_VECTOR SHL 8) OR 23H
INT 21H
MOV WORD PTR [CONTCH],BX
MOV WORD PTR [CONTCH+2],ES
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H
MOV DX,OFFSET DG:INT_23
INT 21H
MOV AX,(GET_INTERRUPT_VECTOR SHL 8) OR 24H
INT 21H
MOV WORD PTR [HARDCH],BX
MOV WORD PTR [HARDCH+2],ES
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 24H
MOV DX,OFFSET DG:INT_24
INT 21H
PUSH CS
POP ES
MOV DX,OFFSET DG:ROOTSTR
MOV AH,CHDIR ;Start at root
INT 21H
MOV DX,OFFSET DG:BADCD
JC CERROR2J ;Couldn't get there
MOV DX,OFFSET DG:FAT ;Scratch space
MOV AH,SET_DMA
INT 21H
MOV DX,OFFSET DG:VOLID ;Look for VOL ID
MOV AH,DIR_SEARCH_FIRST
INT 21H
CMP AL,-1
JZ NOTVOLID
CALL PRINTID ;Have a VOL ID
NOTVOLID:
LDS BX,[THISDPB]
ASSUME DS:NOTHING
MOV AX,[BX.dpb_sector_size]
MOV [SSIZE],AX ;Sector size in bytes
MOV AL,[BX.dpb_cluster_mask]
INC AL
MOV [CSIZE],AL ;Sectros per cluster
MOV AX,[BX.dpb_max_cluster]
MOV [MCLUS],AX ;Bound for FAT searching
DEC AX
MOV [DSIZE],AX ;Total data clusters on disk
MOV AL,[BX.dpb_FAT_size] ;Sectors for one fat
XOR AH,AH
MOV CX,AX
MUL [SSIZE] ;Bytes for FAT
ADD [FATMAP],AX ;Allocate FAT space
MOV AX,[FATMAP]
ADD AX,[MCLUS]
ADD AX,2 ;Insurance
MOV [SECBUF],AX ;Allocate FATMAP space
ADD AX,[SSIZE]
ADD AX,20 ;Insurance
MOV [STACKLIM],AX ;Limit on recursion
MOV DI,CX
MOV CL,[BX.dpb_FAT_count] ;Number of FATs
MOV DX,[BX.dpb_first_FAT] ;First sector of FAT
PUSH CS
POP DS
ASSUME DS:DG
MOV BX,OFFSET DG:FAT
MOV AL,[ALLDRV]
DEC AL
MOV AH,'1'
RDLOOP:
XCHG CX,DI
PUSH DX
PUSH CX
PUSH DI
PUSH AX
INT 25H ;Read in the FAT
MOV [HECODE],AL
POP AX ;Flags
JNC RDOK
MOV DX,OFFSET DG:BADREAD_PRE ;Barfed
CALL PRINT
POP AX
PUSH AX
MOV DL,AH
CALL PRTCHR
MOV DX,OFFSET DG:BADREAD_POST
CALL PRINT
POP AX
POP CX
POP DI
POP DX
INC AH
ADD DX,DI
LOOP RDLOOP ;Try next FAT
CALL RDSKERR
JNZ NORETRY1
JMP NOTVOLID
NORETRY1:
MOV BX,OFFSET DG:BADRDMES
JMP FATAL ;Couldn't read any FAT, BARF
RDOK:
POP AX ;Clean up
POP AX
POP AX
POP AX
MOV SI,OFFSET DG:FAT
LODSB ;Check FAT ID byte
CMP AL,0F8H
JAE IDOK
MOV DX,OFFSET DG:BADIDBYT ;FAT ID bad
CALL PROMPTYN ;Ask user
JZ IDOK
JMP ALLDONE ;User said stop
IDOK:
MOV DI,[FATMAP]
MOV CX,[MCLUS]
INC CX
XOR AL,AL
REP STOSB ;Initialize FATMAP to all free
MOV DX,OFFSET DG:DIRBUF ;FOR ALL SEARCHING
MOV AH,SET_DMA
INT 21H
XOR AX,AX
PUSH AX ;I am root
PUSH AX ;Parent is root
CALL DIRPROC
CALL CHKMAP ;Look for badsectors, orphans
CALL CHKCROSS ;Check for second pass
CALL DOCRLF
CALL REPORT
ALLDONE:
CALL AMDONE
INT 20H ;Fini
ASSUME DS:DG
SUBTTL Check for extents in specified files
PAGE
CHECKFILES:
;Search the directory for the files specified on the command line
;and report the number of fragmented allocation units found in
;each one.
CALL DOCRLF
MOV AH,SET_DMA
MOV DX,[FATMAP] ;Use the first free space available
MOV BP,DX
ADD BP,27 ;cluster in the directory entry
INT 21H
MOV AH,DIR_SEARCH_FIRST ;Look for the first file
FRAGCHK:
MOV DX,FCB
INT 21H
OR AL,AL ;Did we find it?
JNZ MSGCHK ;No -- we're done
XOR AX,AX ;Initialize the fragment counter
MOV SI,[BP] ;Get the first cluster
CALL UNPACK
CMP DI,0FF8H ;End-of-file?
JAE NXTCHK ;Yes -- go report the results
INC SI
CMP SI,DI
JZ EACHCLUS
INC AX
EACHCLUS:
MOV [OLDCLUS],DI ;Save the last cluster found
MOV SI,DI ;Get the next cluster
CALL UNPACK
INC [OLDCLUS] ;Bump the old cluster
CMP DI,[OLDCLUS] ;Are they the same?
JNZ LASTCLUS ;No -- check for end-of-file
JMP SHORT EACHCLUS ;Continue processing
LASTCLUS:
CMP DI,0FF8H ;End-of-file?
JAE NXTCHK ;Yes -- go report the results
INC AX ;No -- found a fragement
JMP SHORT EACHCLUS ;Continue processing
NXTCHK:
OR AX,AX
JZ GETNXT
MOV [FRAGMENT],2 ;Signal that we output at least one file
PUSH AX ;Save count of fragments
MOV SI,[FATMAP]
INC SI
CALL PRINTTHISEL2
CALL DOCRLF
MOV DX,OFFSET DG:CONTAINS ;Print message
CALL PRINT
POP SI ;Number of fragments found
INC SI ;Number non-contig blocks
XOR DI,DI
MOV BX,OFFSET DG:EXTENTS
PUSH BP
CALL DISP16BITS
POP BP
GETNXT:
MOV AH,DIR_SEARCH_NEXT ;Look for the next file
JMP FRAGCHK
MSGCHK:
CMP AH,DIR_SEARCH_FIRST
JNZ FILSPOK
MOV SI,FCB + 1 ;File not found error
CALL PRINTTHISEL2
CALL DOCRLF
MOV DX,OFFSET DG:OPNERR
CALL PRINT ;Bad file spec
RET
FILSPOK:
CMP BYTE PTR [FRAGMENT],2
JZ CDONE
MOV DX,OFFSET DG:NOEXTENTS
CALL PRINT
CDONE:
RET
FIGREC:
;Convert cluster number in BX to sector # AH of cluster in DX
LDS DI,[THISDPB]
ASSUME DS:NOTHING
MOV CL,[DI.dpb_cluster_shift]
MOV DX,BX
DEC DX
DEC DX
SHL DX,CL
OR DL,AH
ADD DX,[DI.dpb_first_sector]
PUSH CS
POP DS
ASSUME DS:DG
RET
SUBTTL PRINTID - Print Volume ID info
PAGE
PRINTID:
ASSUME DS:DG
MOV DX,OFFSET DG:INTERNATVARS
MOV AX,INTERNATIONAL SHL 8
INT 21H
MOV [DISPFLG],1 ;Don't sub spaces for leading zeros
MOV SI,OFFSET DG:FAT + 8
MOV DI,OFFSET DG:VNAME
MOV CX,11
REP MOVSB
MOV DX,OFFSET DG:IDMES1
CALL PRINT ;Print ID message
ADD SI,13
LODSW ;Get date
PUSH SI
MOV DX,AX
MOV AX,[INTERNATVARS.Date_tim_format]
OR AX,AX
JZ USPDAT
DEC AX
JZ EUPDAT
CALL P_YR
CALL P_DSEP
CALL P_MON
CALL P_DSEP
MOV CX,1000H ;Do not supress leading zeroes
CALL P_DAY
JMP P_TIME
USPDAT:
CALL P_MONTH_NAM
MOV CX,1110H ;Supress at most 1 leading 0
CALL P_DAY
PUSH DX
MOV DL,','
CALL PRTCHR
MOV DL,' '
CALL PRTCHR
POP DX
PYA:
CALL P_YR
JMP P_TIME
EUPDAT:
MOV CX,1110H ;Supress at most 1 leading 0
CALL P_DAY
PUSH DX
MOV DL,' '
CALL PRTCHR
POP DX
CALL P_MONTH_NAM
JMP PYA
P_DSEP:
PUSH DX
MOV DL,[INTERNATVARS.Date_sep]
CALL PRTCHR
POP DX
RET
P_MONTH_NAM:
MOV AX,DX
PUSH DX
MOV CL,5
SHR AX,CL
AND AX,0FH ;Month in AX
DEC AX ;Make 0 indexed
MOV CX,AX
SHL AX,1
ADD AX,CX ;Mult by 3 chars/mo
MOV SI,OFFSET DG:MONTAB
ADD SI,AX
LODSB
MOV DL,AL
CALL PRTCHR
LODSB
MOV DL,AL
CALL PRTCHR
LODSB
MOV DL,AL
CALL PRTCHR
MOV DL,' '
CALL PRTCHR
POP DX
RET
P_MON:
MOV SI,DX
PUSH DX
MOV CL,5
SHR SI,CL
AND SI,0FH ;Month in SI
CALL CONVERT
MOV DL,AL
MOV CX,1000H ;Do not supress leading 0
CALL OUTBYTE ;Print month
POP DX
RET
P_DAY:
MOV SI,DX
PUSH DX
PUSH CX
AND SI,01FH ;SI has day
CALL CONVERT
POP CX
MOV DL,AL
CALL OUTBYTE ;Print day
POP DX
RET
P_YR:
MOV SI,DX
PUSH DX
MOV CL,9
SHR SI,CL
AND SI,07FH ;SI has raw year
ADD SI,1980 ;Real year
CALL CONVERT
MOV CX,1000H ;Do not supress leading zeros
CALL OUTWORD ;Print year
POP DX
RET
P_TIME:
MOV DL,' '
CALL PRTCHR
POP SI
ADD SI,-4
LODSW ;Get time
MOV DI,AX
MOV SI,DI
MOV CL,11
SHR SI,CL
AND SI,01FH ;SI has hour
CMP [INTERNATVARS.Time_24],0
JNZ ISOK2 ;24 hour time?
CMP SI,12
JB ISOK ;Is AM
MOV [TCHAR],'p'
JZ ISOK ;Is 12-1p
SUB SI,12 ;Is PM
ISOK:
OR SI,SI
JNZ ISOK2
MOV SI,12 ;0 is 12a
ISOK2:
CALL CONVERT
MOV CX,1110H ;Supress at most 1 leading 0
MOV DL,AL
CALL OUTBYTE ;Print hour
MOV DL,BYTE PTR [INTERNATVARS.Time_sep]
CALL PRTCHR
MOV SI,DI
MOV CL,5
SHR SI,CL
AND SI,03FH ;SI has minute
CALL CONVERT
MOV CX,1000H ;Do not supress leading zeroes
MOV DL,AL
CALL OUTBYTE ;Print minute
MOV DL,[TCHAR]
CMP [INTERNATVARS.Time_24],0
JNZ NOAP ;24 hour time, no a or p
CALL PRTCHR ;Print a or p
NOAP:
MOV DX,OFFSET DG:IDPOST
CALL PRINT
MOV [DISPFLG],0
RET
CONVERT:
MOV CX,16
XOR AX,AX
CNVLOOP:
SHL SI,1
CALL CONVWRD
CLC
LOOP CNVLOOP
RET
SUBTTL Misc Routines - Mostly I/O
PAGE
CONVWRD:
ADC AL,AL
DAA
XCHG AL,AH
ADC AL,AL
DAA
XCHG AL,AH
RET1: RET
UNSCALE:
SHR CX,1
JC RET1
SHL SI,1
RCL DI,1
JMP SHORT UNSCALE
DISP16BITS:
MOV BYTE PTR DISPFLG,1
JMP SHORT DISP32BITS
DISPCLUS:
MUL [SSIZE]
MOV CL,[CSIZE]
XOR CH,CH
MOV SI,AX
MOV DI,DX
CALL UNSCALE
DISP32BITS:
PUSH BP
PUSH BX
XOR AX,AX
MOV BX,AX
MOV BP,AX
MOV CX,32
CONVLP:
SHL SI,1
RCL DI,1
XCHG AX,BP
CALL CONVWRD
XCHG AX,BP
XCHG AX,BX
CALL CONVWRD
XCHG AX,BX
ADC AL,0
LOOP CONVLP
; Conversion complete
MOV CX,1310H ;Print 3-digit number with 2 leading blanks
CMP BYTE PTR DISPFLG,0
JNZ FOURDIG
MOV CX,1810H ;Print 8-digit number with 2 leading blanks
XCHG DX,AX
CALL DIGIT
XCHG AX,BX
CALL OUTWORD
FOURDIG:
MOV AX,BP
CALL OUTWORD
MOV BYTE PTR DISPFLG,0
POP DX
CALL PRINT
POP BP
RET
OUTWORD:
PUSH AX
MOV DL,AH
CALL OUTBYTE
POP DX
OUTBYTE:
MOV DH,DL
SHR DL,1
SHR DL,1
SHR DL,1
SHR DL,1
CALL DIGIT
MOV DL,DH
DIGIT:
AND DL,0FH
JZ BLANKZER
MOV CL,0
BLANKZER:
DEC CH
AND CL,CH
OR DL,30H
SUB DL,CL
CMP BYTE PTR DISPFLG,0
JZ PRTCHR
CMP DL,30H
JL RET2
PRTCHR:
MOV AH,STD_CON_OUTPUT
INT 21H
RET2: RET
PRINTCNT:
LODSB
MOV DL,AL
INT 21H
LOOP PRINTCNT
RET
EPRINT:
CALL CHECKERR
JNZ RET$1
JMP SHORT PRINT
DOCRLF:
MOV DX,OFFSET DG:CRLF
PRINT:
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
RET$1: RET
DOTCOMBMES:
CMP [NOISY],0
JZ SUBERRP
PUSH DX
CALL PRINTCURRDIRERR
MOV DX,OFFSET DG:CENTRY
CALL EPRINT
POP DX
CALL EPRINT
CALL DOCRLF
RET
SUBERRP:
MOV AL,1
XCHG AL,[ERRSUB]
CMP AL,0
JNZ RET32
MOV SI,OFFSET DG:NUL
CALL PRINTCURRDIRERR
MOV DX,OFFSET DG:BADSUBDIR
CALL EPRINT
RET32: RET
FCB_TO_ASCZ: ;Convert DS:SI to ASCIIZ ES:DI
MOV CX,8
MAINNAME:
LODSB
CMP AL,' '
JZ SKIPSPC
STOSB
SKIPSPC:
LOOP MAINNAME
LODSB
CMP AL,' '
JZ GOTNAME
MOV AH,AL
MOV AL,'.'
STOSB
XCHG AL,AH
STOSB
MOV CL,2
EXTNAME:
LODSB
CMP AL,' '
JZ GOTNAME
STOSB
LOOP EXTNAME
GOTNAME:
XOR AL,AL
STOSB
RET
CODE ENDS
END CHKDSK
+477
View File
@@ -0,0 +1,477 @@
TITLE CHKDSK Messages
FALSE EQU 0
TRUE EQU NOT FALSE
.xlist
.xcref
INCLUDE DOSSYM.ASM
;The DOST: prefix is a DEC TOPS/20 directory prefix. Remove it for
; assembly in MS-DOS assembly environments using MASM. The DOSSYM.ASM
; file must exist though, it is included with OEM distribution.
.cref
.list
CODE SEGMENT PUBLIC BYTE
CODE ENDS
CONST SEGMENT PUBLIC BYTE
EXTRN HIDSIZ:WORD,HIDCNT:WORD,DIRCNT:WORD,DIRSIZ:WORD,FILCNT:WORD
EXTRN FILSIZ:WORD,ORPHCNT:WORD,ORPHSIZ:WORD,BADSIZ:WORD,LCLUS:WORD
EXTRN DOFIX:BYTE
CONST ENDS
DATA SEGMENT PUBLIC BYTE
EXTRN DSIZE:WORD
DATA ENDS
DG GROUP CODE,CONST,DATA
CODE SEGMENT PUBLIC BYTE
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
PUBLIC RDSKERR,WDSKERR,SETSWITCH,PROMPTYN,DOINT26,CHAINREPORT,REPORT
EXTRN RDONE:NEAR,PRTCHR:NEAR,PRINT:NEAR,DOCRLF:NEAR
EXTRN DISP16BITS:NEAR,FINDCHAIN:NEAR
EXTRN DISP32BITS:NEAR,DISPCLUS:NEAR
DOINT26:
PUSH CX
PUSH AX
PUSH DX
PUSH BX
INT 26H
MOV [HECODE],AL
POP AX ;FLAGS
POP BX
POP DX
POP AX
POP CX
JNC RET23
MOV SI,OFFSET DG:WRITING
CALL DSKERR
JZ DOINT26
RET23: RET
RDSKERR:
MOV SI,OFFSET DG:READING
JMP SHORT DSKERR
WDSKERR:
MOV SI,OFFSET DG:WRITING
DSKERR:
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH ES
MOV AL,[HECODE]
CMP AL,12
JBE HAVCOD
MOV AL,12
HAVCOD:
XOR AH,AH
MOV DI,AX
SHL DI,1
MOV DX,WORD PTR [DI+MESBAS] ; Get pointer to error message
CALL PRINT ; Print error type
MOV DX,OFFSET DG:ERRMES
CALL PRINT
MOV DX,SI
CALL PRINT
MOV DX,OFFSET DG:DRVMES
CALL PRINT
ASK:
MOV DX,OFFSET DG:REQUEST
CALL PRINT
MOV AX,(STD_CON_INPUT_FLUSH SHL 8)+STD_CON_INPUT
INT 21H ; Get response
PUSH AX
CALL DOCRLF
POP AX
OR AL,20H ; Convert to lower case
CMP AL,"i" ; Ignore?
JZ EEXITNZ
CMP AL,"r" ; Retry?
JZ EEXIT
CMP AL,"a" ; Abort?
JNZ ASK
JMP RDONE
EEXITNZ:
OR AL,AL ; Resets zero flag
EEXIT:
POP ES
POP DI
POP DX
POP CX
POP BX
POP AX
RET
PROMPTYN:
;Prompt message in DX
;Prompt user for Y or N answer. Zero set if Y
PUSH SI
CALL PRINT
PAGAIN:
MOV DX,OFFSET DG:YES_NO
CALL PRINT
MOV DX,OFFSET DG:CONBUF
MOV AH,STD_CON_STRING_INPUT
INT 21H
CALL DOCRLF
MOV SI,OFFSET DG:CONBUF+2
CMP BYTE PTR [SI-1],0
JZ PAGAIN
LODSB
OR AL,20H ;Convert to lower case
CMP AL,'y'
JZ GOTANS
CMP AL,'n'
JZ GOTNANS
JMP PAGAIN
GOTNANS:
OR AL,AL ;Reset zero
GOTANS:
POP SI
RET
SETSWITCH:
;Look for F or V switch in command line
MOV SI,80H
LODSB
MOV DI,SI
MOV CL,AL
XOR CH,CH
JCXZ RET10 ;No parameters
MOV AL,[SWITCHAR]
MORESCAN:
REPNZ SCASB
JNZ RET10
JCXZ BADSWITCHA
MOV AH,[DI]
INC DI
OR AH,20H ;Convert to lower case
CMP AH,'f'
JNZ CHECKV
INC [DOFIX]
JMP SHORT CHEKMORE
CHECKV:
CMP AH,'v'
JZ SETNOISY
CALL BADSWITCH
JMP SHORT CHEKMORE
SETNOISY:
INC [NOISY]
CHEKMORE:
LOOP MORESCAN
RET
BADSWITCHA:
MOV AH,' ' ;Print a non switch
BADSWITCH:
PUSH AX
MOV DL,[SWITCHAR]
CALL PRTCHR
POP AX
PUSH AX
MOV DL,AH
CALL PRTCHR
MOV DX,OFFSET DG:BADSWMES
CALL PRINT
POP AX
RET10: RET
;**************************************
; Prints XXX lost clusters found in YYY chains message
; On entry SI is the XXX value and the YYY value is
; in ORPHCNT.
; NOTE:
; The DISP16BITS routine prints the number in DI:SI followed
; by the message pointed to by BX. If it is desired to
; print a message before the first number, point at the
; message with DX and call PRINT.
CHAINREPORT:
XOR DI,DI
MOV BX,OFFSET DG:ORPHMES2
CALL DISP16BITS
CALL FINDCHAIN
MOV BX,OFFSET DG:CHNUMMES
MOV SI,[ORPHCNT]
XOR DI,DI
CALL DISP16BITS ;Tell user how many chains found
RET
;*****************************************
;Prints all of the reporting data
;NOTE:
; The DISPCLUS, DISP16BITS and DISP32BITS routines
; print the number in DI:SI followed
; by the message pointed to by BX. If it is desired to
; print a message before the first number, point at the
; message with DX and call PRINT.
REPORT:
MOV AX,[DSIZE]
MOV BX,OFFSET DG:DSKSPC
CALL DISPCLUS ;Total size
CMP [HIDCNT],0
JZ USERLIN
MOV AX,[HIDSIZ] ;Hidden files
MOV BX,OFFSET DG:INMES
CALL DISPCLUS
MOV SI,[HIDCNT]
XOR DI,DI
MOV BX,OFFSET DG:HIDMES
CALL DISP16BITS
USERLIN:
CMP [DIRCNT],0
JZ DIRLIN
MOV AX,[DIRSIZ]
MOV BX,OFFSET DG:INMES
CALL DISPCLUS
MOV SI,[DIRCNT]
XOR DI,DI
MOV BX,OFFSET DG:DIRMES
CALL DISP16BITS
DIRLIN:
CMP [FILCNT],0
JZ ORPHLIN
MOV AX,[FILSIZ] ;Regular files
MOV BX,OFFSET DG:INMES
CALL DISPCLUS
MOV SI,[FILCNT]
XOR DI,DI
MOV BX,OFFSET DG:FILEMES
CALL DISP16BITS
ORPHLIN:
MOV AX,[ORPHSIZ]
OR AX,AX
JZ BADLIN
MOV BX,OFFSET DG:INMES ;Orphans
CMP [DOFIX],0
JNZ ALLSET1
MOV BX,OFFSET DG:INMES2 ;Orphans
ALLSET1:
CALL DISPCLUS
MOV SI,[ORPHCNT]
XOR DI,DI
MOV BX,OFFSET DG:ORPHMES
CALL DISP16BITS
BADLIN:
MOV AX,[BADSIZ]
OR AX,AX
JZ AVAILIN
MOV BX,OFFSET DG:BADSPC ;Bad sectors
CALL DISPCLUS
AVAILIN:
MOV AX,[DSIZE]
SUB AX,[DIRSIZ]
SUB AX,[FILSIZ]
SUB AX,[HIDSIZ]
SUB AX,[BADSIZ]
SUB AX,[ORPHSIZ]
SUB AX,[LCLUS]
MOV BX,OFFSET DG:FRESPC
CALL DISPCLUS ;Free space is whats left
MOV AX,DS:WORD PTR [2] ;Find out about memory
MOV DX,16
MUL DX
MOV SI,AX
MOV DI,DX
MOV BX,OFFSET DG:TOTMEM
CALL DISP32BITS
MOV AX,DS:WORD PTR [2]
MOV DX,CS
SUB AX,DX
MOV DX,16
MUL DX
MOV SI,AX
MOV DI,DX
MOV BX,OFFSET DG:FREMEM
CALL DISP32BITS
RET
CODE ENDS
CONST SEGMENT PUBLIC BYTE
EXTRN HECODE:BYTE,SWITCHAR:BYTE,NOISY:BYTE,DOFIX:BYTE,CONBUF:BYTE
PUBLIC CRLF2,CRLF,BADVER,BADDRV
PUBLIC BADSUBDIR,CENTRY,CLUSBAD,BADATT,BADSIZM
PUBLIC FIXMES,DIRECMES,CDDDMES
PUBLIC FREEBYMESF_PRE,FREEBYMES_PRE,FREEBYMESF_POST,FREEBYMES_POST
PUBLIC CREATMES,NDOTMES
PUBLIC BADTARG1,BADTARG2,BADCD,FATALMES,BADRDMES
PUBLIC BADDRVM,STACKMES,BADDPBDIR
PUBLIC BADDRVM2
PUBLIC NULNZ,NULDMES,BADCLUS,NORECDOT
PUBLIC NORECDDOT,IDMES1,IDPOST,VNAME,TCHAR
PUBLIC MONTAB,BADREAD_PRE,BADREAD_POST,BADWRITE_PRE
PUBLIC BADWRITE_POST,BADCHAIN,CROSSMES_PRE,CROSSMES_POST
PUBLIC FREEMES
PUBLIC OPNERR
PUBLIC CONTAINS,EXTENTS,NOEXTENTS,INDENT
PUBLIC BADIDBYT,PTRANDIR,PTRANDIR2
MESBAS DW OFFSET DG:ERR0
DW OFFSET DG:ERR1
DW OFFSET DG:ERR2
DW OFFSET DG:ERR3
DW OFFSET DG:ERR4
DW OFFSET DG:ERR5
DW OFFSET DG:ERR6
DW OFFSET DG:ERR7
DW OFFSET DG:ERR8
DW OFFSET DG:ERR9
DW OFFSET DG:ERR10
DW OFFSET DG:ERR11
DW OFFSET DG:ERR12
CRLF2 DB 13,10
CRLF DB 13,10,"$"
;Messages
BADVER DB "Incorrect DOS version",13,10,"$"
BADDRV DB "Invalid drive specification$"
BADSWMES DB " Invalid parameter",13,10,"$"
BADSUBDIR DB " Invalid sub-directory entry.",13,10,"$"
CENTRY DB " Entry has a bad $"
CLUSBAD DB " link$"
BADATT DB " attribute$"
BADSIZM DB " size$"
;"BADTARG1<name of dir followed by CR LF>BADTARG2"
BADTARG1 DB "Cannot CHDIR to $"
BADTARG2 DB " tree past this point not processed.",13,10,"$"
BADCD DB "Cannot CHDIR to root",13,10,"$"
FATALMES DB "Processing cannot continue.",13,10,"$"
BADRDMES DB "File allocation table bad drive "
BADDRVM DB "A.",13,10,"$"
STACKMES DB "Insufficient memory.",13,10,"$"
BADDPBDIR DB "Invalid current directory.",13,10,"$"
;INT 24 MESSAGE SHOULD AGREE WITH COMMAND
READING DB "read$"
WRITING DB "writ$"
ERRMES DB " error $"
DRVMES DB "ing drive "
BADDRVM2 DB "A",13,10,"$"
REQUEST DB "Abort, Retry, Ignore? $"
ERR0 DB "Write protect$"
ERR1 DB "Bad unit$"
ERR2 DB "Not ready$"
ERR3 DB "Bad command$"
ERR4 DB "Data$"
ERR5 DB "Bad call format$"
ERR6 DB "Seek$"
ERR7 DB "Non-DOS disk$"
ERR8 DB "Sector not found$"
ERR9 DB "No paper$"
ERR10 DB "Write fault$"
ERR11 DB "Read fault$"
ERR12 DB "Disk$"
NDOTMES DB " Does not exist.",13,10,"$"
NULNZ DB " First cluster number is invalid,",13,10
DB " entry truncated.",13,10,"$"
NULDMES DB " Directory is totally empty, no . or ..",13,10,"$"
BADCLUS DB " Allocation error, size adjusted.",13,10,"$"
NORECDOT DB " Cannot recover . entry, processing continued.",13,10,"$"
NORECDDOT DB " Cannot recover .. entry,"
;VOLUME ID
;"IDMES1/name at VNAME<date and time>IDPOST"
IDPOST DB 13,10,"$" ;WARNING this is currently the tail of
; the previos message!!!
IDMES1 DB "Volume "
VNAME DB 12 DUP(' ')
DB "created $"
TCHAR DB 'a'
MONTAB DB "JanFebMarAprMayJunJulAugSepOctNovDec"
;"BADREAD_PRE<# of FAT>BADREAD_POST"
BADREAD_PRE DB "Disk error reading FAT $"
;"BADWRITE_PRE<# of FAT>BADWRITE_POST"
BADWRITE_PRE DB "Disk error writing FAT $"
BADCHAIN DB " Has invalid cluster, file truncated."
BADREAD_POST LABEL BYTE
BADWRITE_POST LABEL BYTE
;"<name of file followed by CR LF>CROSSMES_PRE<# of cluster>CROSSMES_POST"
CROSSMES_POST DB 13,10,"$" ;WARNING Is tail of previos messages
CROSSMES_PRE DB " Is cross linked on cluster $"
;CHAINREPORT messages
ORPHMES2 DB " lost clusters found in $"
CHNUMMES DB " chains.",13,10,"$"
FREEMES DB "Convert lost chains to files $"
;REPORT messages
ORPHMES DB " recovered files",13,10,"$"
DSKSPC DB " bytes total disk space",13,10,"$"
INMES DB " bytes in $"
INMES2 DB " bytes would be in",13,10
DB " $"
FILEMES DB " user files",13,10,"$"
BADSPC DB " bytes in bad sectors",13,10,"$"
HIDMES DB " hidden files",13,10,"$"
DIRMES DB " directories",13,10,"$"
FRESPC DB " bytes available on disk",13,10,13,10,"$"
TOTMEM DB " bytes total memory",13,10,"$"
FREMEM DB " bytes free",13,10,13,10,"$"
;"<filename followed by CR LF>CONTAINS<# non-contig blocks>EXTENTS"
CONTAINS DB " Contains $"
EXTENTS DB " non-contiguous blocks.",13,10,"$"
NOEXTENTS DB "All specified file(s) are contiguous.",13,10,"$"
INDENT DB " $"
BADIDBYT DB "Probable non-DOS disk."
DB 13,10,"Continue $"
YES_NO DB "(Y/N)? $"
PTRANDIR DB " Unrecoverable error in directory.",13,10
PTRANDIR2 DB " Convert directory to file $"
FIXMES DB 13,10,"Errors found, F parameter not specified."
DB 13,10,"Corrections will not be written to disk.",13,10,13,10,"$"
DIRECMES DB "Directory $"
CDDDMES DB " CHDIR .. failed, trying alternate method.",13,10,"$"
FREEBYMESF_POST DB " bytes disk space freed.",13,10
FREEBYMESF_PRE DB "$"
FREEBYMES_POST DB " bytes disk space",13,10
DB " would be freed.",13,10
FREEBYMES_PRE DB "$"
CREATMES DB "Insufficient room in root directory."
DB 13,10,"Erase files in root and repeat CHKDSK.",13,10,"$"
OPNERR DB " File not found.",13,10,"$"
CONST ENDS
END
+1408
View File
File diff suppressed because it is too large Load Diff
+33
View File
@@ -0,0 +1,33 @@
;*************************************
; COMMAND EQUs which are not switch dependant
IFDEF IBM
INCLUDE IFEQU.ASM
ENDIF
SYM EQU ">"
LINPERPAG EQU 23
NORMPERLIN EQU 1
WIDEPERLIN EQU 5
COMBUFLEN EQU 128 ; Length of commmand buffer
DRVCHAR EQU ":"
FCB EQU 5CH
VARSTRUC STRUC
ISDIR DB ?
SIZ DB ?
TTAIL DW ?
INFO DB ?
BUF DB DIRSTRLEN + 20 DUP (?)
VARSTRUC ENDS
WSWITCH EQU 1 ; Wide display during DIR
PSWITCH EQU 2 ; Pause (or Page) mode during DIR
ASWITCH EQU 4 ; ASCII mode during COPY
BSWITCH EQU 8 ; Binary mode during COPY
VSWITCH EQU 10H ; Verify switch
GOTSWITCH EQU 8000H ; Meta switch set if switch character encountered
BIN
View File
Binary file not shown.
+788
View File
@@ -0,0 +1,788 @@
;
; This version of COMMAND is divided into three distinct parts. First is the
; resident portion, which includes handlers for interrupts 22H (terminate),
; 23H (Cntrl-C), 24H (fatal error), and 27H (stay resident); it also has code
; to test and, if necessary, reload the transient portion. Following the
; resident is the init code, which is overwritten after use. Then comes the
; transient portion, which includes all command processing (whether internal
; or external). The transient portion loads at the end of physical memory,
; and it may be overlayed by programs that need as much memory as possible.
; When the resident portion of command regains control from a user program, a
; checksum is performed on the transient portion to see if it must be
; reloaded. Thus programs which do not need maximum memory will save the time
; required to reload COMMAND when they terminate.
;
; REV 1.17
; 05/19/82 Fixed bug in BADEXE error (relocation error must return to
; resident since the EXELOAD may have overwritten the transient.
; REV 1.18
; 05/21/82 IBM version always looks on drive A
; MSVER always looks on default drive
;
; REV 1.19
; 06/03/82 Drive spec now entered in command line
; 06/07/82 Added VER command (print DOS version number) and VOL command
; (print volume label)
; REV 1.20
; 06/09/82 Prints "directory" after directories
; 06/13/82 MKDIR, CHDIR, PWD, RMDIR added
; REV 1.50
; Some code for new 2.0 DOS, sort of HACKey. Not enough time to
; do it right.
; REV 1.70
; EXEC used to fork off new processes
; REV 1.80
; C switch for single command execution
; REV 1.90
; Batch uses XENIX
; Rev 2.00
; Lots of neato stuff
; IBM 2.00 level
; Rev 2.01
; 'D' switch for date time suppression
; Rev 2.02
; Default userpath is NUL rather than BIN
; same as IBM
; COMMAND split into pieces
; Rev 2.10
; INTERNATIONAL SUPPORT
; Rev 2.11 COMMAND split into more pieces
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSW.ASM
INCLUDE COMEQU.ASM
CODERES SEGMENT PUBLIC
CODERES ENDS
DATARES SEGMENT PUBLIC BYTE
EXTRN COMBAD:BYTE,NEEDCOM:BYTE,DRVMSG:BYTE
EXTRN DEFMSG:BYTE,PROMPT:BYTE,EXECEMES:BYTE,EXEBAD:BYTE
EXTRN TOOBIG:BYTE,NOCOM:BYTE,RBADNAM:BYTE,INT_2E_RET:DWORD
EXTRN NOHANDMES:BYTE,BMEMMES:BYTE,HALTMES:BYTE,FRETMES:BYTE
EXTRN PARENT:WORD,HANDLE01:WORD,LOADING:BYTE,BATCH:WORD
EXTRN TRNSEG:WORD,COMDRV:BYTE,MEMSIZ:WORD,SUM:WORD,EXTCOM:BYTE
EXTRN IO_SAVE:WORD,PERMCOM:BYTE,SINGLECOM:WORD,VERVAL:WORD
EXTRN PIPEFLAG:BYTE,SAVE_PDB:WORD,COMSPEC:BYTE,TRANS:WORD
EXTRN TRANVARS:BYTE,LTPA:WORD,RSWITCHAR:BYTE,RDIRCHAR:BYTE
EXTRN RETCODE:WORD,FORFLAG:BYTE
IF IBMVER
EXTRN SYS_CALL:DWORD,ZEXEC:WORD,EXESEG:WORD,EXESUM:WORD
EXTRN USER_SS:WORD,USER_SP:WORD
ENDIF
DATARES ENDS
ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment
ENVIRONMENT ENDS
INIT SEGMENT PUBLIC PARA
EXTRN CONPROC:NEAR
INIT ENDS
TAIL SEGMENT PUBLIC PARA
TAIL ENDS
TRANCODE SEGMENT PUBLIC PARA
TRANCODE ENDS
TRANDATA SEGMENT PUBLIC BYTE
EXTRN TRANDATAEND:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE
EXTRN TRANSPACEEND:BYTE,HEADCALL:DWORD
TRANSPACE ENDS
TRANTAIL SEGMENT PUBLIC PARA
TRANTAIL ENDS
ZEXEC_CODE SEGMENT PUBLIC PARA
ZEXEC_CODE ENDS
ZEXEC_DATA SEGMENT PUBLIC BYTE
ZEXEC_DATA ENDS
RESGROUP GROUP CODERES,DATARES,ENVIRONMENT,INIT,TAIL
TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL
EGROUP GROUP ZEXEC_CODE,ZEXEC_DATA
ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment
PUBLIC ECOMSPEC,ENVIREND,PATHSTRING
ORG 0
ENVARENA DB 10H DUP (?) ; Pad for mem arena
PATHSTRING DB "PATH="
USERPATH LABEL BYTE
DB 0 ; Null path
DB "COMSPEC="
ECOMSPEC DB "/COMMAND.COM"
DB 134 DUP (0)
ENVIREND LABEL BYTE
ENVIRONSIZ EQU $-PATHSTRING
ENVIRONSIZ2 EQU $-ECOMSPEC
ENVIRONMENT ENDS
; START OF RESIDENT PORTION
CODERES SEGMENT PUBLIC
PUBLIC GETCOMDSK2,LODCOM,THEADFIX,CONTCTERM,LOADCOM,INT_2E,LODCOM1
PUBLIC CHKSUM,SETVECT,EXT_EXEC,TREMCHECK,RESTHAND,CONTC,RSTACK
PUBLIC SAVHAND
IF IBMVER
PUBLIC EXECHK,SYSCALL,EXEC_WAIT
ENDIF
ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN RPRINT:NEAR,ASKEND:NEAR,DSKERR:NEAR
ORG 0
ZERO = $
ORG 100H
PROGSTART:
JMP RESGROUP:CONPROC
DB (80H - 3) DUP (?)
RSTACK LABEL WORD
IF IBMVER
SYSCALL:
CMP AH,EXEC
JZ do_exec
JMP DWORD PTR [SYS_CALL]
do_exec:
PUSH ES
PUSH DS
PUSH BP
PUSH DI
PUSH SI
PUSH DX
PUSH CX
PUSH BX
PUSH AX
MOV [user_ss],SS
MOV [user_sp],SP
;
; are we running on RSTACK already?
;
PUSH CS
POP BX ; BX <- CS
PUSH SS
POP AX ; AX <- SS
CMP AX,BX ; IF AX == BX then no stack switch!
JZ Get_mem
MOV SS,BX
ASSUME SS:RESGROUP
MOV SP,OFFSET RESGROUP:RSTACK
Get_mem:
MOV BX,0FFFFH ; allocate all of memory
MOV AH,ALLOC
INT int_command
MOV AX,OFFSET EGROUP:ZEXECDATAEND + 15
MOV CL,4
SHR AX,CL
MOV CX,AX ; Save in CX
CMP BX,AX ; enough for EXEC?
JB EXECMER ; nope... cry
MOV AH,ALLOC
INT int_command
JC EXECMER ; Memory arenas probably trashed
ADD BX,AX
MOV [MEMSIZ],BX
SUB BX,CX
MOV [EXESEG],BX ; exec
MOV ES,AX
MOV AH,DEALLOC
INT int_command
PUSH CS
POP DS
ASSUME DS:RESGROUP
CALL EXECHK
CMP DX,[EXESUM]
JZ HAVEXEC ; EXEC OK
MOV DX,OFFSET RESGROUP:COMSPEC
MOV AX,OPEN SHL 8
INT int_command ; Open COMMAND.COM
JC EXECMER
MOV BX,AX ; Handle
MOV DX,OFFSET RESGROUP:TRANSTART
ADD DX,OFFSET TRANGROUP:EXECSTART - 100H
XOR CX,CX ; Seek loc
MOV AX,LSEEK SHL 8
INT int_command
MOV CX,OFFSET EGROUP:ZEXECCODEEND
MOV DS,[EXESEG]
ASSUME DS:NOTHING
MOV AH,READ
INT int_command
PUSH AX
MOV AH,CLOSE
INT int_command ; Close COMMAND.COM
POP CX
CMP CX,OFFSET EGROUP:ZEXECCODEEND
JNZ EXECMER ; Size matched
CALL EXECHK
CMP DX,[EXESUM]
JNZ EXECMER
HAVEXEC:
MOV [LOADING],0 ; Flag to DSKERR
CALL DWORD PTR [ZEXEC]
JMP SHORT EXECRET
execmer:
LDS SI,DWORD PTR [user_Sp]
MOV [SI.user_AX],exec_not_enough_memory
PUSH [SI.user_F]
POPF
STC
PUSHF
POP [SI.user_F]
execret:
MOV SS,[user_SS]
ASSUME SS:NOTHING
MOV SP,[user_SP]
POP AX ; PUSH ES
POP BX ; PUSH DS
POP CX ; PUSH BP
POP DX ; PUSH DI
POP SI ; PUSH SI
POP DI ; PUSH DX
POP BP ; PUSH CX
POP DS ; PUSH BX
POP ES ; PUSH AX
IRET
EXECHK:
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
PUSH DS
MOV DS,[EXESEG]
MOV CX,OFFSET EGROUP:ZEXECCODEEND
XOR SI,SI
JMP CHECK_SUM
ENDIF
EXEC_ERR: ; Select the correct error message
MOV DX,OFFSET RESGROUP:RBADNAM
CMP AX,exec_file_not_found
JZ GOTEXECEMES
CMP AX,error_access_denied
JZ GOTEXECEMES
MOV DX,OFFSET RESGROUP:TOOBIG
CMP AX,exec_not_enough_memory
JZ GOTEXECEMES
MOV DX,OFFSET RESGROUP:EXEBAD
CMP AX,exec_bad_format
JZ GOTEXECEMES
MOV DX,OFFSET RESGROUP:EXECEMES
GOTEXECEMES:
PUSH CS
POP DS
CALL RPRINT
JMP SHORT NOEXEC
EXT_EXEC:
;
; we are now running in free space. anything we do from here
; on may get trashed. Move the stack (also in free space) to
; allocated space because since EXEC restores the stack,
; somebody may trash what is on the stack.
;
MOV CX,CS
MOV SS,CX
MOV SP,OFFSET RESGROUP:RSTACK
;
; Oops!! We have to make sure that the EXEC code doesn't blop a newstack!
;
;
INT int_command ; Do the EXEC
JC EXEC_ERR ; EXEC failed
EXEC_WAIT:
MOV AH,WAIT
INT int_command ; Get the return code
MOV [RETCODE],AX
NOEXEC:
JMP LODCOM
CONTC:
STI
MOV AX,CS
MOV DS,AX
ASSUME DS:RESGROUP
MOV AH,DISK_RESET
INT int_command ; Reset disks in case files were open
TEST [BATCH],-1
JZ CONTCTERM
JMP ASKEND ; See if user wants to terminate batch
CONTCTERM:
XOR BP,BP ; Indicate no read
MOV [FORFLAG],0 ; Turn off for processing
MOV [PIPEFLAG],0 ; Turn off any pipe
CMP [SINGLECOM],0 ; See if we need to set SINGLECOM
JZ NOSETSING
MOV [SINGLECOM],-1 ; Cause termination on pipe, batch, for
NOSETSING:
CMP [EXTCOM],0
JNZ DODAB ; Internal ^C
JMP LODCOM1
DODAB:
STC ; Tell DOS to abort
ZZY PROC FAR
RET ; Leave flags on stack
ZZY ENDP
BADMEMERR: ; Allocation error loading transient
MOV DX,OFFSET RESGROUP:BMEMMES
FATALC:
PUSH CS
POP DS
CALL RPRINT
CMP [PERMCOM],0
JZ FATALRET
CMP [SINGLECOM],0 ; If PERMCOM and SINGLECOM
JNZ FATALRET ; Must take INT_2E exit
MOV DX,OFFSET RESGROUP:HALTMES
CALL RPRINT
STALL:
JMP STALL ; Crash the system nicely
FATALRET:
MOV DX,OFFSET RESGROUP:FRETMES
CALL RPRINT
FATALRET2:
CMP [PERMCOM],0 ; If we get here and PERMCOM,
JNZ RET_2E ; must be INT_2E
IF IBM
LDS DX,DWORD PTR [SYS_CALL]
ASSUME DS:NOTHING
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) + INT_COMMAND
INT int_command
ENDIF
MOV AX,[PARENT]
MOV WORD PTR CS:[PDB_Parent_PID],AX
MOV AX,(EXIT SHL 8) ; Return to lower level
INT int_command
RET_2E:
PUSH CS
POP DS
ASSUME DS:RESGROUP,ES:NOTHING,SS:NOTHING
MOV [SINGLECOM],0 ; Turn off singlecom
MOV ES,[LTPA]
MOV AH,DEALLOC
INT int_command ; Free up space used by transient
MOV BX,[SAVE_PDB]
MOV AH,SET_CURRENT_PDB
INT int_command ; Current process is user
MOV AX,[RETCODE]
CMP [EXTCOM],0
JNZ GOTECODE
XOR AX,AX ; Internals always return 0
GOTECODE:
MOV [EXTCOM],1 ; Force external
JMP [INT_2E_RET] ;"IRET"
INT_2E: ; Magic command executer
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
POP WORD PTR [INT_2E_RET]
POP WORD PTR [INT_2E_RET+2] ;Get return address
POP AX ;Chuck flags
PUSH CS
POP ES
MOV DI,80H
MOV CX,64
REP MOVSW
MOV AH,GET_CURRENT_PDB
INT int_command ; Get user's header
MOV [SAVE_PDB],BX
MOV AH,SET_CURRENT_PDB
MOV BX,CS
INT int_command ; Current process is me
MOV [SINGLECOM],81H
MOV [EXTCOM],1 ; Make sure this case forced
LODCOM: ; Termination handler
CMP [EXTCOM],0
JZ LODCOM1 ; If internal, memory already allocated
MOV BX,0FFFFH
MOV AH,ALLOC
INT int_command
MOV AX,OFFSET TRANGROUP:TRANSPACEEND + 15
MOV CL,4
SHR AX,CL
IF IBM
PUSH AX
MOV AX,OFFSET EGROUP:ZEXECDATAEND + 15
MOV CL,4
SHR AX,CL
POP CX
ADD AX,CX
ENDIF
ADD AX,20H
CMP BX,AX ; Is less than 512 byte buffer worth it?
JNC MEMOK
BADMEMERRJ:
JMP BADMEMERR ; Not enough memory
MEMOK:
MOV AH,ALLOC
INT int_command
JC BADMEMERRJ ; Memory arenas probably trashed
MOV [EXTCOM],0 ; Flag not to ALLOC again
MOV [LTPA],AX ; New TPA is base just allocated
ADD BX,AX
MOV [MEMSIZ],BX
MOV AX,OFFSET TRANGROUP:TRANSPACEEND + 15
MOV CL,4
SHR AX,CL
IF IBM
PUSH AX
MOV AX,OFFSET EGROUP:ZEXECDATAEND + 15
MOV CL,4
SHR AX,CL
POP CX
ADD AX,CX
ENDIF
SUB BX,AX
MOV [TRNSEG],BX ; Transient starts here
LODCOM1:
MOV AX,CS
MOV SS,AX
ASSUME SS:RESGROUP
MOV SP,OFFSET RESGROUP:RSTACK
MOV DS,AX
ASSUME DS:RESGROUP
CALL HEADFIX ; Make sure files closed stdin and stdout restored
XOR BP,BP ; Flag command ok
MOV AX,-1
XCHG AX,[VERVAL]
CMP AX,-1
JZ NOSETVER
MOV AH,SET_VERIFY_ON_WRITE ; AL has correct value
INT int_command
NOSETVER:
CMP [SINGLECOM],-1
JNZ NOSNG
JMP FATALRET2 ; We have finished the single command
NOSNG:
CALL SETVECT
IF IBMVER
CALL EXECHK ; Check exe loader
CMP DX,[EXESUM]
JNZ BOGUS_COM
ENDIF
CALL CHKSUM ; Check the transient
CMP DX,[SUM]
JZ HAVCOM ; Transient OK
BOGUS_COM:
MOV [LOADING],1 ; Flag DSKERR routine
CALL LOADCOM
CHKSAME:
IF IBMVER
CALL EXECHK
CMP DX,[EXESUM]
JNZ ALSO_BOGUS
ENDIF
CALL CHKSUM
CMP DX,[SUM]
JZ HAVCOM ; Same COMMAND
ALSO_BOGUS:
CALL WRONGCOM
JMP SHORT CHKSAME
HAVCOM:
MOV AX,CHAR_OPER SHL 8
INT int_command
MOV [RSWITCHAR],DL
CMP DL,'/'
JNZ USESLASH
MOV [RDIRCHAR],'\' ; Select alt path separator
USESLASH:
MOV [LOADING],0 ; Flag to DSKERR
MOV SI,OFFSET RESGROUP:TRANVARS
MOV DI,OFFSET TRANGROUP:HEADCALL
MOV ES,[TRNSEG]
CLD
MOV CX,8
REP MOVSW ; Transfer INFO to transient
MOV AX,[MEMSIZ]
MOV WORD PTR DS:[PDB_block_len],AX ; Adjust my own header
JMP DWORD PTR [TRANS]
; Far call to REMCHECK for TRANSIENT
TREMCHECK PROC FAR
CALL REMCHECK
RET
TREMCHECK ENDP
REMCHECK:
;All registers preserved. Returns zero if media removable, NZ if fixed
; AL is drive (0=DEF, 1=A,...)
IF IBM
PUSH AX
OR AL,AL
JNZ GOTDRV2
MOV AH,GET_DEFAULT_DRIVE
INT int_command
INC AL ;A=1
GOTDRV2:
PUSH BX
MOV BL,AL
INT 11H ;IBM EQUIP CALL
ROL AL,1
ROL AL,1
AND AL,3
JNZ NOT_SINGLE
INC AL
NOT_SINGLE:
INC AL ; AL is now MAX floppy #
CMP BL,AL
POP BX
JBE SETREM ; Is an IBM floppy and so is removable
OR AL,AL ; Know AL is non-zero
JMP SHORT SETNREM
SETREM:
ELSE
PUSH AX
ENDIF
XOR AX,AX ;Zero
IF IBM
SETNREM:
ENDIF
POP AX
RET
; Far call to HEADFIX for TRANSIENT
THEADFIX PROC FAR
CALL HEADFIX
RET
THEADFIX ENDP
HEADFIX:
XOR BX,BX ; Clean up header
MOV CX,[IO_SAVE]
MOV DX,WORD PTR DS:[PDB_JFN_Table]
CMP CL,DL
JZ CHK1 ; Stdin matches
MOV AH,CLOSE
INT int_command
MOV DS:[PDB_JFN_Table],CL ; Restore stdin
CHK1:
INC BX
CMP CH,DH ; Stdout matches
JZ CHKOTHERHAND
MOV AH,CLOSE
INT int_command
MOV DS:[PDB_JFN_Table+1],CH ; Restore stdout
CHKOTHERHAND:
ADD BX,4 ; Skip 2,3,4
MOV CX,FilPerProc - 5 ; Already done 0,1,2,3,4
CLOSELOOP:
MOV AH,CLOSE
INT int_command
INC BX
LOOP CLOSELOOP
RET
SAVHAND:
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
PUSH DS
PUSH BX ; Set stdin to sterr, stdout to stderr
PUSH AX
MOV AH,GET_CURRENT_PDB
INT int_command ; Get user's header
MOV DS,BX
MOV AX,WORD PTR DS:[PDB_JFN_Table]
MOV [HANDLE01],AX ; Save user's stdin, stdout
MOV AL,DS:[PDB_JFN_Table+2]
MOV AH,AL
MOV WORD PTR DS:[PDB_JFN_Table],AX ; Dup stderr
POP AX
POP BX
POP DS
RET
ASSUME DS:RESGROUP
GETCOMDSK2:
CALL GETCOMDSK
JMP LODCOM1 ; Memory already allocated
RESTHAND:
PUSH DS
PUSH BX ; Restore stdin, stdout to user
PUSH AX
MOV AH,GET_CURRENT_PDB
INT int_command ; Point to user's header
MOV AX,[HANDLE01]
MOV DS,BX
ASSUME DS:NOTHING
MOV WORD PTR DS:[PDB_JFN_Table],AX ; Stuff his old 0 and 1
POP AX
POP BX
POP DS
RET
ASSUME DS:RESGROUP,SS:RESGROUP
HOPELESS:
MOV DX,OFFSET RESGROUP:NOCOM
JMP FATALC
GETCOMDSK:
MOV DX,OFFSET RESGROUP:NEEDCOM
GETCOMDSK3:
MOV AL,[COMDRV]
CALL REMCHECK
JNZ HOPELESS ;Non-removable media
CALL RPRINT
MOV DX,OFFSET RESGROUP:DRVMSG
CMP [COMDRV],0
JNZ GETCOM1
MOV DX,OFFSET RESGROUP:DEFMSG
GETCOM1:
CALL RPRINT
MOV DX,OFFSET RESGROUP:PROMPT
CALL RPRINT
CALL GetRawFlushedByte
RET
; flush world and get raw input
GetRawFlushedByte:
MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR RAW_CON_INPUT
INT int_command ; Get char without testing or echo
MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0
INT int_command
return
LOADCOM: ; Load in transient
INC BP ; Flag command read
MOV DX,OFFSET RESGROUP:COMSPEC
MOV AX,OPEN SHL 8
INT int_command ; Open COMMAND.COM
JNC READCOM
CMP AX,open_too_many_open_files
JNZ TRYDOOPEN
MOV DX,OFFSET RESGROUP:NOHANDMES
JMP FATALC ; Fatal, will never find a handle
TRYDOOPEN:
CALL GETCOMDSK
JMP SHORT LOADCOM
READCOM:
MOV BX,AX ; Handle
MOV DX,OFFSET RESGROUP:TRANSTART
XOR CX,CX ; Seek loc
MOV AX,LSEEK SHL 8
INT int_command
JC WRONGCOM1
MOV CX,OFFSET TRANGROUP:TRANSPACEEND - 100H
IF IBM
ADD CX,15
AND CX,0FFF0H
ADD CX,OFFSET EGROUP:ZEXECCODEEND
ENDIF
PUSH DS
MOV DS,[TRNSEG]
ASSUME DS:NOTHING
MOV DX,100H
MOV AH,READ
INT int_command
POP DS
ASSUME DS:RESGROUP
WRONGCOM1:
PUSHF
PUSH AX
MOV AH,CLOSE
INT int_command ; Close COMMAND.COM
POP AX
POPF
JC WRONGCOM ; If error on READ
CMP AX,CX
JZ RET10 ; Size matched
WRONGCOM:
MOV DX,OFFSET RESGROUP:COMBAD
CALL GETCOMDSK3
JMP SHORT LOADCOM ; Try again
CHKSUM: ; Compute transient checksum
PUSH DS
MOV DS,[TRNSEG]
MOV SI,100H
MOV CX,OFFSET TRANGROUP:TRANDATAEND - 100H
CHECK_SUM:
CLD
SHR CX,1
XOR DX,DX
CHK:
LODSW
ADD DX,AX
LOOP CHK
POP DS
RET10: RET
SETVECT: ; Set useful vectors
MOV DX,OFFSET RESGROUP:LODCOM
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 22H ; Set Terminate address
INT int_command
MOV DX,OFFSET RESGROUP:CONTC
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H ; Set Ctrl-C address
INT int_command
MOV DX,OFFSET RESGROUP:DSKERR
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 24H ; Set Hard Disk Error address
INT int_command
RET
CODERES ENDS
; This TAIL segment is used to produce a PARA aligned label in the resident
; group which is the location where the transient segments will be loaded
; initial.
TAIL SEGMENT PUBLIC PARA
ORG 0
TRANSTART LABEL WORD
TAIL ENDS
; This TAIL segment is used to produce a PARA aligned label in the transient
; group which is the location where the exec segments will be loaded
; initial.
TRANTAIL SEGMENT PUBLIC PARA
ORG 0
EXECSTART LABEL WORD
TRANTAIL ENDS
IF IBMVER
INCLUDE EXEC.ASM
ENDIF
END PROGSTART
+38
View File
@@ -0,0 +1,38 @@
; The following are all of the segments used in the load order
CODERES SEGMENT PUBLIC
CODERES ENDS
DATARES SEGMENT PUBLIC
DATARES ENDS
ENVIRONMENT SEGMENT PUBLIC
ENVIRONMENT ENDS
INIT SEGMENT PUBLIC
INIT ENDS
TAIL SEGMENT PUBLIC
TAIL ENDS
TRANCODE SEGMENT PUBLIC
TRANCODE ENDS
TRANDATA SEGMENT PUBLIC
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
TRANSPACE ENDS
TRANTAIL SEGMENT PUBLIC
TRANTAIL ENDS
ZEXEC_CODE SEGMENT PUBLIC
ZEXEC_CODE ENDS
ZEXEC_DATA SEGMENT PUBLIC
ZEXEC_DATA ENDS
RESGROUP GROUP CODERES,DATARES,ENVIRONMENT,INIT,TAIL
TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL
EGROUP GROUP ZEXEC_CODE,ZEXEC_DATA
+13
View File
@@ -0,0 +1,13 @@
; Use the following booleans to set assembly flags
FALSE EQU 0
TRUE EQU NOT FALSE
IBMVER EQU true ; Switch to build IBM version of Command
IBM EQU IBMVER
MSVER EQU false ; Switch to build MS-DOS version of Command
HIGHMEM EQU FALSE ; Run resident part above transient (high memory)
KANJI EQU false ; Support for dual byte Microsoft KANJI standard
IBMJAPAN EQU FALSE ;MUST BE TRUE (along with IBM and KANJI)

+579
View File
@@ -0,0 +1,579 @@
TITLE COMMAND COPY routines.
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
DATARES SEGMENT PUBLIC
EXTRN VERVAL:WORD
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN BADARGS:BYTE,BADCD:BYTE,BADSWT:BYTE,COPIED_PRE:BYTE
EXTRN COPIED_POST:BYTE
EXTRN INBDEV:BYTE,OVERWR:BYTE,FULDIR:BYTE,LOSTERR:BYTE
EXTRN NOSPACE:BYTE,DEVWMES:BYTE,NOTFND:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN MELCOPY:BYTE,SRCPT:WORD,MELSTART:WORD,SCANBUF:BYTE
EXTRN DESTFCB2:BYTE,SDIRBUF:BYTE,SRCTAIL:WORD,CFLAG:BYTE
EXTRN NXTADD:WORD,DESTCLOSED:BYTE,ALLSWITCH:WORD,ARGC:BYTE
EXTRN PLUS:BYTE,BINARY:BYTE,ASCII:BYTE,FILECNT:WORD
EXTRN WRITTEN:BYTE,CONCAT:BYTE,DESTBUF:BYTE,SRCBUF:BYTE
EXTRN SDIRBUF:BYTE,DIRBUF:BYTE,DESTFCB:BYTE,FRSTSRCH:BYTE
EXTRN FIRSTDEST:BYTE,DESTISDIR:BYTE,DESTSWITCH:WORD,STARTEL:WORD
EXTRN DESTTAIL:WORD,DESTSIZ:BYTE,DESTINFO:BYTE,INEXACT:BYTE
EXTRN CURDRV:BYTE,DESTVARS:BYTE,RESSEG:WORD,SRCSIZ:BYTE
EXTRN SRCINFO:BYTE,SRCVARS:BYTE,USERDIR1:BYTE,NOWRITE:BYTE
EXTRN RDEOF:BYTE,SRCHAND:WORD,CPDATE:WORD,CPTIME:WORD
EXTRN SRCISDEV:BYTE,BYTCNT:WORD,TPA:WORD,TERMREAD:BYTE
EXTRN DESTHAND:WORD,DESTISDEV:BYTE,DIRCHAR:BYTE
TRANSPACE ENDS
; **************************************************
; COPY CODE
;
TRANCODE SEGMENT PUBLIC BYTE
EXTRN RESTUDIR:NEAR,CERROR:NEAR,SWITCH:NEAR,DISP32BITS:NEAR
EXTRN PRINT:NEAR,TCOMMAND:NEAR,ZPRINT:NEAR,ONESPC:NEAR
EXTRN RESTUDIR1:NEAR,FCB_TO_ASCZ:NEAR,CRLF2:NEAR,SAVUDIR1:NEAR
EXTRN SETREST1:NEAR,BADCDERR:NEAR,STRCOMP:NEAR,DELIM:NEAR
EXTRN UPCONV:NEAR,PATHCHRCMP:NEAR,SCANOFF:NEAR
EXTRN CPARSE:NEAR
EXTRN SEARCH:NEAR,SEARCHNEXT:NEAR,DOCOPY:NEAR,CLOSEDEST:NEAR
EXTRN FLSHFIL:NEAR,SETASC:NEAR,BUILDNAME:NEAR,COPERR:NEAR
PUBLIC COPY,BUILDPATH,COMPNAME,ENDCOPY
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
DOMELCOPY:
cmp [MELCOPY],0FFH
jz CONTMEL
mov SI,[SRCPT]
mov [MELSTART],si
mov [MELCOPY],0FFH
CONTMEL:
xor BP,BP
mov si,[SRCPT]
mov bl,'+'
SCANSRC2:
mov di,OFFSET TRANGROUP:SCANBUF
call CPARSE
test bh,80H
jz NEXTMEL ; Go back to start
test bh,1 ; Switch ?
jnz SCANSRC2 ; Yes
call SOURCEPROC
call RESTUDIR1
mov di,OFFSET TRANGROUP:DESTFCB2
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
mov bx,OFFSET TRANGROUP:SDIRBUF + 1
mov si,OFFSET TRANGROUP:DESTFCB2 + 1
mov di,[SRCTAIL]
call BUILDNAME
jmp MELDO
NEXTMEL:
call CLOSEDEST
xor ax,ax
mov [CFLAG],al
mov [NXTADD],ax
mov [DESTCLOSED],al
mov si,[MELSTART]
mov [SRCPT],si
call SEARCHNEXT
jz SETNMELJ
jmp ENDCOPY2
SETNMELJ:
jmp SETNMEL
COPY:
; First order of buisness is to find out about the destination
ASSUME DS:TRANGROUP,ES:TRANGROUP
xor ax,ax
mov [ALLSWITCH],AX ; no switches
mov [ARGC],al ; no arguments
mov [PLUS],al ; no concatination
mov [BINARY],al ; Binary not specifically specified
mov [ASCII],al ; ASCII not specifically specified
mov [FILECNT],ax ; No files yet
mov [WRITTEN],al ; Nothing written yet
mov [CONCAT],al ; No concatination
mov [MELCOPY],al ; Not a Mel Hallerman copy
mov word ptr [SCANBUF],ax ; Init buffer
mov word ptr [DESTBUF],ax ; Init buffer
mov word ptr [SRCBUF],ax ; Init buffer
mov word ptr [SDIRBUF],ax ; Init buffer
mov word ptr [DIRBUF],ax ; Init buffer
mov word ptr [DESTFCB],ax ; Init buffer
dec ax
mov [FRSTSRCH],al ; First search call
mov [FIRSTDEST],al ; First time
mov [DESTISDIR],al ; Don't know about dest
mov si,81H
mov bl,'+' ; include '+' as a delimiter
DESTSCAN:
xor bp,bp ; no switches
mov di,offset trangroup:SCANBUF
call CPARSE
PUSHF ; save flags
test bh,80H ; A '+' argument?
jz NOPLUS ; no
mov [PLUS],1 ; yes
NOPLUS:
POPF ; get flags back
jc CHECKDONE ; Hit CR?
test bh,1 ; Switch?
jz TESTP2 ; no
or [DESTSWITCH],BP ; Yes, assume destination
or [ALLSWITCH],BP ; keep tabs on all switches
jmp short DESTSCAN
TESTP2:
test bh,80H ; Plus?
jnz GOTPLUS ; Yes, not a separate arg
inc [ARGC] ; found a real arg
GOTPLUS:
push SI
mov ax,[STARTEL]
mov SI,offset trangroup:SCANBUF ; Adjust to copy
sub ax,SI
mov DI,offset trangroup:DESTBUF
add ax,DI
mov [DESTTAIL],AX
mov [DESTSIZ],cl ; Save its size
inc cx ; Include the NUL
rep movsb ; Save potential destination
mov [DESTINFO],bh ; Save info about it
mov [DESTSWITCH],0 ; reset switches
pop SI
jmp short DESTSCAN ; keep going
CHECKDONE:
mov al,[PLUS]
mov [CONCAT],al ; PLUS -> Concatination
shl al,1
shl al,1
mov [INEXACT],al ; CONCAT -> inexact copy
mov dx,offset trangroup:BADARGS
mov al,[ARGC]
or al,al ; Good number of args?
jz CERROR4J ; no, not enough
cmp al,2
jbe ACOUNTOK
CERROR4J:
jmp CERROR ; no, too many
ACOUNTOK:
mov bp,offset trangroup:DESTVARS
cmp al,1
jnz GOT2ARGS
mov al,[CURDRV] ; Dest is default drive:*.*
add al,'A'
mov ah,':'
mov [bp.SIZ],2
mov di,offset trangroup:DESTBUF
stosw
mov [DESTSWITCH],0 ; no switches on dest
mov [bp.INFO],2 ; Flag dest is ambig
mov [bp.ISDIR],0 ; Know destination specs file
call SETSTARS
GOT2ARGS:
cmp [bp.SIZ],2
jnz NOTSHORTDEST
cmp [DESTBUF+1],':'
jnz NOTSHORTDEST ; Two char file name
or [bp.INFO],2 ; Know dest is d:
mov di,offset trangroup:DESTBUF + 2
mov [bp.ISDIR],0 ; Know destination specs file
call SETSTARS
NOTSHORTDEST:
mov di,[bp.TTAIL]
cmp byte ptr [DI],0
jnz CHKSWTCHES
mov dx,offset trangroup:BADCD
cmp byte ptr [DI-2],':'
jnz CERROR4J ; Trailing '/' error
mov [bp.ISDIR],2 ; Know destination is d:/
or [bp.INFO],6
call SETSTARS
CHKSWTCHES:
mov dx,offset trangroup:BADSWT
mov ax,[ALLSWITCH]
cmp ax,GOTSWITCH
jz CERROR4J ; Switch specified which is not known
; Now know most of the information needed about the destination
TEST AX,VSWITCH ; Verify requested?
JZ NOVERIF ; No
MOV AH,GET_VERIFY_ON_WRITE
INT int_command ; Get current setting
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
XOR AH,AH
MOV [VERVAL],AX ; Save current setting
POP DS
ASSUME DS:TRANGROUP
MOV AX,(SET_VERIFY_ON_WRITE SHL 8) OR 1 ; Set verify
INT int_command
NOVERIF:
xor bp,bp ; no switches
mov si,81H
mov bl,'+' ; include '+' as a delimiter
SCANFSRC:
mov di,offset trangroup:SCANBUF
call CPARSE ; Parse first source name
test bh,1 ; Switch?
jnz SCANFSRC ; Yes, try again
or [DESTSWITCH],bp ; Include copy wide switches on DEST
test bp,BSWITCH
jnz NOSETCASC ; Binary explicit
cmp [CONCAT],0
JZ NOSETCASC ; Not Concat
mov [ASCII],ASWITCH ; Concat -> ASCII copy if no B switch
NOSETCASC:
push SI
mov ax,[STARTEL]
mov SI,offset trangroup:SCANBUF ; Adjust to copy
sub ax,SI
mov DI,offset trangroup:SRCBUF
add ax,DI
mov [SRCTAIL],AX
mov [SRCSIZ],cl ; Save its size
inc cx ; Include the NUL
rep movsb ; Save this source
mov [SRCINFO],bh ; Save info about it
pop SI
mov ax,bp ; Switches so far
call SETASC ; Set A,B switches accordingly
call SWITCH ; Get any more switches on this arg
call SETASC ; Set
call FRSTSRC
jmp FIRSTENT
ENDCOPY:
CALL CLOSEDEST
ENDCOPY2:
MOV DX,OFFSET TRANGROUP:COPIED_PRE
CALL PRINT
MOV SI,[FILECNT]
XOR DI,DI
CALL DISP32BITS
MOV DX,OFFSET TRANGROUP:COPIED_POST
CALL PRINT
JMP TCOMMAND ; Stack could be messed up
SRCNONEXIST:
cmp [CONCAT],0
jnz NEXTSRC ; If in concat mode, ignore error
mov dx,offset trangroup:SRCBUF
call zprint
CALL ONESPC
mov dx,offset trangroup:NOTFND
jmp COPERR
SOURCEPROC:
push SI
mov ax,[STARTEL]
mov SI,offset trangroup:SCANBUF ; Adjust to copy
sub ax,SI
mov DI,offset trangroup:SRCBUF
add ax,DI
mov [SRCTAIL],AX
mov [SRCSIZ],cl ; Save its size
inc cx ; Include the NUL
rep movsb ; Save this sorce
mov [SRCINFO],bh ; Save info about it
pop SI
mov ax,bp ; Switches so far
call SETASC ; Set A,B switches accordingly
call SWITCH ; Get any more switches on this arg
call SETASC ; Set
cmp [CONCAT],0
jnz LEAVECFLAG ; Leave CFLAG if concatination
FRSTSRC:
xor ax,ax
mov [CFLAG],al ; Flag destination not created
mov [NXTADD],ax ; Zero out buffer
mov [DESTCLOSED],al ; Not created -> not closed
LEAVECFLAG:
mov [SRCPT],SI ; remember where we are
mov di,offset trangroup:USERDIR1
mov bp,offset trangroup:SRCVARS
call BUILDPATH ; Figure out everything about the source
mov si,[SRCTAIL] ; Create the search FCB
return
NEXTSRC:
cmp [PLUS],0
jnz MORECP
ENDCOPYJ2:
jmp ENDCOPY ; Done
MORECP:
xor bp,bp ; no switches
mov si,[SRCPT]
mov bl,'+' ; include '+' as a delimiter
SCANSRC:
mov di,offset trangroup:SCANBUF
call CPARSE ; Parse first source name
JC EndCopyJ2 ; if error, then end (trailing + case)
test bh,80H
jz ENDCOPYJ2 ; If no '+' we're done
test bh,1 ; Switch?
jnz SCANSRC ; Yes, try again
call SOURCEPROC
FIRSTENT:
mov di,FCB
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
mov ax,word ptr [SRCBUF] ; Get drive
cmp ah,':'
jz DRVSPEC1
mov al,'@'
DRVSPEC1:
sub al,'@'
mov ds:[FCB],al
mov ah,DIR_SEARCH_FIRST
call SEARCH
pushf ; Save result of search
call RESTUDIR1 ; Restore users dir
popf
jz NEXTAMBIG0
jmp SRCNONEXIST ; Failed
NEXTAMBIG0:
xor al,al
xchg al,[FRSTSRCH]
or al,al
jz NEXTAMBIG
SETNMEL:
mov cx,12
mov di,OFFSET TRANGROUP:SDIRBUF
mov si,OFFSET TRANGROUP:DIRBUF
rep movsb ; Save very first source name
NEXTAMBIG:
xor al,al
mov [NOWRITE],al ; Turn off NOWRITE
mov di,[SRCTAIL]
mov si,offset trangroup:DIRBUF + 1
call FCB_TO_ASCZ ; SRCBUF has complete name
MELDO:
cmp [CONCAT],0
jnz SHOWCPNAM ; Show name if concat
test [SRCINFO],2 ; Show name if multi
jz DOREAD
SHOWCPNAM:
mov dx,offset trangroup:SRCBUF
call ZPRINT
call CRLF2
DOREAD:
call DOCOPY
cmp [CONCAT],0
jnz NODCLOSE ; If concat, do not close
call CLOSEDEST ; else close current destination
jc NODCLOSE ; Concat flag got set, close didn't really happen
mov [CFLAG],0 ; Flag destination not created
NODCLOSE:
cmp [CONCAT],0 ; Check CONCAT again
jz NOFLUSH
CALL FLSHFIL ; Flush output between source files on CONCAT
; so LOSTERR stuff works correctly
TEST [MELCOPY],0FFH
jz NOFLUSH
jmp DOMELCOPY
NOFLUSH:
call SEARCHNEXT ; Try next match
jnz NEXTSRCJ ; Finished with this source spec
mov [DESTCLOSED],0 ; Not created or concat -> not closed
jmp NEXTAMBIG ; Do next ambig
NEXTSRCJ:
jmp NEXTSRC
BUILDPATH:
test [BP.INFO],2
jnz NOTPFILE ; If ambig don't bother with open
mov dx,bp
add dx,BUF ; Set DX to spec
mov ax,OPEN SHL 8
INT int_command
jc NOTPFILE
mov bx,ax ; Is pure file
mov ax,IOCTL SHL 8
INT int_command
mov ah,CLOSE
INT int_command
test dl,devid_ISDEV
jnz ISADEV ; If device, done
test [BP.INFO],4
jz ISSIMPFILE ; If no path seps, done
NOTPFILE:
mov dx,word ptr [BP.BUF]
cmp dh,':'
jz DRVSPEC5
mov dl,'@'
DRVSPEC5:
sub dl,'@' ; A = 1
call SAVUDIR1
mov dx,bp
add dx,BUF ; Set DX for upcomming CHDIRs
mov bh,[BP.INFO]
and bh,6
cmp bh,6 ; Ambig and path ?
jnz CHECKAMB ; jmp if no
mov si,[BP.TTAIL]
cmp byte ptr [si-2],':'
jnz KNOWNOTSPEC
mov [BP.ISDIR],2 ; Know is d:/file
jmp short DOPCDJ
KNOWNOTSPEC:
mov [BP.ISDIR],1 ; Know is path/file
dec si ; Point to the /
DOPCDJ:
jmp short DOPCD
CHECKAMB:
cmp bh,2
jnz CHECKCD
ISSIMPFILE:
ISADEV:
mov [BP.ISDIR],0 ; Know is file since ambig but no path
return
CHECKCD:
call SETREST1
mov ah,CHDIR
INT int_command
jc NOTPDIR
mov di,dx
xor ax,ax
mov cx,ax
dec cx
repne scasb
dec di
mov al,[DIRCHAR]
mov [bp.ISDIR],2 ; assume d:/file
cmp al,[di-1]
jz GOTSRCSLSH
stosb
mov [bp.ISDIR],1 ; know path/file
GOTSRCSLSH:
or [bp.INFO],6
call SETSTARS
return
NOTPDIR:
mov [bp.ISDIR],0 ; assume pure file
mov bh,[bp.INFO]
test bh,4
retz ; Know pure file, no path seps
mov [bp.ISDIR],2 ; assume d:/file
mov si,[bp.TTAIL]
cmp byte ptr [si],0
jz BADCDERRJ2 ; Trailing '/'
cmp byte ptr [si],'.'
jz BADCDERRJ2 ; If . or .. pure cd should have worked
cmp byte ptr [si-2],':'
jz DOPCD ; Know d:/file
mov [bp.ISDIR],1 ; Know path/file
dec si ; Point at last '/'
DOPCD:
xor bl,bl
xchg bl,[SI] ; Stick in a NUL
call SETREST1
mov ah,CHDIR
INT int_command
xchg bl,[SI]
retnc
BADCDERRJ2:
JMP BADCDERR
SETSTARS:
mov [bp.TTAIL],DI
add [bp.SIZ],12
mov ax,('.' SHL 8) OR '?'
mov cx,8
rep stosb
xchg al,ah
stosb
xchg al,ah
mov cl,3
rep stosb
xor al,al
stosb
return
COMPNAME:
PUSH CX
PUSH AX
MOV si,offset trangroup:SRCBUF
MOV di,offset trangroup:DESTBUF
MOV CL,[CURDRV]
MOV CH,CL
CMP BYTE PTR [SI+1],':'
JNZ NOSRCDRV
LODSW
SUB AL,'A'
MOV CL,AL
NOSRCDRV:
CMP BYTE PTR [DI+1],':'
JNZ NODSTDRV
MOV AL,[DI]
INC DI
INC DI
SUB AL,'A'
MOV CH,AL
NODSTDRV:
CMP CH,CL
jnz RET81P
call STRCOMP
jz RET81P
mov ax,[si-1]
mov cx,[di-1]
push ax
and al,cl
pop ax
jnz RET81P ; Niether of the mismatch chars was a NUL
; Know one of the mismatch chars is a NUL
; Check for ".NUL" compared with NUL
cmp al,'.'
jnz CHECKCL
or ah,ah
jmp short RET81P ; If NUL return match, else no match
CHECKCL:
cmp cl,'.'
jnz RET81P ; Mismatch
or ch,ch ; If NUL return match, else no match
RET81P:
POP AX
POP CX
return
TRANCODE ENDS
END
+526
View File
@@ -0,0 +1,526 @@
TITLE COPYRPOC ;Procedures called by COPY
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
DATARES SEGMENT PUBLIC
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN OVERWR:BYTE,FULDIR:BYTE,LOSTERR:BYTE
EXTRN DEVWMES:BYTE,INBDEV:BYTE,NOSPACE:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN CFLAG:BYTE,NXTADD:WORD,DESTCLOSED:BYTE
EXTRN PLUS:BYTE,BINARY:BYTE,ASCII:BYTE,FILECNT:WORD
EXTRN WRITTEN:BYTE,CONCAT:BYTE,DESTBUF:BYTE,SRCBUF:BYTE
EXTRN SDIRBUF:BYTE,DIRBUF:BYTE,DESTFCB:BYTE,MELCOPY:BYTE
EXTRN FIRSTDEST:BYTE,DESTISDIR:BYTE,DESTSWITCH:WORD
EXTRN DESTTAIL:WORD,DESTINFO:BYTE,INEXACT:BYTE
EXTRN DESTVARS:BYTE,SRCINFO:BYTE,RDEOF:BYTE
EXTRN USERDIR1:BYTE,NOWRITE:BYTE
EXTRN SRCHAND:WORD,CPDATE:WORD,CPTIME:WORD
EXTRN SRCISDEV:BYTE,BYTCNT:WORD,TPA:WORD,TERMREAD:BYTE
EXTRN DESTHAND:WORD,DESTISDEV:BYTE,DIRCHAR:BYTE
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
PUBLIC SEARCH,SEARCHNEXT,DOCOPY,CLOSEDEST,FLSHFIL,SETASC
PUBLIC BUILDNAME,COPERR
EXTRN PRINT:NEAR,BUILDPATH:NEAR,RESTUDIR1:NEAR
EXTRN COMPNAME:NEAR,ENDCOPY:NEAR
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
SEARCHNEXT:
MOV AH,DIR_SEARCH_NEXT
TEST [SRCINFO],2
JNZ SEARCH ; Do serach-next if ambig
OR AH,AH ; Reset zero flag
return
SEARCH:
PUSH AX
MOV AH,SET_DMA
MOV DX,OFFSET TRANGROUP:DIRBUF
INT int_command ; Put result of search in DIRBUF
POP AX ; Restore search first/next command
MOV DX,FCB
INT int_command ; Do the search
OR AL,AL
return
DOCOPY:
mov [RDEOF],0 ; No EOF yet
mov dx,offset trangroup:SRCBUF
mov ax,OPEN SHL 8
INT int_command
retc ; If open fails, ignore
mov bx,ax ; Save handle
mov [SRCHAND],bx ; Save handle
mov ax,(FILE_TIMES SHL 8)
INT int_command
mov [CPDATE],dx ; Save DATE
mov [CPTIME],cx ; Save TIME
mov ax,(IOCTL SHL 8)
INT int_command ; Get device stuff
and dl,devid_ISDEV
mov [SRCISDEV],dl ; Set source info
jz COPYLP ; Source not a device
cmp [BINARY],0
jz COPYLP ; ASCII device OK
mov dx,offset trangroup:INBDEV ; Cannot do binary input
jmp COPERR
COPYLP:
mov bx,[SRCHAND]
mov cx,[BYTCNT]
mov dx,[NXTADD]
sub cx,dx ; Compute available space
jnz GOTROOM
call FLSHFIL
CMP [TERMREAD],0
JNZ CLOSESRC ; Give up
mov cx,[BYTCNT]
GOTROOM:
push ds
mov ds,[TPA]
ASSUME DS:NOTHING
mov ah,READ
INT int_command
pop ds
ASSUME DS:TRANGROUP
jc CLOSESRC ; Give up if error
mov cx,ax ; Get count
jcxz CLOSESRC ; No more to read
cmp [SRCISDEV],0
jnz NOTESTA ; Is a device, ASCII mode
cmp [ASCII],0
jz BINREAD
NOTESTA:
MOV DX,CX
MOV DI,[NXTADD]
MOV AL,1AH
PUSH ES
MOV ES,[TPA]
REPNE SCASB ; Scan for EOF
POP ES
JNZ USEALL
INC [RDEOF]
INC CX
USEALL:
SUB DX,CX
MOV CX,DX
BINREAD:
ADD CX,[NXTADD]
MOV [NXTADD],CX
CMP CX,[BYTCNT] ; Is buffer full?
JB TESTDEV ; If not, we may have found EOF
CALL FLSHFIL
CMP [TERMREAD],0
JNZ CLOSESRC ; Give up
JMP SHORT COPYLP
TESTDEV:
cmp [SRCISDEV],0
JZ CLOSESRC ; If file then EOF
CMP [RDEOF],0
JZ COPYLP ; On device, go till ^Z
CLOSESRC:
mov bx,[SRCHAND]
mov ah,CLOSE
INT int_command
return
CLOSEDEST:
cmp [DESTCLOSED],0
retnz ; Don't double close
MOV AL,BYTE PTR [DESTSWITCH]
CALL SETASC ; Check for B or A switch on destination
JZ BINCLOS
MOV BX,[NXTADD]
CMP BX,[BYTCNT] ; Is memory full?
JNZ PUTZ
call TRYFLUSH ; Make room for one lousy byte
jz NOCONC
CONCHNG: ; Concat flag changed on us
stc
return
NOCONC:
XOR BX,BX
PUTZ:
PUSH DS
MOV DS,[TPA]
MOV WORD PTR [BX],1AH ; Add End-of-file mark (Ctrl-Z)
POP DS
INC [NXTADD]
MOV [NOWRITE],0 ; Make sure our ^Z gets written
MOV AL,[WRITTEN]
XOR AH,AH
ADD AX,[NXTADD]
JC BINCLOS ; > 1
CMP AX,1
JZ FORGETIT ; WRITTEN = 0 NXTADD = 1 (the ^Z)
BINCLOS:
call TRYFLUSH
jnz CONCHNG
cmp [WRITTEN],0
jz FORGETIT ; Never wrote nothin
MOV BX,[DESTHAND]
MOV CX,[CPTIME]
MOV DX,[CPDATE]
CMP [INEXACT],0 ; Copy not exact?
JZ DODCLOSE ; If no, copy date & time
MOV AH,GET_TIME
INT int_command
SHL CL,1
SHL CL,1 ; Left justify min in CL
SHL CX,1
SHL CX,1
SHL CX,1 ; hours to high 5 bits, min to 5-10
SHR DH,1 ; Divide seconds by 2 (now 5 bits)
OR CL,DH ; And stick into low 5 bits of CX
PUSH CX ; Save packed time
MOV AH,GET_DATE
INT int_command
SUB CX,1980
XCHG CH,CL
SHL CX,1 ; Year to high 7 bits
SHL DH,1 ; Month to high 3 bits
SHL DH,1
SHL DH,1
SHL DH,1
SHL DH,1 ; Most sig bit of month in carry
ADC CH,0 ; Put that bit next to year
OR DL,DH ; Or low three of month into day
MOV DH,CH ; Get year and high bit of month
POP CX ; Get time back
DODCLOSE:
MOV AX,(FILE_TIMES SHL 8) OR 1
INT int_command ; Set date and time
MOV AH,CLOSE
INT int_command
INC [FILECNT]
INC [DESTCLOSED]
RET50:
CLC
return
FORGETIT:
MOV BX,[DESTHAND]
CALL DODCLOSE ; Close the dest
MOV DX,OFFSET TRANGROUP:DESTBUF
MOV AH,UNLINK
INT int_command ; And delete it
MOV [FILECNT],0 ; No files transferred
JMP RET50
TRYFLUSH:
mov al,[CONCAT]
push ax
call FLSHFIL
pop ax
cmp al,[CONCAT]
return
FLSHFIL:
; Write out any data remaining in memory.
; Inputs:
; [NXTADD] = No. of bytes to write
; [CFLAG] <>0 if file has been created
; Outputs:
; [NXTADD] = 0
MOV [TERMREAD],0
cmp [CFLAG],0
JZ NOTEXISTS
JMP EXISTS
NOTEXISTS:
call BUILDDEST ; Find out all about the destination
CALL COMPNAME ; Source and dest. the same?
JNZ PROCDEST ; If not, go ahead
CMP [SRCISDEV],0
JNZ PROCDEST ; Same name on device OK
CMP [CONCAT],0 ; Concatenation?
MOV DX,OFFSET TRANGROUP:OVERWR
JZ COPERRJ ; If not, overwrite error
MOV [NOWRITE],1 ; Flag not writting (just seeking)
PROCDEST:
mov ax,(OPEN SHL 8) OR 1
CMP [NOWRITE],0
JNZ DODESTOPEN ; Don't actually create if NOWRITE set
mov ah,CREAT
xor cx,cx
DODESTOPEN:
mov dx,offset trangroup:DESTBUF
INT int_command
MOV DX,OFFSET TRANGROUP:FULDIR
JC COPERRJ
mov [DESTHAND],ax ; Save handle
mov [CFLAG],1 ; Destination now exists
mov bx,ax
mov ax,(IOCTL SHL 8)
INT int_command ; Get device stuff
mov [DESTISDEV],dl ; Set dest info
test dl,devid_ISDEV
jz EXISTS ; Dest not a device
mov al,BYTE PTR [DESTSWITCH]
AND AL,ASWITCH+BSWITCH
JNZ TESTBOTH
MOV AL,[ASCII] ; Neither set, use current setting
OR AL,[BINARY]
JZ EXSETA ; Neither set, default to ASCII
TESTBOTH:
JPE EXISTS ; Both are set, ignore
test AL,BSWITCH
jz EXISTS ; Leave in cooked mode
mov ax,(IOCTL SHL 8) OR 1
xor dh,dh
or dl,devid_RAW
mov [DESTISDEV],dl ; New value
INT int_command ; Set device to RAW mode
jmp short EXISTS
COPERRJ:
jmp SHORT COPERR
EXSETA:
; What we read in may have been in binary mode, flag zapped write OK
mov [ASCII],ASWITCH ; Set ASCII mode
or [INEXACT],ASWITCH ; ASCII -> INEXACT
EXISTS:
cmp [NOWRITE],0
jnz NOCHECKING ; If nowrite don't bother with name check
CALL COMPNAME ; Source and dest. the same?
JNZ NOCHECKING ; If not, go ahead
CMP [SRCISDEV],0
JNZ NOCHECKING ; Same name on device OK
; At this point we know in append (would have gotten overwrite error on first
; destination create otherwise), and user trying to specify destination which
; has been scribbled already (if dest had been named first, NOWRITE would
; be set).
MOV DX,OFFSET TRANGROUP:LOSTERR ; Tell him he's not going to get it
CALL PRINT
MOV [NXTADD],0 ; Set return
INC [TERMREAD] ; Tell Read to give up
RET60:
return
NOCHECKING:
mov bx,[DESTHAND] ; Get handle
XOR CX,CX
XCHG CX,[NXTADD]
JCXZ RET60 ; If Nothing to write, forget it
INC [WRITTEN] ; Flag that we wrote something
CMP [NOWRITE],0 ; If NOWRITE set, just seek CX bytes
JNZ SEEKEND
XOR DX,DX
PUSH DS
MOV DS,[TPA]
ASSUME DS:NOTHING
MOV AH,WRITE
INT int_command
POP DS
ASSUME DS:TRANGROUP
MOV DX,OFFSET TRANGROUP:NOSPACE
JC COPERR ; Failure
sub cx,ax
retz ; Wrote all supposed to
test [DESTISDEV],devid_ISDEV
jz COPERR ; Is a file, error
test [DESTISDEV],devid_RAW
jnz DEVWRTERR ; Is a raw device, error
cmp [INEXACT],0
retnz ; INEXACT so OK
dec cx
retz ; Wrote one byte less (the ^Z)
DEVWRTERR:
MOV DX,OFFSET TRANGROUP:DEVWMES
COPERR:
CALL PRINT
inc [DESTCLOSED]
cmp [CFLAG],0
jz ENDCOPYJ ; Never actually got it open
MOV bx,[DESTHAND]
MOV AH,CLOSE ; Close the file
INT int_command
MOV DX,OFFSET TRANGROUP:DESTBUF
MOV AH,UNLINK
INT int_command ; And delete it
MOV [CFLAG],0
ENDCOPYJ:
JMP ENDCOPY
SEEKEND:
xor dx,dx ; Zero high half of offset
xchg dx,cx ; cx:dx is seek location
mov ax,(LSEEK SHL 8) OR 1
INT int_command ; Seek ahead in the file
cmp [RDEOF],0
retz
; If a ^Z has been read we must set the file size to the current
; file pointer location
MOV AH,WRITE
INT int_command ; CX is zero, truncates file
return
SETASC:
; Given switch vector in AX,
; Set ASCII switch if A is set
; Clear ASCII switch if B is set
; BINARY set if B specified
; Leave ASCII unchanged if neither or both are set
; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set
AND AL,ASWITCH+BSWITCH
JPE LOADSW ; PE means both or neither are set
PUSH AX
AND AL,BSWITCH
MOV [BINARY],AL
POP AX
AND AL,ASWITCH
MOV [ASCII],AL
OR [INEXACT],AL
LOADSW:
MOV AL,[ASCII]
OR AL,AL
return
BUILDDEST:
cmp [DESTISDIR],-1
jnz KNOWABOUTDEST ; Already done the figuring
MOV DI,OFFSET TRANGROUP:USERDIR1
mov bp,offset trangroup:DESTVARS
call BUILDPATH
call RESTUDIR1
; Now know all about the destination
KNOWABOUTDEST:
xor al,al
xchg al,[FIRSTDEST]
or al,al
jnz FIRSTDST
jmp NOTFIRSTDEST
FIRSTDST:
mov si,[DESTTAIL] ; Create an FCB of the original DEST
mov di,offset trangroup:DESTFCB
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
mov ax,word ptr [DESTBUF] ; Get drive
cmp ah,':'
jz DRVSPEC4
mov al,'@'
DRVSPEC4:
MOV CL,[ASCII] ; Save current ASCII setting
sub al,'@'
mov [DESTFCB],al
mov al,[DESTINFO]
mov ah,[SRCINFO]
and ax,0202H
or al,al
jz NOTMELCOPY
cmp al,ah
jnz NOTMELCOPY
cmp [PLUS],0
jz NOTMELCOPY
inc [MELCOPY] ; ambig source, ambig dest, and pluses
xor al,al
jmp short SETCONC
NOTMELCOPY:
xor al,2 ; al=2 if unambig dest, =0 if ambig dest
and al,ah
shr al,1 ; al=1 if unambig dest AND ambig sorce
; Implies concatination
SETCONC:
or al,[PLUS] ; al=1 if concat
mov [CONCAT],al
shl al,1
shl al,1
mov [INEXACT],al ; Concat -> inexact copy
cmp [BINARY],0
jnz NOTFIRSTDEST ; Binary explicitly given, all OK
mov [ASCII],al ; Concat -> ASCII
or cl,cl
jnz NOTFIRSTDEST ; ASCII flag set before, DATA read correctly
or al,al
JZ NOTFIRSTDEST ; ASCII flag did not change states
; At this point there may already be binary read data in the read buffer.
; We need to find the first ^Z (if there is one) and trim the amount
; of data in the buffer correctly.
MOV CX,[NXTADD]
JCXZ NOTFIRSTDEST ; No data, everything OK
MOV AL,1AH
PUSH ES
XOR DI,DI
MOV ES,[TPA]
REPNE SCASB ; Scan for EOF
POP ES
JNZ NOTFIRSTDEST ; No ^Z in buffer, everything OK
DEC DI ; Point at ^Z
MOV [NXTADD],DI ; New buffer
NOTFIRSTDEST:
mov bx,offset trangroup:DIRBUF+1 ; Source of replacement chars
cmp [CONCAT],0
jz GOTCHRSRC ; Not a concat
mov bx,offset trangroup:SDIRBUF+1 ; Source of replacement chars
GOTCHRSRC:
mov si,offset trangroup:DESTFCB+1 ; Original dest name
mov di,[DESTTAIL] ; Where to put result
BUILDNAME:
mov cx,8
BUILDMAIN:
lodsb
cmp al,"?"
jnz NOTAMBIG
mov al,byte ptr [BX]
NOTAMBIG:
cmp al,' '
jz NOSTORE
stosb
NOSTORE:
inc bx
loop BUILDMAIN
mov cl,3
cmp byte ptr [SI],' '
jz ENDDEST ; No extension
mov al,'.'
stosb
BUILDEXT:
lodsb
cmp al,"?"
jnz NOTAMBIGE
mov al,byte ptr [BX]
NOTAMBIGE:
cmp al,' '
jz NOSTOREE
stosb
NOSTOREE:
inc bx
loop BUILDEXT
ENDDEST:
xor al,al
stosb ; NUL terminate
return
TRANCODE ENDS
END
+291
View File
@@ -0,0 +1,291 @@
TITLE CPARSE
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
DATARES SEGMENT PUBLIC
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN BADCPMES:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN CURDRV:BYTE,ELPOS:BYTE,STARTEL:WORD
EXTRN SKPDEL:BYTE,SWITCHAR:BYTE,ELCNT:BYTE
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP
EXTRN DELIM:NEAR,UPCONV:NEAR,PATHCHRCMP:NEAR
EXTRN SWLIST:BYTE,BADCDERR:NEAR,SCANOFF:NEAR,CERROR:NEAR
if KANJI
EXTRN TESTKANJ:NEAR
endif
SWCOUNT EQU 5
PUBLIC CPARSE
CPARSE:
;-----------------------------------------------------------------------;
; ENTRY: ;
; DS:SI Points input buffer ;
; ES:DI Points to the token buffer ;
; BL Special delimiter for this call ;
; Always checked last ;
; set it to space if there is no special delimiter ;
; EXIT: ;
; DS:SI Points to next char in the input buffer ;
; ES:DI Points to the token buffer ;
; [STARTEL] Points to start of last element of path in token ;
; points to a NUL for no element strings 'd:' 'd:/' ;
; CX Character count ;
; BH Condition Code ;
; Bit 1H of BH set if switch character ;
; Token buffer contains char after ;
; switch character ;
; BP has switch bits set (ORing only) ;
; Bit 2H of BH set if ? or * in token ;
; if * found element ? filled ;
; Bit 4H of BH set if path sep in token ;
; Bit 80H of BH set if the special delimiter ;
; was skipped at the start of this token ;
; Token buffer always starts d: for non switch tokens ;
; CARRY SET ;
; if CR on input ;
; token buffer not altered ;
; ;
; DOES NOT RETURN ON BAD PATH ERROR ;
; MODIFIES: ;
; CX, SI, AX, BH, DX and the Carry Flag ; ;
; ;
; -----------------------------------------------------------------------;
xor ax,ax
mov [STARTEL],DI ; No path element (Is DI correct?)
mov [ELPOS],al ; Start in 8 char prefix
mov [SKPDEL],al ; No skip delimiter yet
mov bh,al ; Init nothing
pushf ; save flags
push di ; save the token buffer addrss
xor cx,cx ; no chars in token buffer
moredelim:
LODSB
CALL DELIM
JNZ SCANCDONE
CMP AL,' '
JZ moredelim
CMP AL,9
JZ moredelim
xchg al,[SKPDEL]
or al,al
jz moredelim ; One non space/tab delimiter allowed
JMP x_done ; Nul argument
SCANCDONE:
IF NOT KANJI
call UPCONV
ENDIF
cmp al,bl ; Special delimiter?
jnz nospec
or bh,80H
jmp short moredelim
nospec:
cmp al,0DH ; a CR?
jne ncperror
jmp cperror
ncperror:
cmp al,[SWITCHAR] ; is the char the switch char?
jne na_switch ; yes, process...
jmp a_switch
na_switch:
cmp byte ptr [si],':'
jne anum_chard ; Drive not specified
IF KANJI
call UPCONV
ENDIF
call move_char
lodsb ; Get the ':'
call move_char
mov [STARTEL],di
mov [ELCNT],0
jmp anum_test
anum_chard:
mov [STARTEL],di
mov [ELCNT],0 ; Store of this char sets it to one
call PATHCHRCMP ; Starts with a pathchar?
jnz anum_char ; no
push ax
mov al,[CURDRV] ; Insert drive spec
add al,'A'
call move_char
mov al,':'
call move_char
pop ax
mov [STARTEL],di
mov [ELCNT],0
anum_char:
IF KANJI
call TESTKANJ
jz TESTDOT
call move_char
lodsb
jmp short notspecial
TESTDOT:
ENDIF
cmp al,'.'
jnz testquest
inc [ELPOS] ; flag in extension
mov [ELCNT],0FFH ; Store of the '.' resets it to 0
testquest:
cmp al,'?'
jnz testsplat
or bh,2
testsplat:
cmp al,'*'
jnz testpath
or bh,2
mov ah,7
cmp [ELPOS],0
jz gotelcnt
mov ah,2
gotelcnt:
mov al,'?'
sub ah,[ELCNT]
jc badperr2
xchg ah,cl
jcxz testpathx
qmove:
xchg ah,cl
call move_char
xchg ah,cl
loop qmove
testpathx:
xchg ah,cl
testpath:
call PATHCHRCMP
jnz notspecial
or bh,4
test bh,2 ; If just hit a '/', cannot have ? or * yet
jnz badperr
mov [STARTEL],di ; New element
INC [STARTEL] ; Point to char after /
mov [ELCNT],0FFH ; Store of '/' sets it to 0
mov [ELPOS],0
notspecial:
call move_char ; just an alphanum string
anum_test:
lodsb
IF NOT KANJI
call UPCONV
ENDIF
call DELIM
je x_done
cmp al,0DH
je x_done
cmp al,[SWITCHAR]
je x_done
cmp al,bl
je x_done
cmp al,':' ; ':' allowed as trailer because
; of devices
IF KANJI
je FOO15
jmp anum_char
FOO15:
ELSE
jne anum_char
ENDIF
mov byte ptr [si-1],' ' ; Change the trailing ':' to a space
jmp short x_done
badperr2:
mov dx,offset trangroup:BADCPMES
jmp CERROR
badperr:
jmp BADCDERR
cperror:
dec si ; adjust the pointer
pop di ; retrive token buffer address
popf ; restore flags
stc ; set the carry bit
return
x_done:
dec si ; adjust for next round
jmp short out_token
a_switch:
OR BH,1 ; Indicate switch
OR BP,GOTSWITCH
CALL SCANOFF
INC SI
cmp al,0DH
je cperror
call move_char ; store the character
CALL UPCONV
PUSH ES
PUSH DI
PUSH CX
PUSH CS
POP ES
ASSUME ES:TRANGROUP
MOV DI,OFFSET TRANGROUP:SWLIST
MOV CX,SWCOUNT
REPNE SCASB
JNZ out_tokenp
MOV AX,1
SHL AX,CL
OR BP,AX
out_tokenp:
POP CX
POP DI
POP ES
ASSUME ES:NOTHING
out_token:
mov al,0
stosb ; null at the end
pop di ; restore token buffer pointer
popf
clc ; clear carry flag
return
move_char:
stosb ; store char in token buffer
inc cx ; increment char count
inc [ELCNT] ; increment element count for * substi
return
TRANCODE ENDS
END
+468
View File
@@ -0,0 +1,468 @@
;
; ^C status routines for MSDOS
;
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
i_need DevIOBuf,BYTE
i_need DidCTRLC,BYTE
i_need INDOS,BYTE
i_need DSKSTCOM,BYTE
i_need DSKSTCALL,BYTE
i_need DSKSTST,WORD
i_need BCON,DWORD
i_need DSKCHRET,BYTE
i_need DSKSTCNT,WORD
i_need IDLEINT,BYTE
i_need CONSWAP,BYTE
i_need user_SS,WORD
i_need user_SP,WORD
i_need ERRORMODE,BYTE
i_need ConC_spSave,WORD
i_need Exit_type,BYTE
i_need PFLAG,BYTE
i_need ExitHold,DWORD
i_need WPErr,BYTE
i_need ReadOp,BYTE
i_need CONTSTK,WORD
i_need Exit_Code,WORD
i_need CurrentPDB,WORD
i_need DIVMES,BYTE
i_need DivMesLen,BYTE
SUBTTL Checks for ^C in CON I/O
PAGE
ASSUME DS:NOTHING,ES:NOTHING
procedure DSKSTATCHK,NEAR ; Check for ^C if only one level in
CMP BYTE PTR [INDOS],1
retnz ; Do NOTHING
PUSH CX
PUSH ES
PUSH BX
PUSH DS
PUSH SI
PUSH CS
POP ES
PUSH CS
POP DS
ASSUME DS:DOSGROUP
XOR CX,CX
MOV BYTE PTR [DSKSTCOM],DEVRDND
MOV BYTE PTR [DSKSTCALL],DRDNDHL
MOV [DSKSTST],CX
MOV BX,OFFSET DOSGROUP:DSKSTCALL
LDS SI,[BCON]
ASSUME DS:NOTHING
invoke DEVIOCALL2
TEST [DSKSTST],STBUI
JNZ ZRET ; No characters available
MOV AL,BYTE PTR [DSKCHRET]
DSK1:
CMP AL,"C"-"@"
JNZ RET36
MOV BYTE PTR [DSKSTCOM],DEVRD
MOV BYTE PTR [DSKSTCALL],DRDWRHL
MOV BYTE PTR [DSKCHRET],CL
MOV [DSKSTST],CX
INC CX
MOV [DSKSTCNT],CX
invoke DEVIOCALL2 ; Eat the ^C
POP SI
POP DS
POP BX ; Clean stack
POP ES
POP CX
JMP SHORT CNTCHAND
ZRET:
XOR AL,AL ; Set zero
RET36:
POP SI
POP DS
POP BX
POP ES
POP CX
return
NOSTOP:
CMP AL,"P"-"@"
JZ INCHK
IF NOT TOGLPRN
CMP AL,"N"-"@"
JZ INCHK
ENDIF
CMP AL,"C"-"@"
JZ INCHK
return
DSKSTATCHK ENDP
procedure SPOOLINT,NEAR
PUSHF
CMP BYTE PTR [IDLEINT],0
JZ POPFRET
CMP BYTE PTR [ERRORMODE],0
JNZ POPFRET ;No spool ints in error mode
INT int_spooler
POPFRET:
POPF
RET18: return
SPOOLINT ENDP
procedure STATCHK,NEAR
invoke DSKSTATCHK ; Allows ^C to be detected under
; input redirection
PUSH BX
XOR BX,BX
invoke GET_IO_FCB
POP BX
JC RET18
MOV AH,1
invoke IOFUNC
JZ SPOOLINT
CMP AL,'S'-'@'
JNZ NOSTOP
XOR AH,AH
invoke IOFUNC ; Eat Cntrl-S
JMP SHORT PAUSOSTRT
PRINTOFF:
PRINTON:
NOT BYTE PTR [PFLAG]
return
PAUSOLP:
CALL SPOOLINT
PAUSOSTRT:
MOV AH,1
invoke IOFUNC
JZ PAUSOLP
INCHK:
PUSH BX
XOR BX,BX
invoke GET_IO_FCB
POP BX
JC RET18
XOR AH,AH
invoke IOFUNC
CMP AL,'P'-'@'
JZ PRINTON
IF NOT TOGLPRN
CMP AL,'N'-'@'
JZ PRINTOFF
ENDIF
CMP AL,'C'-'@'
retnz
STATCHK ENDP
procedure CNTCHAND,NEAR
; Ctrl-C handler.
; "^C" and CR/LF is printed. Then the user registers are restored and
; the user CTRL-C handler is executed. At this point the top of the stack
; has 1) the interrupt return address should the user CTRL-C handler wish
; to allow processing to continue; 2) the original interrupt return address
; to the code that performed the function call in the first place. If
; the user CTRL-C handler wishes to continue, it must leave all registers
; unchanged and RET (not IRET) with carry CLEAR. If carry is SET then
; an terminate system call is simulated.
MOV AL,3 ; Display "^C"
invoke BUFOUT
invoke CRLF
PUSH SS
POP DS
ASSUME DS:DOSGROUP
CMP BYTE PTR [CONSWAP],0
JZ NOSWAP
invoke SWAPBACK
NOSWAP:
CLI ; Prepare to play with stack
MOV SP,[user_SP]
MOV SS,[user_SS] ; User stack now restored
ASSUME SS:NOTHING
invoke restore_world ; User registers now restored
ASSUME DS:NOTHING
MOV BYTE PTR [INDOS],0 ; Go to known state
MOV BYTE PTR [ERRORMODE],0
MOV [ConC_spsave],SP ; save his SP
INT int_ctrl_c ; Execute user Ctrl-C handler
MOV [user_SS],AX ; save the AX
PUSHF ; and the flags (maybe new call)
POP AX
CMP SP,[ConC_spsave]
JNZ ctrlc_try_new ; new syscall maybe?
ctrlc_repeat:
MOV AX,[user_SS] ; no...
transfer COMMAND ; Repeat command otherwise
ctrlc_try_new:
SUB [ConC_spsave],2 ; Are there flags on the stack?
CMP SP,[ConC_spsave]
JZ ctrlc_new ; yes, new system call
ctrlc_abort:
MOV AX,(EXIT SHL 8) + 0
MOV BYTE PTR [DidCTRLC],0FFh
transfer COMMAND ; give up by faking $EXIT
ctrlc_new:
PUSH AX
POPF
POP [user_SS]
JNC ctrlc_repeat ; repeat operation
JMP ctrlc_abort ; indicate ^ced
CNTCHAND ENDP
SUBTTL DIVISION OVERFLOW INTERRUPT
PAGE
; Default handler for division overflow trap
procedure DIVOV,NEAR
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
MOV SI,OFFSET DOSGROUP:DIVMES
CALL RealDivOv
JMP ctrlc_abort ; Use Ctrl-C abort on divide overflow
DIVOV ENDP
;
; RealDivOv: perform actual divide overflow stuff.
; Inputs: none
; Outputs: message to BCON
;
procedure RealDivOv,NEAR ; Do divide overflow and clock process
PUSH CS ; get ES addressability
POP ES
PUSH CS ; get DS addressability
POP DS
ASSUME DS:DOSGROUP
MOV BYTE PTR [DskStCom],DevWrt
MOV BYTE PTR [DskStCall],DRdWrHL
MOV [DskSTST],0
MOV BL,[DivMesLen]
XOR BH,BH
MOV [DskStCnt],BX
MOV BX,OFFSET DOSGROUP:DskStCall
MOV WORD PTR [DskChRet+1],SI ; transfer address (need an EQU)
LDS SI,[BCON]
ASSUME DS:NOTHING
invoke DEVIOCALL2
MOV WORD PTR [DskChRet+1],OFFSET DOSGROUP:DevIOBuf
MOV [DskStCnt],1
return
RealDivOv ENDP
SUBTTL CHARHRD,HARDERR,ERROR -- HANDLE DISK ERRORS AND RETURN TO USER
PAGE
procedure CHARHARD,NEAR
ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
; Character device error handler
; Same function as HARDERR
MOV WORD PTR [EXITHOLD+2],ES
MOV WORD PTR [EXITHOLD],BP
PUSH SI
AND DI,STECODE
MOV BP,DS ;Device pointer is BP:SI
CALL FATALC
POP SI
return
CHARHARD ENDP
procedure HardErr,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Hard disk error handler. Entry conditions:
; DS:BX = Original disk transfer address
; DX = Original logical sector number
; CX = Number of sectors to go (first one gave the error)
; AX = Hardware error code
; DI = Original sector transfer count
; ES:BP = Base of drive parameters
; [READOP] = 0 for read, 1 for write
;
XCHG AX,DI ; Error code in DI, count in AX
AND DI,STECODE ; And off status bits
CMP DI,WRECODE ; Write Protect Error?
JNZ NOSETWRPERR
PUSH AX
MOV AL,ES:[BP.dpb_drive]
MOV BYTE PTR [WPERR],AL ; Flag drive with WP error
POP AX
NOSETWRPERR:
SUB AX,CX ; Number of sectors successfully transferred
ADD DX,AX ; First sector number to retry
PUSH DX
MUL ES:[BP.dpb_sector_size] ; Number of bytes transferred
POP DX
ADD BX,AX ; First address for retry
XOR AH,AH ; Flag disk section in error
CMP DX,ES:[BP.dpb_first_FAT] ; In reserved area?
JB ERRINT
INC AH ; Flag for FAT
CMP DX,ES:[BP.dpb_dir_sector] ; In FAT?
JB ERRINT
INC AH
CMP DX,ES:[BP.dpb_first_sector] ; In directory?
JB ERRINT
INC AH ; Must be in data area
ERRINT:
SHL AH,1 ; Make room for read/write bit
OR AH,BYTE PTR [READOP]
entry FATAL
MOV AL,ES:[BP.dpb_drive] ; Get drive number
entry FATAL1
MOV WORD PTR [EXITHOLD+2],ES
MOV WORD PTR [EXITHOLD],BP ; The only things we preserve
LES SI,ES:[BP.dpb_driver_addr]
MOV BP,ES ; BP:SI points to the device involved
FATALC:
CMP BYTE PTR [ERRORMODE],0
JNZ SETIGN ; No INT 24s if already INT 24
MOV [CONTSTK],SP
PUSH SS
POP ES
ASSUME ES:DOSGROUP
CLI ; Prepare to play with stack
INC BYTE PTR [ERRORMODE] ; Flag INT 24 in progress
DEC BYTE PTR [INDOS] ; INT 24 handler might not return
MOV SS,[user_SS]
ASSUME SS:NOTHING
MOV SP,ES:[user_SP] ; User stack pointer restored
INT int_fatal_abort ; Fatal error interrupt vector, must preserve ES
MOV ES:[user_SP],SP ; restore our stack
MOV ES:[user_SS],SS
MOV SP,ES
MOV SS,SP
ASSUME SS:DOSGROUP
MOV SP,[CONTSTK]
INC BYTE PTR [INDOS] ; Back in the DOS
MOV BYTE PTR [ERRORMODE],0 ; Back from INT 24
STI
IGNRET:
LES BP,[EXITHOLD]
ASSUME ES:NOTHING
CMP AL,2
JZ error_abort
MOV BYTE PTR [WPERR],-1 ;Forget about WP error
return
SETIGN:
XOR AL,AL ;Flag ignore
JMP SHORT IGNRET
error_abort:
PUSH SS
POP DS
ASSUME DS:DOSGROUP
CMP BYTE PTR [CONSWAP],0
JZ NOSWAP2
invoke SWAPBACK
NOSWAP2:
MOV BYTE PTR [exit_Type],Exit_hard_error
MOV DS,[CurrentPDB]
ASSUME DS:NOTHING
;
; reset_environment checks the DS value against the CurrentPDB. If they
; are different, then an old-style return is performed. If they are
; the same, then we release jfns and restore to parent. We still use
; the PDB at DS:0 as the source of the terminate addresses.
;
; output: none.
;
entry reset_environment
ASSUME DS:NOTHING,ES:NOTHING
PUSH DS ; save PDB of process
MOV AL,int_Terminate
invoke $Get_interrupt_vector ; and who to go to
MOV WORD PTR [EXITHOLD+2],ES ; save return address
MOV WORD PTR [EXITHOLD],BX
MOV BX,[CurrentPDB] ; get current process
MOV DS,BX ;
MOV AX,DS:[PDB_Parent_PID] ; get parent to return to
POP CX
;
; AX = parentPDB, BX = CurrentPDB, CX = ThisPDB
; Only free handles if AX <> BX and BX = CX and [exit_code].upper is not
; Exit_keep_process
;
CMP AX,BX
JZ reset_return ; parentPDB = CurrentPDB
CMP BX,CX
JNZ reset_return ; CurrentPDB <> ThisPDB
PUSH AX ; save parent
CMP BYTE PTR [exit_type],Exit_keep_process
JZ reset_to_parent ; keeping this process
invoke arena_free_process
; reset environment at [CurrentPDB]; close those handles
MOV CX,FilPerProc
reset_free_jfn:
MOV BX,CX
PUSH CX
DEC BX ; get jfn
invoke $CLOSE ; close it, ignore return
POP CX
LOOP reset_free_jfn ; and do 'em all
reset_to_parent:
POP [CurrentPDB] ; set up process as parent
reset_return: ; come here for normal return
PUSH CS
POP DS
ASSUME DS:DOSGROUP
MOV AL,-1
invoke FLUSHBUF ; make sure that everything is clean
CLI
MOV BYTE PTR [INDOS],0 ;Go to known state
MOV BYTE PTR [WPERR],-1 ;Forget about WP error
;
; Snake into multitasking... Get stack from CurrentPDB person
;
MOV DS,[CurrentPDB]
ASSUME DS:NOTHING
MOV SS,WORD PTR DS:[PDB_user_stack+2]
MOV SP,WORD PTR DS:[PDB_user_stack]
ASSUME SS:NOTHING
invoke restore_world
ASSUME ES:NOTHING
POP AX ; suck off CS:IP of interrupt...
POP AX
POP AX
MOV AX,0F202h ; STI
PUSH AX
PUSH WORD PTR [EXITHOLD+2]
PUSH WORD PTR [EXITHOLD]
STI
IRET ; Long return back to user terminate address
HardErr ENDP
ASSUME SS:DOSGROUP
do_ext
CODE ENDS
END
+1264
View File
File diff suppressed because it is too large Load Diff
+694
View File
@@ -0,0 +1,694 @@
TITLE PART1 DEBUGGER COMMANDS
; Routines to perform debugger commands except ASSEMble and UASSEMble
.xlist
.xcref
INCLUDE DEBEQU.ASM
INCLUDE DOSSYM.ASM
.cref
.list
CODE SEGMENT PUBLIC BYTE 'CODE'
CODE ENDS
CONST SEGMENT PUBLIC BYTE
EXTRN SYNERR:BYTE
EXTRN DISPB:WORD,DSIZ:BYTE,DSSAVE:WORD
if sysver
EXTRN CIN:DWORD,PFLAG:BYTE
endif
CONST ENDS
DATA SEGMENT PUBLIC BYTE
EXTRN DEFLEN:WORD,BYTEBUF:BYTE,DEFDUMP:BYTE
DATA ENDS
DG GROUP CODE,CONST,DATA
CODE SEGMENT PUBLIC BYTE 'CODE'
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
PUBLIC HEXCHK,GETHEX1,PRINT,DSRANGE,ADDRESS,HEXIN,PERROR
PUBLIC GETHEX,GET_ADDRESS,GETEOL,GETHX,PERR
PUBLIC PERR,MOVE,DUMP,ENTER,FILL,SEARCH,DEFAULT
if sysver
PUBLIC IN
EXTRN DISPREG:NEAR,DEVIOCALL:NEAR
endif
EXTRN OUT:NEAR,CRLF:NEAR,OUTDI:NEAR,OUTSI:NEAR,SCANP:NEAR
EXTRN SCANB:NEAR,BLANK:NEAR,TAB:NEAR,PRINTMES:NEAR,COMMAND:NEAR
EXTRN HEX:NEAR,BACKUP:NEAR
DEBCOM1:
; RANGE - Looks for parameters defining an address range.
; The first parameter is the starting address. The second parameter
; may specify the ending address, or it may be preceded by
; "L" and specify a length (4 digits max), or it may be
; omitted and a length of 128 bytes is assumed. Returns with
; segment in AX, displacement in DX, and length in CX.
DSRANGE:
MOV BP,[DSSAVE] ; Set default segment to DS
MOV [DEFLEN],128 ; And default length to 128 bytes
RANGE:
CALL ADDRESS
PUSH AX ; Save segment
PUSH DX ; Save offset
CALL SCANP ; Get to next parameter
MOV AL,[SI]
CMP AL,"L" ; Length indicator?
JE GETLEN
MOV DX,[DEFLEN] ; Default length
CALL HEXIN ; Second parameter present?
JC GetDef ; If not, use default
MOV CX,4
CALL GETHEX ; Get ending address (same segment)
MOV CX,DX ; Low 16 bits of ending addr.
POP DX ; Low 16 bits of starting addr.
SUB CX,DX ; Compute range
JAE DSRNG2
DSRNG1: JMP PERROR ; Negative range
DSRNG2: INC CX ; Include last location
JCXZ DSRNG1 ; Wrap around error
POP AX ; Restore segment
RET
GetDef:
POP CX ; get original offset
PUSH CX ; save it
NEG CX ; rest of segment
JZ RngRet ; use default
CMP CX,DX ; more room in segment?
JAE RngRet ; yes, use default
JMP RngRet1 ; no, length is in CX
GETLEN:
INC SI ; Skip over "L" to length
MOV CX,4 ; Length may have 4 digits
CALL GETHEX ; Get the range
RNGRET:
MOV CX,DX ; Length
RngRet1:
POP DX ; Offset
MOV AX,CX
ADD AX,DX
JNC OKRET
CMP AX,1
JAE DSRNG1 ; Look for wrap error
OKRET:
POP AX ; Segment
RET
DEFAULT:
; DI points to default address and CX has default length
CALL SCANP
JZ USEDEF ; Use default if no parameters
MOV [DEFLEN],CX
CALL RANGE
JMP GETEOL
USEDEF:
MOV SI,DI
LODSW ; Get default displacement
MOV DX,AX
LODSW ; Get default segment
RET
; Dump an area of memory in both hex and ASCII
DUMP:
MOV BP,[DSSAVE]
MOV CX,DISPB
MOV DI,OFFSET DG:DEFDUMP
CALL DEFAULT ; Get range if specified
MOV DS,AX ; Set segment
MOV SI,DX ; SI has displacement in segment
IF ZIBO
PUSH SI ; save SI away
AND SI,0FFF0h ; convert to para number
CALL OutSI ; display location
POP SI ; get SI back
MOV AX,SI ; move offset
MOV AH,3 ; spaces per byte
AND AL,0Fh ; convert to real offset
MUL AH ; compute (AL+1)*3-1
OR AL,AL ; set flag
JZ InRow ; if xero go on
PUSH CX ; save count
MOV CX,AX ; move to convenient spot
CALL Tab ; move over
POP CX ; get back count
JMP InRow ; display line
ENDIF
ROW:
CALL OUTSI ; Print address at start of line
InRow:
PUSH SI ; Save address for ASCII dump
CALL BLANK
BYTE0:
CALL BLANK ; Space between bytes
BYTE1:
LODSB ; Get byte to dump
CALL HEX ; and display it
POP DX ; DX has start addr. for ASCII dump
DEC CX ; Drop loop count
JZ ToAscii ; If through do ASCII dump
MOV AX,SI
TEST AL,CS:(BYTE PTR DSIZ) ; On 16-byte boundary?
JZ ENDROW
PUSH DX ; Didn't need ASCII addr. yet
TEST AL,7 ; On 8-byte boundary?
JNZ BYTE0
MOV AL,"-" ; Mark every 8 bytes
CALL OUT
JMP SHORT BYTE1
ENDROW:
CALL ASCII ; Show it in ASCII
JMP SHORT ROW ; Loop until count is zero
ToAscii:
MOV AX,SI ; get offset
AND AL,0Fh ; real offset
JZ ASCII ; no loop if already there
SUB AL,10h ; remainder
NEG AL
MOV CL,3
MUL CL
MOV CX,AX ; number of chars to move
CALL Tab
ASCII:
PUSH CX ; Save byte count
MOV AX,SI ; Current dump address
MOV SI,DX ; ASCII dump address
SUB AX,DX ; AX=length of ASCII dump
IF NOT ZIBO
; Compute tab length. ASCII dump always appears on right side
; screen regardless of how many bytes were dumped. Figure 3
; characters for each byte dumped and subtract from 51, which
; allows a minimum of 3 blanks after the last byte dumped.
MOV BX,AX
SHL AX,1 ; Length times 2
ADD AX,BX ; Length times 3
MOV CX,51
SUB CX,AX ; Amount to tab in CX
CALL TAB
MOV CX,BX ; ASCII dump length back in CX
ELSE
MOV CX,SI ; get starting point
DEC CX
AND CX,0Fh
INC CX
AND CX,0Fh
ADD CX,3 ; we have the correct number to tab
PUSH AX ; save count
CALL TAB
POP CX ; get count back
ENDIF
ASCDMP:
LODSB ; Get ASCII byte to dump
AND AL,7FH ; ASCII uses 7 bits
CMP AL,7FH ; Don't try to print RUBOUT
JZ NOPRT
CMP AL," " ; Check for control characters
JNC PRIN
NOPRT:
MOV AL,"." ; If unprintable character
PRIN:
CALL OUT ; Print ASCII character
LOOP ASCDMP ; CX times
POP CX ; Restore overall dump length
MOV ES:WORD PTR [DEFDUMP],SI
MOV ES:WORD PTR [DEFDUMP+2],DS ; Save last address as default
CALL CRLF ; Print CR/LF and return
RET
; Block move one area of memory to another. Overlapping moves
; are performed correctly, i.e., so that a source byte is not
; overwritten until after it has been moved.
MOVE:
CALL DSRANGE ; Get range of source area
PUSH CX ; Save length
PUSH AX ; Save segment
PUSH DX ; Save source displacement
CALL ADDRESS ; Get destination address (same segment)
CALL GETEOL ; Check for errors
POP SI
MOV DI,DX ; Set dest. displacement
POP BX ; Source segment
MOV DS,BX
MOV ES,AX ; Destination segment
POP CX ; Length
CMP DI,SI ; Check direction of move
SBB AX,BX ; Extend the CMP to 32 bits
JB COPYLIST ; Move forward into lower mem.
; Otherwise, move backward. Figure end of source and destination
; areas and flip direction flag.
DEC CX
ADD SI,CX ; End of source area
ADD DI,CX ; End of destination area
STD ; Reverse direction
INC CX
COPYLIST:
MOVSB ; Do at least 1 - Range is 1-10000H not 0-FFFFH
DEC CX
REP MOVSB ; Block move
RET1: RET
; Fill an area of memory with a list values. If the list
; is bigger than the area, don't use the whole list. If the
; list is smaller, repeat it as many times as necessary.
FILL:
CALL DSRANGE ; Get range to fill
PUSH CX ; Save length
PUSH AX ; Save segment number
PUSH DX ; Save displacement
CALL LIST ; Get list of values to fill with
POP DI ; Displacement in segment
POP ES ; Segment
POP CX ; Length
CMP BX,CX ; BX is length of fill list
MOV SI,OFFSET DG:BYTEBUF ; List is in byte buffer
JCXZ BIGRNG
JAE COPYLIST ; If list is big, copy part of it
BIGRNG:
SUB CX,BX ; How much bigger is area than list?
XCHG CX,BX ; CX=length of list
PUSH DI ; Save starting addr. of area
REP MOVSB ; Move list into area
POP SI
; The list has been copied into the beginning of the
; specified area of memory. SI is the first address
; of that area, DI is the end of the copy of the list
; plus one, which is where the list will begin to repeat.
; All we need to do now is copy [SI] to [DI] until the
; end of the memory area is reached. This will cause the
; list to repeat as many times as necessary.
MOV CX,BX ; Length of area minus list
PUSH ES ; Different index register
POP DS ; requires different segment reg.
JMP SHORT COPYLIST ; Do the block move
; Search a specified area of memory for given list of bytes.
; Print address of first byte of each match.
SEARCH:
CALL DSRANGE ; Get area to be searched
PUSH CX ; Save count
PUSH AX ; Save segment number
PUSH DX ; Save displacement
CALL LIST ; Get search list
DEC BX ; No. of bytes in list-1
POP DI ; Displacement within segment
POP ES ; Segment
POP CX ; Length to be searched
SUB CX,BX ; minus length of list
SCAN:
MOV SI,OFFSET DG:BYTEBUF ; List kept in byte buffer
LODSB ; Bring first byte into AL
DOSCAN:
SCASB ; Search for first byte
LOOPNE DOSCAN ; Do at least once by using LOOP
JNZ RET1 ; Exit if not found
PUSH BX ; Length of list minus 1
XCHG BX,CX
PUSH DI ; Will resume search here
REPE CMPSB ; Compare rest of string
MOV CX,BX ; Area length back in CX
POP DI ; Next search location
POP BX ; Restore list length
JNZ TEST ; Continue search if no match
DEC DI ; Match address
CALL OUTDI ; Print it
INC DI ; Restore search address
CALL CRLF
TEST:
JCXZ RET1
JMP SHORT SCAN ; Look for next occurrence
; Get the next parameter, which must be a hex number.
; CX is maximum number of digits the number may have.
GETHX:
CALL SCANP
GETHX1:
XOR DX,DX ; Initialize the number
CALL HEXIN ; Get a hex digit
JC HXERR ; Must be one valid digit
MOV DL,AL ; First 4 bits in position
GETLP:
INC SI ; Next char in buffer
DEC CX ; Digit count
CALL HEXIN ; Get another hex digit?
JC RETHX ; All done if no more digits
STC
JCXZ HXERR ; Too many digits?
SHL DX,1 ; Multiply by 16
SHL DX,1
SHL DX,1
SHL DX,1
OR DL,AL ; and combine new digit
JMP SHORT GETLP ; Get more digits
GETHEX:
CALL GETHX ; Scan to next parameter
JMP SHORT GETHX2
GETHEX1:
CALL GETHX1
GETHX2: JC PERROR
RETHX: CLC
HXERR: RET
; Check if next character in the input buffer is a hex digit
; and convert it to binary if it is. Carry set if not.
HEXIN:
MOV AL,[SI]
; Check if AL has a hex digit and convert it to binary if it
; is. Carry set if not.
HEXCHK:
SUB AL,"0" ; Kill ASCII numeric bias
JC RET2
CMP AL,10
CMC
JNC RET2 ; OK if 0-9
AND AL,5FH
SUB AL,7 ; Kill A-F bias
CMP AL,10
JC RET2
CMP AL,16
CMC
RET2: RET
; Process one parameter when a list of bytes is
; required. Carry set if parameter bad. Called by LIST.
LISTITEM:
CALL SCANP ; Scan to parameter
CALL HEXIN ; Is it in hex?
JC STRINGCHK ; If not, could be a string
MOV CX,2 ; Only 2 hex digits for bytes
CALL GETHEX ; Get the byte value
MOV [BX],DL ; Add to list
INC BX
GRET: CLC ; Parameter was OK
RET
STRINGCHK:
MOV AL,[SI] ; Get first character of param
CMP AL,"'" ; String?
JZ STRING
CMP AL,'"' ; Either quote is all right
JZ STRING
STC ; Not string, not hex - bad
RET
STRING:
MOV AH,AL ; Save for closing quote
INC SI
STRNGLP:
LODSB ; Next char of string
CMP AL,13 ; Check for end of line
JZ PERR ; Must find a close quote
CMP AL,AH ; Check for close quote
JNZ STOSTRG ; Add new character to list
CMP AH,[SI] ; Two quotes in a row?
JNZ GRET ; If not, we're done
INC SI ; Yes - skip second one
STOSTRG:
MOV [BX],AL ; Put new char in list
INC BX
JMP SHORT STRNGLP ; Get more characters
; Get a byte list for ENTER, FILL or SEARCH. Accepts any number
; of 2-digit hex values or character strings in either single
; (') or double (") quotes.
LIST:
MOV BX,OFFSET DG:BYTEBUF ; Put byte list in the byte buffer
LISTLP:
CALL LISTITEM ; Process a parameter
JNC LISTLP ; If OK, try for more
SUB BX,OFFSET DG:BYTEBUF ; BX now has no. of bytes in list
JZ PERROR ; List must not be empty
; Make sure there is nothing more on the line except for
; blanks and carriage return. If there is, it is an
; unrecognized parameter and an error.
GETEOL:
CALL SCANB ; Skip blanks
JNZ PERROR ; Better be a RETURN
RET3: RET
; Command error. SI has been incremented beyond the
; command letter so it must decremented for the
; error pointer to work.
PERR:
DEC SI
; Syntax error. SI points to character in the input buffer
; which caused error. By subtracting from start of buffer,
; we will know how far to tab over to appear directly below
; it on the terminal. Then print "^ Error".
PERROR:
SUB SI,OFFSET DG:(BYTEBUF-1); How many char processed so far?
MOV CX,SI ; Parameter for TAB in CX
CALL TAB ; Directly below bad char
MOV SI,OFFSET DG:SYNERR ; Error message
; Print error message and abort to command level
PRINT:
CALL PRINTMES
JMP COMMAND
; Gets an address in Segment:Displacement format. Segment may be omitted
; and a default (kept in BP) will be used, or it may be a segment
; register (DS, ES, SS, CS). Returns with segment in AX, OFFSET in DX.
ADDRESS:
CALL GET_ADDRESS
JC PERROR
ADRERR: STC
RET
GET_ADDRESS:
CALL SCANP
MOV AL,[SI+1]
CMP AL,"S"
JZ SEGREG
MOV CX,4
CALL GETHX
JC ADRERR
MOV AX,BP ; Get default segment
CMP BYTE PTR [SI],":"
JNZ GETRET
PUSH DX
GETDISP:
INC SI ; Skip over ":"
MOV CX,4
CALL GETHX
POP AX
JC ADRERR
GETRET: CLC
RET
SEGREG:
MOV AL,[SI]
MOV DI,OFFSET DG:SEGLET
MOV CX,4
REPNE SCASB
JNZ ADRERR
INC SI
INC SI
SHL CX,1
MOV BX,CX
CMP BYTE PTR [SI],":"
JNZ ADRERR
PUSH [BX+DSSAVE]
JMP SHORT GETDISP
SEGLET DB "CSED"
; Short form of ENTER command. A list of values from the
; command line are put into memory without using normal
; ENTER mode.
GETLIST:
CALL LIST ; Get the bytes to enter
POP DI ; Displacement within segment
POP ES ; Segment to enter into
MOV SI,OFFSET DG:BYTEBUF ; List of bytes is in byte 2uffer
MOV CX,BX ; Count of bytes
REP MOVSB ; Enter that byte list
RET
; Enter values into memory at a specified address. If the
; line contains nothing but the address we go into "enter
; mode", where the address and its current value are printed
; and the user may change it if desired. To change, type in
; new value in hex. Backspace works to correct errors. If
; an illegal hex digit or too many digits are typed, the
; bell is sounded but it is otherwise ignored. To go to the
; next byte (with or without change), hit space bar. To
; back CLDto a previous address, type "-". On
; every 8-byte boundary a new line is started and the address
; is printed. To terminate command, type carriage return.
; Alternatively, the list of bytes to be entered may be
; included on the original command line immediately following
; the address. This is in regular LIST format so any number
; of hex values or strings in quotes may be entered.
ENTER:
MOV BP,[DSSAVE] ; Set default segment to DS
CALL ADDRESS
PUSH AX ; Save for later
PUSH DX
CALL SCANB ; Any more parameters?
JNZ GETLIST ; If not end-of-line get list
POP DI ; Displacement of ENTER
POP ES ; Segment
GETROW:
CALL OUTDI ; Print address of entry
CALL BLANK ; Leave a space
CALL BLANK
GETBYTE:
MOV AL,ES:[DI] ; Get current value
CALL HEX ; And display it
PUTDOT:
MOV AL,"."
CALL OUT ; Prompt for new value
MOV CX,2 ; Max of 2 digits in new value
MOV DX,0 ; Intial new value
GETDIG:
CALL IN ; Get digit from user
MOV AH,AL ; Save
CALL HEXCHK ; Hex digit?
XCHG AH,AL ; Need original for echo
JC NOHEX ; If not, try special command
MOV DH,DL ; Rotate new value
MOV DL,AH ; And include new digit
LOOP GETDIG ; At most 2 digits
; We have two digits, so all we will accept now is a command.
DWAIT:
CALL IN ; Get command character
NOHEX:
CMP AL,8 ; Backspace
JZ BS
CMP AL,7FH ; RUBOUT
JZ RUB
CMP AL,"-" ; Back CLDto previous address
JZ PREV
CMP AL,13 ; All done with command?
JZ EOL
CMP AL," " ; Go to next address
JZ NEXT
MOV AL,8
CALL OUT ; Back CLDover illegal character
CALL BACKUP
JCXZ DWAIT
JMP SHORT GETDIG
RUB:
MOV AL,8
CALL OUT
BS:
CMP CL,2 ; CX=2 means nothing typed yet
JZ PUTDOT ; Put back the dot we backed CLDover
INC CL ; Accept one more character
MOV DL,DH ; Rotate out last digit
MOV DH,CH ; Zero this digit
CALL BACKUP ; Physical backspace
JMP SHORT GETDIG ; Get more digits
; If new value has been entered, convert it to binary and
; put into memory. Always bump pointer to next location
STORE:
CMP CL,2 ; CX=2 means nothing typed yet
JZ NOSTO ; So no new value to store
; Rotate DH left 4 bits to combine with DL and make a byte value
PUSH CX
MOV CL,4
SHL DH,CL
POP CX
OR DL,DH ; Hex is now converted to binary
MOV ES:[DI],DL ; Store new value
NOSTO:
INC DI ; Prepare for next location
RET
NEXT:
CALL STORE ; Enter new value
INC CX ; Leave a space plus two for
INC CX ; each digit not entered
CALL TAB
MOV AX,DI ; Next memory address
AND AL,7 ; Check for 8-byte boundary
JNZ GETBYTE ; Take 8 per line
NEWROW:
CALL CRLF ; Terminate line
JMP GETROW ; Print address on new line
PREV:
CALL STORE ; Enter the new value
; DI has been bumped to next byte. Drop it 2 to go to previous addr
DEC DI
DEC DI
JMP SHORT NEWROW ; Terminate line after backing CLD
EOL:
CALL STORE ; Enter the new value
JMP CRLF ; CR/LF and terminate
; Console input of single character
IF SYSVER
IN:
PUSH DS
PUSH SI
LDS SI,CS:[CIN]
MOV AH,4
CALL DEVIOCALL
POP SI
POP DS
CMP AL,3
JNZ NOTCNTC
INT 23H
NOTCNTC:
CMP AL,'P'-'@'
JZ PRINTON
CMP AL,'N'-'@'
JZ PRINTOFF
CALL OUT
RET
PRINTOFF:
PRINTON:
NOT [PFLAG]
JMP SHORT IN
ELSE
IN:
MOV AH,1
INT 21H
RET
ENDIF
CODE ENDS
END DEBCOM1
+1269
View File
File diff suppressed because it is too large Load Diff
+1103
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+32
View File
@@ -0,0 +1,32 @@
FALSE EQU 0
TRUE EQU NOT FALSE
IBMVER EQU true ; Set conditional switches
MSVER EQU false
SYSVER EQU FALSE ; if true, i/o direct to bios
; so DOS can be debugged
IBMJAPAN EQU FALSE
SETCNTC EQU TRUE ; If this is FALSE, DEBUG will not set
; the Control C int vector
ZIBO EQU TRUE ; true if P traces over interrupts
; and calls and dump looks pretty
PROMPT EQU "-"
FCB EQU 5CH
EXEFCB EQU FCB
BUFLEN EQU 80 ; Maximum length of line input buffer
BPMAX EQU 10 ; Maximum number of breakpoints
BPLEN EQU 5*BPMAX ; Length of breakpoint table
REGTABLEN EQU 14 ; Number of registers
SEGDIF EQU 0
BUFSIZ EQU 512
BXREG EQU "B"+5800H ; "BX"
BPREG EQU "B"+5000H ; "BP"
SIREG EQU "S"+4900H ; "SI"
DIREG EQU "D"+4900H ; "DI"
COMMA EQU 2C00H
OPBUFLEN EQU 35

BIN
View File
Binary file not shown.
+868
View File
@@ -0,0 +1,868 @@
TITLE DEBUASM
; Code for the UASSEMble command in the debugger
.xlist
.xcref
INCLUDE DEBEQU.ASM
INCLUDE DOSSYM.ASM
.cref
.list
CODE SEGMENT PUBLIC BYTE 'CODE'
CODE ENDS
CONST SEGMENT PUBLIC BYTE
EXTRN SYNERR:BYTE
EXTRN NSEG:WORD,SISAVE:WORD,BPSAVE:WORD,DISAVE:WORD
EXTRN BXSAVE:WORD,DSSAVE:WORD,ESSAVE:WORD,CSSAVE:WORD,IPSAVE:WORD
EXTRN SSSAVE:WORD,CXSAVE:WORD,SPSAVE:WORD,FSAVE:WORD
EXTRN DISTAB:WORD,SHFTAB:WORD,IMMTAB:WORD,GRP1TAB:WORD,GRP2TAB:WORD
EXTRN DBMN:BYTE,ESCMN:BYTE,DISPB:WORD,STACK:BYTE,REG8:BYTE
EXTRN REG16:BYTE,SREG:BYTE,SIZ8:BYTE,SEGTAB:WORD,M8087_TAB:BYTE
EXTRN FI_TAB:BYTE,SIZE_TAB:BYTE,MD9_TAB:BYTE,MD9_TAB2:BYTE
EXTRN MDB_TAB:BYTE,MDB_TAB2:BYTE,MDD_TAB:BYTE,MDD_TAB2:BYTE
EXTRN MDF_TAB:BYTE
CONST ENDS
DATA SEGMENT PUBLIC BYTE
EXTRN DISADD:BYTE,DISCNT:WORD,BYTCNT:BYTE,TEMP:BYTE,AWORD:BYTE
EXTRN MIDFLD:BYTE,MODE:BYTE,REGMEM:BYTE,OPCODE:WORD,OPBUF:BYTE
EXTRN INDEX:WORD
DATA ENDS
DG GROUP CODE,CONST,DATA
CODE SEGMENT PUBLIC BYTE 'CODE'
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
PUBLIC UNASSEM
PUBLIC DISASLN,MEMIMM,JMPCALL,SIGNIMM,ALUFROMREG,WORDTOALU
PUBLIC GRP2,PREFIX,OUTVARW,GRP1,SSPRE,MOVSEGTO,DSPRE,SHIFT
PUBLIC ESPRE,IMMED,CSPRE,OUTVARB,CHK10,ACCIMM,INT3,INVARB
PUBLIC MOVSEGFROM,LOADACC,OUTFIXB,XCHGAX,REGIMMW,SHORTJMP
PUBLIC SAV8,M8087,M8087_DB,M8087_DF,M8087_D9,M8087_DD
PUBLIC SAV16,SAVHEX,INFIXW,REGIMMB,OUTFIXW,SHIFTV,LONGJMP
PUBLIC INVARW,STOREACC,INFIXB,NOOPERANDS,ALUTOREG
PUBLIC SEGOP,REGOP,GETADDR
EXTRN CRLF:NEAR,PRINTMES:NEAR,BLANK:NEAR,TAB:NEAR,OUT:NEAR
EXTRN HEX:NEAR,DEFAULT:NEAR,OUTSI:NEAR,OUTDI:NEAR
UNASSEM:
MOV BP,[CSSAVE] ; Default code segment
MOV DI,OFFSET DG:DISADD ; Default address
MOV CX,DISPB ; Default length
SHR CX,1
SHR CX,1
CALL DEFAULT
MOV WORD PTR [DISADD],DX ; Displacement of disassembly
MOV WORD PTR [DISADD+2],AX ; Segment
MOV WORD PTR [DISCNT],CX ; No. of bytes (but whole instructions)
DISLP:
CALL DISASLN ; Disassemble one line
CALL CRLF
TEST [DISCNT],-1 ; See if we've used up the range
JNZ DISLP
RET
GOTDIS: PUSH DS ; RE-GET LAST BYTE
PUSH SI
LDS SI,DWORD PTR [DISADD]
MOV AL,[SI-1]
POP SI
POP DS
RET
GETDIS:
PUSH DS
LDS SI,DWORD PTR [DISADD]
LODSB ; Get the next byte of code
POP DS
MOV WORD PTR [DISADD],SI ; Update pointer
PUSH AX
CALL HEX ; Display each code byte
MOV SI,[DISCNT]
OR SI,SI ; Check if range exhausted
JZ ENDRNG ; If so, don't wrap around
DEC SI ; Count off the bytes
MOV [DISCNT],SI
ENDRNG:
INC BYTE PTR[BYTCNT] ; Keep track of no. of bytes per line
POP AX
RET
DSPRE: INC BYTE PTR [NSEG+1]
SSPRE: INC BYTE PTR [NSEG+1]
CSPRE: INC BYTE PTR [NSEG+1]
ESPRE: INC BYTE PTR [NSEG+1]
PREFIX:
POP BX ; Dump off return address
CALL FINLN
CALL CRLF
DISASLN:
PUSH DS
LDS SI,DWORD PTR [DISADD]
CALL OUTSI ; Show disassembly address
POP DS
CALL BLANK
DISASLN1:
MOV BYTE PTR [BYTCNT],0 ; Count of code bytes per line
MOV DI,OFFSET DG:OPBUF ; Point to operand buffer
MOV AL," "
MOV CX,OPBUFLEN-1 ; Don't do last byte which has end marker
REP STOSB ; Initialize operand buffer to blanks
MOV BYTE PTR [DI]," "+80H
CALL GETDIS ; Get opcode
MOV AH,0
MOV BX,AX
AND AL,1 ; Mask to "W" bit
MOV [AWORD],AL
MOV AL,BL ; Restore opcode
SHL BX,1
SHL BX,1 ; Multiply opcode by 4
ADD BX,OFFSET DG:DISTAB
MOV DX,[BX] ; Get pointer to mnemonic from table
MOV [OPCODE],DX ; Save it until line is complete
MOV DI,OFFSET DG:OPBUF ; Initialize for opcode routines
CALL WORD PTR [BX+2] ; Dispatch to opcode routine
FINLN:
MOV SI,OFFSET DG:DISADD
MOV AH,[BYTCNT] ; See how many bytes in this instruction
ADD AH,AH ; Each uses two characters
MOV AL,14 ; Amount of space we want to use
SUB AL,AH ; See how many fill characters needed
CBW
XCHG CX,AX ; Parameter for TAB needed in CX
CALL TAB
MOV SI,[OPCODE]
OR SI,SI ; MAKE SURE THERE IS SOMETHING TO PRINT
JZ NOOPC
CALL PRINTMES ; Print opcode mnemonic
MOV AL,9
CALL OUT ; and a tab
NOOPC: MOV SI,OFFSET DG:OPBUF
JMP PRINTMES ; and the operand buffer
GETMODE:
CALL GETDIS ; Get the address mode byte
MOV AH,AL
AND AL,7 ; Mask to "r/m" field
MOV [REGMEM],AL
SHR AH,1
SHR AH,1
SHR AH,1
MOV AL,AH
AND AL,7 ; Mask to center 3-bit field
MOV [MIDFLD],AL
SHR AH,1
SHR AH,1
SHR AH,1
MOV [MODE],AH ; Leaving 2-bit "MOD" field
RET
IMMED:
MOV BX,OFFSET DG:IMMTAB
CALL GETMNE
FINIMM:
CALL TESTREG
JMP SHORT IMM
MEMIMM:
CALL GETMODE
JMP SHORT FINIMM
ACCIMM:
XOR AL,AL
IMM1:
CALL SAVREG
IMM:
MOV AL,","
STOSB
TEST BYTE PTR [AWORD],-1
JNZ SAV16
SAV8:
CALL GETDIS
JMP SHORT SAVHEX
LONGJMP:
PUSH DI
MOV DI,OFFSET DG:TEMP
CALL SAV16
POP DI
CALL SAV16
MOV AL,":"
STOSB
MOV SI,OFFSET DG:TEMP
MOV CX,4
MOVDIG:
LODSB
STOSB
LOOP MOVDIG
RET
SAV16:
CALL GETDIS ; Get low byte
MOV DL,AL
CALL GETDIS ; Get high byte
MOV DH,AL
CALL SAVHEX ; Convert and store high byte
MOV AL,DL
SAVHEX:
MOV AH,AL
SHR AL,1
SHR AL,1
SHR AL,1
SHR AL,1
CALL SAVDIG
MOV AL,AH
SAVDIG:
AND AL,0FH
ADD AL,90H
DAA
ADC AL,40H
DAA
STOSB
RET
CHK10:
CALL GETDIS
CMP AL,10
JNZ SAVHEX
RET
SIGNIMM:
MOV BX,OFFSET DG:IMMTAB
CALL GETMNE
CALL TESTREG
MOV AL,","
STOSB
SAVD8:
CALL GETDIS ; Get signed 8-bit number
CBW
MOV DX,AX ; Save true 16-bit value in DX
MOV AH,AL
MOV AL,"+"
OR AH,AH
; JZ nosign
JNS POSITIV ; OK if positive
MOV AL,"-"
NEG AH ; Get magnitude if negative
POSITIV:
STOSB
; nosign:
MOV AL,AH
JMP SHORT SAVHEX
ALUFROMREG:
CALL GETADDR
MOV AL,","
STOSB
REGFLD:
MOV AL,[MIDFLD]
SAVREG:
MOV SI,OFFSET DG:REG8
CMP BYTE PTR [AWORD],1
JNE FNDREG
SAVREG16:
MOV SI,OFFSET DG:REG16
FNDREG:
CBW
ADD SI,AX
ADD SI,AX
MOVSW
RET
SEGOP:
SHR AL,1
SHR AL,1
SHR AL,1
SAVSEG:
AND AL,3
MOV SI,OFFSET DG:SREG
JMP SHORT FNDREG
REGOP:
AND AL,7
JMP SHORT SAVREG16
MOVSEGTO:
MOV BYTE PTR [AWORD],1
CALL GETADDR
MOV AL,","
STOSB
MOV AL,[MIDFLD]
JMP SHORT SAVSEG
MOVSEGFROM:
CALL GETMODE
CALL SAVSEG
MOV BYTE PTR [AWORD],1
JMP SHORT MEMOP2
GETADDR:
CALL GETMODE
JMP SHORT ADDRMOD
WORDTOALU:
MOV BYTE PTR [AWORD],1
ALUTOREG:
CALL GETMODE
CALL REGFLD
MEMOP2:
MOV AL,","
STOSB
ADDRMOD:
CMP BYTE PTR [MODE],3
MOV AL,[REGMEM]
JE SAVREG
XOR BX,BX
MOV BYTE PTR [NSEG],3
MOV BYTE PTR [DI],"["
INC DI
CMP AL,6
JNE NODRCT
CMP BYTE PTR [MODE],0
JE DIRECT ; Mode=0 and R/M=6 means direct addr.
NODRCT:
MOV DL,AL
CMP AL,1
JBE USEBX
CMP AL,7
JE USEBX
CMP AL,3
JBE USEBP
CMP AL,6
JNE CHKPLS
USEBP:
MOV BX,[BPSAVE]
MOV BYTE PTR [NSEG],2 ; Change default to Stack Segment
MOV AX,BPREG
SAVBASE:
STOSW
CHKPLS:
CMP DL,4
JAE NOPLUS
MOV AL,"+"
STOSB
NOPLUS:
CMP DL,6
JAE DOMODE ; No index register
AND DL,1 ; Even for SI, odd for DI
JZ USESI
ADD BX,[DISAVE]
MOV AX,DIREG
SAVINDX:
STOSW
DOMODE:
MOV AL,[MODE]
OR AL,AL
JZ CLOSADD ; If no displacement, then done
CMP AL,2
JZ ADDDIR
CALL SAVD8 ; Signed 8-bit displacement
ADDCLOS:
ADD BX,DX
CLOSADD:
MOV AL,"]"
STOSB
MOV [INDEX],BX
NOOPERANDS:
RET
ADDDIR:
MOV AL,"+"
STOSB
DIRECT:
CALL SAV16
JMP SHORT ADDCLOS
USEBX:
MOV BX,[BXSAVE]
MOV AX,BXREG
JMP SHORT SAVBASE
USESI:
ADD BX,[SISAVE]
MOV AX,SIREG
JMP SHORT SAVINDX
SHORTJMP:
CALL GETDIS
CBW
ADD AX,WORD PTR [DISADD]
XCHG DX,AX
SAVJMP:
MOV AL,DH
CALL SAVHEX
MOV AL,DL
JMP SAVHEX
JMPCALL:
CALL GETDIS
MOV DL,AL
CALL GETDIS
MOV DH,AL
ADD DX,WORD PTR [DISADD]
JMP SHORT SAVJMP
XCHGAX:
AND AL,7
CALL SAVREG16
MOV AL,","
STOSB
XOR AL,AL
JMP SAVREG16
LOADACC:
XOR AL,AL
CALL SAVREG
MOV AL,","
STOSB
MEMDIR:
MOV AL,"["
STOSB
XOR BX,BX
MOV BYTE PTR [NSEG],3
JMP DIRECT
STOREACC:
CALL MEMDIR
MOV AL,","
STOSB
XOR AL,AL
JMP SAVREG
REGIMMB:
MOV BYTE PTR [AWORD],0
JMP SHORT REGIMM
REGIMMW:
MOV BYTE PTR [AWORD],1
REGIMM:
AND AL,7
JMP IMM1
INT3:
MOV BYTE PTR [DI],"3"
RET
;
; 8087 instructions whose first byte is 0dfh
;
M8087_DF:
CALL GET64F
JZ ISDD3
MOV SI,OFFSET DG:MDF_TAB
JMP NODB3
;
; 8087 instructions whose first byte is 0ddh
;
M8087_DD:
CALL GET64F
JZ ISDD3
MOV SI,OFFSET DG:MDD_TAB
JMP NOD93
ISDD3:
MOV AL,DL
TEST AL,100B
JZ ISSTI
JMP ESC0
ISSTI: AND AL,11B
MOV SI,OFFSET DG:MDD_TAB2
MOV CL,AL
CALL MOVBYT
JMP PUTRST
;
; 8087 instructions whose first byte is 0dbh
;
M8087_DB:
CALL GET64F
JZ ISDB3
MOV SI,OFFSET DG:MDB_TAB
NODB3: CALL PUTOP
CALL PUTSIZE
JMP ADDRMOD
ISDB3:
MOV AL,DL
TEST AL,100B
JNZ ISDBIG
ESC0V: JMP ESC0
ISDBIG: CALL GOTDIS
AND AL,11111B
CMP AL,4
JAE ESC0V
MOV SI,OFFSET DG:MDB_TAB2
JMP DOBIG
;
; 8087 instructions whose first byte is 0d9h
;
M8087_D9:
CALL GET64F
JZ ISD93
MOV SI,OFFSET DG:MD9_TAB
NOD93: CALL PUTOP
AND AL,111B
CMP AL,3
JA NOSHO
MOV AL,DL
CALL PUTSIZE
NOSHO: JMP ADDRMOD
ISD93: MOV AL,DL
TEST AL,100B
JNZ ISD9BIG
AND AL,111B
OR AL,AL
JNZ NOTFLD
MOV AX,"DL"
STOSW
JMP SHORT PUTRST
NOTFLD: CMP AL,1
JNZ NOTFXCH
MOV AX,"CX"
STOSW
MOV AL,"H"
JMP SHORT PUTRST1
NOTFXCH:CMP AL,3
JNZ NOTFSTP
MOV AX,"TS"
STOSW
MOV AL,"P"
PUTRST1:STOSB
PUTRST: MOV AL,9
STOSB
JMP PUTST0
NOTFSTP:CALL GOTDIS
CMP AL,11010000B ; CHECK FOR FNOP
JZ GOTFNOP
JMP ESC0
GOTFNOP:MOV AX,"ON"
STOSW
MOV AL,"P"
STOSB
RET
ISD9BIG:
CALL GOTDIS ; GET THE MODE BYTE
MOV SI,OFFSET DG:MD9_TAB2
DOBIG: AND AL,11111B
MOV CL,AL
JMP MOVBYT
;
; entry point for the remaining 8087 instructions
;
M8087:
CALL GET64
CALL PUTFI ; PUT FIRST PART OF OPCODE
MOV AL,DL
CMP BYTE PTR [MODE],11B ; CHECK FOR REGISTER MODE
JZ MODEIS3
CALL PUTMN ; PUT MIDDLE PART OF OPCODE
NO3: MOV AL,9 ; OUTPUT A TAB
STOSB
MOV AL,DL
CALL PUTSIZE ; OUTPUT THE OPERAND SIZE
JMP ADDRMOD
MODEIS3:
TEST AL,100000B ; D BIT SET?
JZ MPUT ; NOPE...
TEST AL,000100B ; FDIV OR FSUB?
JZ MPUT ; NOPE...
XOR AL,1 ; REVERSE SENSE OF R
MOV DL,AL ; SAVE CHANGE
MPUT: CALL PUTMN ; PUT MIDDLE PART OF OPCODE
MOV AL,DL
TEST AL,010000B
JZ NOPSH
MOV AL,"P"
STOSB
NOPSH: MOV AL,9
STOSB
MOV AL,DL
AND AL,00000111B
CMP AL,2 ; FCOM
JZ PUTST0
CMP AL,3 ; FCOMP
JZ PUTST0
MOV AL,DL
TEST AL,100000B
JZ PUTSTST0
;
; output 8087 registers in the form st(n),st
;
PUTST0ST:
CALL PUTST0
MOV AL,','
ISCOMP: STOSB
PUTST: MOV AX,"TS"
STOSW
RET
;
; output 8087 registers in the form st,st(n)
;
PUTSTST0:
CALL PUTST
MOV AL,','
STOSB
PUTST0: CALL PUTST
MOV AL,"("
STOSB
MOV AL,[REGMEM]
ADD AL,"0"
STOSB
MOV AL,")"
STOSB
RET
;
; output an 8087 mnemonic
;
PUTMN: MOV SI,OFFSET DG:M8087_TAB
MOV CL,AL
AND CL,00000111B
JMP SHORT MOVBYT
;
; output either 'FI' or 'F' for first byte of opcode
;
PUTFI: MOV SI,OFFSET DG:FI_TAB
JMP SHORT PUTFI2
;
; output size (dword, tbyte, etc.)
;
PUTSIZE:MOV SI,OFFSET DG:SIZE_TAB
PUTFI2: CMP BYTE PTR [MODE],11B ; check if 8087 register
JNZ PUTFI3
AND AL,111000B ; LOOK FOR INVALID FORM OF 0DAH OPERANDS
CMP AL,010000B
JZ ESC0PJ
MOV AL,DL
CMP AL,110011B ; FCOMPP
JNZ GOFI
CMP BYTE PTR [REGMEM],1
JZ GOFI
ESC0PJ: JMP ESC0P
GOFI: XOR CL,CL
JMP SHORT MOVBYT
;
; Look for qword
;
PUTFI3: CMP AL,111101B
JZ GOTQU
CMP AL,111111B
JNZ NOTQU
GOTQU: MOV CL,2
JMP SHORT MOVBYT
;
; look for tbyte
;
NOTQU: CMP AL,011101B
JZ GOTTB
CMP AL,111100B
JZ GOTTB
CMP AL,111110B
JZ GOTTB
CMP AL,011111B
JNZ NOTTB
GOTTB: MOV CL,5
JMP SHORT MOVBYT
NOTTB: MOV CL,4
SHR AL,CL
MOV CL,AL
;
; SI POINTS TO A TABLE OF TEXT SEPARATED BY "$"
; CL = WHICH ELEMENT IN THE TABLE YOU WISH TO COPY TO [DI]
;
MOVBYT: PUSH AX
INC CL
MOVBYT1:DEC CL
JZ MOVBYT3
MOVBYT2:LODSB
CMP AL,'$'
JZ MOVBYT1
JMP MOVBYT2
MOVBYT3:LODSB
CMP AL,'$'
JZ MOVBYT5
CMP AL,'@' ; THIS MEANS RESVERED OP-CODE
JNZ MOVBYT4
POP AX
JMP SHORT ESC0P ; GO DO AN ESCAPE COMMAND
MOVBYT4:STOSB
JMP MOVBYT3
MOVBYT5:POP AX
RET
PUTOP: AND AL,111B
MOV CL,AL
CALL MOVBYT
MOV AL,9
STOSB
MOV AL,DL
RET
GET64F: CALL GET64
MOV AL,"F"
STOSB
CMP BYTE PTR [MODE],3
MOV AL,DL
RET
GET64:
AND AL,7
MOV DL,AL
CALL GETMODE
SHL DL,1
SHL DL,1
SHL DL,1
OR AL,DL
MOV DL,AL ; SAVE RESULT
RET
ESC0P: POP DI ; CLEAN UP STACK
ESC0: MOV WORD PTR [OPCODE],OFFSET DG:ESCMN
MOV AL,DL
MOV DI,OFFSET DG:OPBUF
JMP SHORT ESC1
ESC: CALL GET64
ESC1: CALL SAVHEX
CMP BYTE PTR [MODE],3
JZ SHRTESC
MOV BYTE PTR [AWORD],1
JMP MEMOP2
SHRTESC:
MOV AL,","
STOSB
MOV AL,[REGMEM]
AND AL,7
JMP SAVREG
INVARW:
CALL PUTAX
JMP SHORT INVAR
INVARB:
CALL PUTAL
INVAR: MOV AL,','
STOSB
JMP PUTDX
INFIXW:
CALL PUTAX
JMP SHORT INFIX
INFIXB:
CALL PUTAL
INFIX: MOV AL,','
STOSB
JMP SAV8
STOSW
RET
OUTVARB:
MOV BX,"LA"
JMP SHORT OUTVAR
OUTVARW:
MOV BX,"XA"
OUTVAR: CALL PUTDX
OUTFV: MOV AL,','
STOSB
MOV AX,BX
STOSW
RET
OUTFIXB:
MOV BX,"LA"
JMP SHORT OUTFIX
OUTFIXW:
MOV BX,"XA"
OUTFIX: CALL SAV8
JMP OUTFV
PUTAL: MOV AX,"A"+4C00H ; "AL"
JMP SHORT PUTX
PUTAX: MOV AX,"A"+5800H ; "AX"
JMP SHORT PUTX
PUTDX: MOV AX,"D"+5800H ; "DX"
PUTX: STOSW
RET
SHFT:
MOV BX,OFFSET DG:SHFTAB
CALL GETMNE
TESTREG:
CMP BYTE PTR [MODE],3
JZ NOFLG
MOV SI,OFFSET DG:SIZE_TAB
MOV CL,3
TEST BYTE PTR [AWORD],-1
JNZ TEST_1
INC CL
TEST_1: CALL MOVBYT
NOFLG:
JMP ADDRMOD
SHIFTV:
CALL SHFT
MOV AL,","
STOSB
MOV WORD PTR [DI],"C"+4C00H ; "CL"
RET
SHIFT:
CALL SHFT
MOV AX,"1,"
STOSW
RET
GETMNE:
CALL GETMODE
MOV DL,AL
CBW
SHL AX,1
ADD BX,AX
MOV AX,[BX]
MOV [OPCODE],AX
MOV AL,DL
RET
GRP1:
MOV BX,OFFSET DG:GRP1TAB
CALL GETMNE
OR AL,AL
JZ FINIMMJ
JMP TESTREG
FINIMMJ:
JMP FINIMM
GRP2:
MOV BX,OFFSET DG:GRP2TAB
CALL GETMNE
CMP AL,2
JB TESTREG
CMP AL,6
JAE INDIRECT
TEST AL,1
JZ INDIRECT
MOV AX,"AF" ; "FAR"
STOSW
MOV AX," R"
STOSW
INDIRECT:
JMP ADDRMOD
CODE ENDS
END UNASSEM
+838
View File
@@ -0,0 +1,838 @@
TITLE DEBUGger for MS-DOS
; DEBUG-86 8086 debugger runs under 86-DOS version 2.30
;
; Modified 5/4/82 by AaronR to do all I/O direct to devices
; Runs on MS-DOS 1.28 and above
; REV 1.20
; Tab expansion
; New device interface (1.29 and above)
; REV 2.0
; line by line assembler added by C. Peters
; REV 2.1
; Uses EXEC system call
; REV 2.2
; Ztrace mode by zibo.
; Fix dump display to indent properly
; Parity nonsense by zibo
;
; REV 2.3
; Split into seperate modules to allow for
; assembly on an IBM PC
;
.xlist
.xcref
INCLUDE DEBEQU.ASM
INCLUDE DOSSYM.ASM
.cref
.list
IF SYSVER
; Structure for system call 72
SYSINITVAR STRUC
DPBHEAD DD ? ; Pointer to head of DPB-FAT list
sft_addr DD ? ; Pointer to first FCB table
; The following address points to the CLOCK device
BCLOCK DD ?
; The following address is used by DISKSTATCHK it is always
; points to the console input device header
BCON DD ? ; Console device entry points
NUMIO DB 0 ; Number of disk tables
MAXSEC DW 0 ; Maximum allowed sector size
BUFFHEAD DD ?
DEVHEAD DD ?
SYSINITVAR ENDS
ENDIF
CODE SEGMENT PUBLIC 'CODE'
CODE ENDS
CONST SEGMENT PUBLIC BYTE
EXTRN USER_PROC_PDB:WORD,STACK:BYTE,CSSAVE:WORD,DSSAVE:WORD
EXTRN SPSAVE:WORD,IPSAVE:WORD,LINEBUF:BYTE,QFLAG:BYTE
EXTRN NEWEXEC:BYTE,HEADSAVE:WORD,LBUFSIZ:BYTE,BACMES:BYTE
EXTRN BADVER:BYTE,ENDMES:BYTE,CARRET:BYTE,ParityMes:BYTE
IF IBMVER
EXTRN DSIZ:BYTE,NOREGL:BYTE,DISPB:WORD
ENDIF
IF SYSVER
EXTRN CONFCB:BYTE,POUT:DWORD,COUT:DWORD,CIN:DWORD,IOBUFF:BYTE
EXTRN IOADDR:DWORD,IOCALL:BYTE,IOCOM:BYTE,IOSTAT:WORD,IOCNT:WORD
EXTRN IOSEG:WORD,COLPOS:BYTE,BADDEV:BYTE,BADLSTMES:BYTE
EXTRN LBUFFCNT:BYTE,PFLAG:BYTE
ENDIF
CONST ENDS
DATA SEGMENT PUBLIC BYTE
EXTRN PARSERR:BYTE,DATAEND:WORD,ParityFlag:BYTE,DISADD:BYTE
EXTRN ASMADD:BYTE,DEFDUMP:BYTE,BYTEBUF:BYTE
DATA ENDS
DG GROUP CODE,CONST,DATA
CODE SEGMENT PUBLIC 'CODE'
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
PUBLIC RESTART,SET_TERMINATE_VECTOR,DABORT,TERMINATE,COMMAND
PUBLIC FIND_DEBUG,CRLF,BLANK,TAB,OUT,INBUF,SCANB,SCANP
PUBLIC PRINTMES,RPRBUF,HEX,OUTSI,OUTDI,OUT16,DIGIT,BACKUP,RBUFIN
IF SYSVER
PUBLIC SETUDEV,DEVIOCALL
EXTRN DISPREG:NEAR,IN:NEAR
ENDIF
EXTRN PERR:NEAR,COMPARE:NEAR,DUMP:NEAR,ENTER:NEAR,FILL:NEAR
EXTRN GO:NEAR,INPUT:NEAR,LOAD:NEAR,MOVE:NEAR,NAME:NEAR
EXTRN REG:NEAR,SEARCH:NEAR,DWRITE:NEAR,UNASSEM:NEAR,ASSEM:NEAR
EXTRN OUTPUT:NEAR,ZTRACE:NEAR,TRACE:NEAR,GETHEX:NEAR,GETEOL:NEAR
EXTRN PREPNAME:NEAR,DEFIO:NEAR,SKIP_FILE:NEAR,DEBUG_FOUND:NEAR
EXTRN TrapParity:NEAR,ReleaseParity:NEAR
ORG 100H
START:
DEBUG:
JMP SHORT DSTRT
HEADER DB "Vers 2.30"
DSTRT:
DOSVER_HIGH EQU 0200H ; 2.00 in hex
MOV AH,GET_VERSION
INT 21H
XCHG AH,AL ; Turn it around to AH.AL
CMP AX,DOSVER_HIGH
JAE OKDOS
GOTBADDOS:
MOV DX,OFFSET DG:BADVER
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
INT 20H
OKDOS:
CALL TrapParity ; scarf up those parity guys
MOV AH,GET_CURRENT_PDB
INT 21H
MOV [USER_PROC_PDB],BX ; Initially set to DEBUG
IF SYSVER
MOV [IOSEG],CS
ENDIF
MOV SP,OFFSET DG:STACK
MOV [PARSERR],AL
MOV AH,GET_IN_VARS
INT 21H
IF SYSVER
LDS SI,ES:[BX.BCON]
MOV WORD PTR CS:[CIN+2],DS
MOV WORD PTR CS:[CIN],SI
MOV WORD PTR CS:[COUT+2],DS
MOV WORD PTR CS:[COUT],SI
PUSH CS
POP DS
MOV DX,OFFSET DG:CONFCB
MOV AH,FCB_OPEN
INT 21H
OR AL,AL
JZ GOTLIST
MOV DX,OFFSET DG:BADLSTMES
CALL RPRBUF
CALL RBUFIN
CALL CRLF
MOV CL,[LBUFFCNT]
OR CL,CL
JZ NOLIST1 ; User didn't specify one
XOR CH,CH
MOV DI,OFFSET DG:(CONFCB + 1)
MOV SI,OFFSET DG:LINEBUF
REP MOVSB
MOV DX,OFFSET DG:CONFCB
MOV AH,FCB_OPEN
INT 21H
OR AL,AL
JZ GOTLIST ; GOOD
MOV DX,OFFSET DG:BADDEV
CALL RPRBUF
NOLIST1:
MOV WORD PTR [POUT+2],CS
MOV WORD PTR [POUT],OFFSET DG:LONGRET
JMP NOLIST
XXX PROC FAR
LONGRET:RET
XXX ENDP
ENDIF
GOTLIST:
IF SYSVER
MOV SI,DX
LDS SI,DWORD PTR DS:[SI.fcb_FIRCLUS]
MOV WORD PTR CS:[POUT+2],DS
MOV WORD PTR CS:[POUT],SI
ENDIF
NOLIST:
MOV AX,CS
MOV DS,AX
MOV ES,AX
; Code to print header
; MOV DX,OFFSET DG:HEADER
; CALL RPRBUF
CALL SET_TERMINATE_VECTOR
IF SETCNTC
MOV AL,23H ; Set vector 23H
MOV DX,OFFSET DG:DABORT
INT 21H
ENDIF
MOV DX,CS ; Get DEBUG's segment
MOV AX,OFFSET DG:DATAEND + 15 ; End of debug
SHR AX,1 ; Convert to segments
SHR AX,1
SHR AX,1
SHR AX,1
ADD DX,AX ; Add siz of debug in paragraphs
MOV AH,CREATE_PROCESS_DATA_BLOCK ; create program segment just after DEBUG
INT 21H
MOV AX,DX
MOV DI,OFFSET DG:DSSAVE
CLD
STOSW
STOSW
STOSW
STOSW
MOV WORD PTR [DISADD+2],AX
MOV WORD PTR [ASMADD+2],AX
MOV WORD PTR [DEFDUMP+2],AX
MOV AX,100H
MOV WORD PTR[DISADD],AX
MOV WORD PTR[ASMADD],AX
MOV WORD PTR [DEFDUMP],AX
MOV DS,DX
MOV ES,DX
MOV DX,80H
MOV AH,SET_DMA
INT 21H ; Set default DMA address to 80H
MOV AX,WORD PTR DS:[6]
MOV BX,AX
CMP AX,0FFF0H
PUSH CS
POP DS
JAE SAVSTK
MOV AX,WORD PTR DS:[6]
PUSH BX
MOV BX,OFFSET DG:DATAEND + 15
AND BX,0FFF0H ; Size of DEBUG in bytes (rounded up to PARA)
SUB AX,BX
POP BX
SAVSTK:
PUSH BX
DEC AX
DEC AX
MOV BX,AX
MOV WORD PTR [BX],0
POP BX
MOV SPSAVE,AX
DEC AH
MOV ES:WORD PTR [6],AX
SUB BX,AX
MOV CL,4
SHR BX,CL
ADD ES:WORD PTR [8],BX
IF IBMVER
; Get screen size and initialize display related variables
MOV AH,15
INT 10H
CMP AH,40
JNZ PARSCHK
MOV BYTE PTR DSIZ,7
MOV BYTE PTR NOREGL,4
MOV DISPB,64
ENDIF
PARSCHK:
; Copy rest of command line to test program's parameter area
MOV DI,FCB
MOV SI,81H
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H
INT 21H
CALL SKIP_FILE ; Make sure si points to delimiter
CALL PREPNAME
PUSH CS
POP ES
FILECHK:
MOV DI,80H
CMP BYTE PTR ES:[DI],0 ; ANY STUFF FOUND?
JZ COMMAND ; NOPE
FILOOP: INC DI
CMP BYTE PTR ES:[DI],13 ; COMMAND LINE JUST SPACES?
JZ COMMAND
CMP BYTE PTR ES:[DI]," "
JZ FILOOP
CMP BYTE PTR ES:[DI],9
JZ FILOOP
CALL DEFIO ; WELL READ IT IN
MOV AX,CSSAVE
MOV WORD PTR DISADD+2,AX
MOV WORD PTR ASMADD+2,AX
MOV AX,IPSAVE
MOV WORD PTR DISADD,AX
MOV WORD PTR ASMADD,AX
COMMAND:
CLD
MOV AX,CS
MOV DS,AX
MOV ES,AX
MOV SS,AX
MOV SP,OFFSET DG:STACK
STI
CMP [ParityFlag],0 ; did we detect a parity error?
JZ GoPrompt ; nope, go prompt
MOV [ParityFlag],0 ; reset flag
MOV DX,OFFSET DG:ParityMes ; message to print
MOV AH,STD_CON_STRING_OUTPUT; easy way out
INT 21h ; blam
GoPrompt:
MOV AL,PROMPT
CALL OUT
CALL INBUF ; Get command line
; From now and throughout command line processing, DI points
; to next character in command line to be processed.
CALL SCANB ; Scan off leading blanks
JZ COMMAND ; Null command?
LODSB ; AL=first non-blank character
; Prepare command letter for table lookup
SUB AL,"A" ; Low end range check
JB ERR1
CMP AL,"Z"-"A" ; Upper end range check
JA ERR1
SHL AL,1 ; Times two
CBW ; Now a 16-bit quantity
XCHG BX,AX ; In BX we can address with it
CALL CS:[BX+COMTAB] ; Execute command
JMP SHORT COMMAND ; Get next command
ERR1: JMP PERR
SET_TERMINATE_VECTOR:
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 22H ; Set vector 22H
MOV DX,OFFSET DG:TERMINATE
INT 21H
RET
TERMINATE:
CMP BYTE PTR CS:[QFLAG],0
JNZ QUITING
MOV CS:[USER_PROC_PDB],CS
CMP BYTE PTR CS:[NEWEXEC],0
JZ NORMTERM
MOV AX,CS
MOV DS,AX
MOV SS,AX
MOV SP,OFFSET DG:STACK
MOV AX,[HEADSAVE]
JMP DEBUG_FOUND
NORMTERM:
MOV DX,OFFSET DG:ENDMES
JMP SHORT RESTART
QUITING:
MOV AX,(EXIT SHL 8)
INT 21H
DABORT:
MOV DX,OFFSET DG:CARRET
RESTART:
MOV AX,CS
MOV DS,AX
MOV SS,AX
MOV SP,OFFSET DG:STACK
CALL RPRBUF
JMP COMMAND
IF SYSVER
SETUDEV:
MOV DI,OFFSET DG:CONFCB
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H
INT 21H
CALL USERDEV
JMP DISPREG
USERDEV:
MOV DX,OFFSET DG:CONFCB
MOV AH,FCB_OPEN
INT 21H
OR AL,AL
JNZ OPENERR
MOV SI,DX
TEST BYTE PTR [SI.fcb_DEVID],080H ; Device?
JZ OPENERR ; NO
LDS SI,DWORD PTR [CONFCB.fcb_FIRCLUS]
MOV WORD PTR CS:[CIN],SI
MOV WORD PTR CS:[CIN+2],DS
MOV WORD PTR CS:[COUT],SI
MOV WORD PTR CS:[COUT+2],DS
PUSH CS
POP DS
RET
OPENERR:
MOV DX,OFFSET DG:BADDEV
CALL RPRBUF
RET
ENDIF
; Get input line. Convert all characters NOT in quotes to upper case.
INBUF:
CALL RBUFIN
MOV SI,OFFSET DG:LINEBUF
MOV DI,OFFSET DG:BYTEBUF
CASECHK:
LODSB
CMP AL,'a'
JB NOCONV
CMP AL,'z'
JA NOCONV
ADD AL,"A"-"a" ; Convert to upper case
NOCONV:
STOSB
CMP AL,13
JZ INDONE
CMP AL,'"'
JZ QUOTSCAN
CMP AL,"'"
JNZ CASECHK
QUOTSCAN:
MOV AH,AL
KILLSTR:
LODSB
STOSB
CMP AL,13
JZ INDONE
CMP AL,AH
JNZ KILLSTR
JMP SHORT CASECHK
INDONE:
MOV SI,OFFSET DG:BYTEBUF
; Output CR/LF sequence
CRLF:
MOV AL,13
CALL OUT
MOV AL,10
JMP OUT
; Physical backspace - blank, backspace, blank
BACKUP:
MOV SI,OFFSET DG:BACMES
; Print ASCII message. Last char has bit 7 set
PRINTMES:
LODS CS:BYTE PTR [SI] ; Get char to print
CALL OUT
SHL AL,1 ; High bit set?
JNC PRINTMES
RET
; Scan for parameters of a command
SCANP:
CALL SCANB ; Get first non-blank
CMP BYTE PTR [SI],"," ; One comma between params OK
JNE EOLCHK ; If not comma, we found param
INC SI ; Skip over comma
; Scan command line for next non-blank character
SCANB:
PUSH AX
SCANNEXT:
LODSB
CMP AL," "
JZ SCANNEXT
CMP AL,9
JZ SCANNEXT
DEC SI ; Back to first non-blank
POP AX
EOLCHK:
CMP BYTE PTR [SI],13
RET
; Hex addition and subtraction
HEXADD:
MOV CX,4
CALL GETHEX
MOV DI,DX
MOV CX,4
CALL GETHEX
CALL GETEOL
PUSH DX
ADD DX,DI
CALL OUT16
CALL BLANK
CALL BLANK
POP DX
SUB DI,DX
MOV DX,DI
CALL OUT16
JMP SHORT CRLF
; Print the hex address of DS:SI
OUTSI:
MOV DX,DS ; Put DS where we can work with it
CALL OUT16 ; Display segment
MOV AL,":"
CALL OUT
MOV DX,SI
JMP SHORT OUT16 ; Output displacement
; Print hex address of ES:DI
; Same as OUTSI above
OUTDI:
MOV DX,ES
CALL OUT16
MOV AL,":"
CALL OUT
MOV DX,DI
; Print out 16-bit value in DX in hex
OUT16:
MOV AL,DH ; High-order byte first
CALL HEX
MOV AL,DL ; Then low-order byte
; Output byte in AL as two hex digits
HEX:
MOV AH,AL ; Save for second digit
; Shift high digit into low 4 bits
PUSH CX
MOV CL,4
SHR AL,CL
POP CX
CALL DIGIT ; Output first digit
MOV AL,AH ; Now do digit saved in AH
DIGIT:
AND AL,0FH ; Mask to 4 bits
; Trick 6-byte hex conversion works on 8086 too.
ADD AL,90H
DAA
ADC AL,40H
DAA
; Console output of character in AL. No registers affected but bit 7
; is reset before output.
IF SYSVER
OUT:
PUSH AX
AND AL,7FH
CMP AL,7FH
JNZ NOTDEL
MOV AL,8 ; DELETE same as backspace
NOTDEL:
CMP AL,9
JZ TABDO
CALL DOCONOUT
CMP AL,0DH
JZ ZEROPOS
CMP AL,0AH
JZ ZEROPOS
CMP AL,8
JNZ OOKRET
MOV AL," "
CALL DOCONOUT
MOV AL,8
CALL DOCONOUT
CMP BYTE PTR CS:[COLPOS],0
JZ NOTINC
DEC BYTE PTR CS:[COLPOS]
JMP NOTINC
ZEROPOS:
MOV BYTE PTR CS:[COLPOS],0FFH
OOKRET:
INC BYTE PTR CS:[COLPOS]
NOTINC:
TEST BYTE PTR CS:[PFLAG],1
JZ POPRET
CALL LISTOUT
POPRET:
POP AX
RET
TABDO:
MOV AL,CS:[COLPOS]
OR AL,0F8H
NEG AL
PUSH CX
MOV CL,AL
XOR CH,CH
JCXZ POPTAB
TABLP:
MOV AL," "
CALL OUT
LOOP TABLP
POPTAB:
POP CX
POP AX
RET
DOCONOUT:
PUSH DS
PUSH SI
PUSH AX
CONOWAIT:
LDS SI,CS:[COUT]
MOV AH,10
CALL DEVIOCALL
MOV AX,CS:[IOSTAT]
AND AX,200H
JNZ CONOWAIT
POP AX
PUSH AX
MOV AH,8
CALL DEVIOCALL
POP AX
POP SI
POP DS
RET
LISTOUT:
PUSH DS
PUSH SI
PUSH AX
LISTWAIT:
LDS SI,CS:[POUT]
MOV AH,10
CALL DEVIOCALL
MOV AX,CS:[IOSTAT]
AND AX,200H
JNZ LISTWAIT
POP AX
PUSH AX
MOV AH,8
CALL DEVIOCALL
POP AX
POP SI
POP DS
RET
DEVIOCALL:
PUSH ES
PUSH BX
PUSH CS
POP ES
MOV BX,OFFSET DG:IOCALL
MOV CS:[IOCOM],AH
MOV WORD PTR CS:[IOSTAT],0
MOV WORD PTR CS:[IOCNT],1
MOV CS:[IOBUFF],AL
MOV WORD PTR CS:[IOADDR+2],DS
MOV AX,[SI+6]
MOV WORD PTR CS:[IOADDR],AX
CALL DWORD PTR CS:[IOADDR]
MOV AX,[SI+8]
MOV WORD PTR CS:[IOADDR],AX
CALL DWORD PTR CS:[IOADDR]
MOV AL,CS:[IOBUFF]
POP BX
POP ES
RET
ELSE
OUT:
PUSH DX
PUSH AX
AND AL,7FH
MOV DL,AL
MOV AH,2
INT 21H
POP AX
POP DX
RET
ENDIF
IF SYSVER
RBUFIN:
PUSH AX
PUSH ES
PUSH DI
PUSH CS
POP ES
MOV BYTE PTR [LBUFFCNT],0
MOV DI,OFFSET DG:LINEBUF
FILLBUF:
CALL IN
CMP AL,0DH
JZ BDONE
CMP AL,8
JZ ECHR
CMP AL,7FH
JZ ECHR
CMP BYTE PTR [LBUFFCNT],BUFLEN
JAE BFULL
STOSB
INC BYTE PTR [LBUFFCNT]
JMP SHORT FILLBUF
BDONE:
STOSB
POP DI
POP ES
POP AX
RET
BFULL:
MOV AL,8
CALL OUT
MOV AL,7
CALL OUT
JMP SHORT FILLBUF
ECHR:
CMP DI,OFFSET DG:LINEBUF
JZ FILLBUF
DEC DI
DEC BYTE PTR [LBUFFCNT]
JMP SHORT FILLBUF
ELSE
RBUFIN:
PUSH AX
PUSH DX
MOV AH,10
MOV DX,OFFSET DG:LBUFSIZ
INT 21H
POP DX
POP AX
RET
ENDIF
IF SYSVER
RPRBUF:
PUSHF
PUSH AX
PUSH SI
MOV SI,DX
PLOOP:
LODSB
CMP AL,"$"
JZ PRTDONE
CALL OUT
JMP SHORT PLOOP
PRTDONE:
POP SI
POP AX
POPF
RET
ELSE
RPRBUF:
MOV AH,9
INT 21H
RET
ENDIF
; Output one space
BLANK:
MOV AL," "
JMP OUT
; Output the number of blanks in CX
TAB:
CALL BLANK
LOOP TAB
RET
; Command Table. Command letter indexes into table to get
; address of command. PERR prints error for no such command.
COMTAB DW ASSEM ; A
DW PERR ; B
DW COMPARE ; C
DW DUMP ; D
DW ENTER ; E
DW FILL ; F
DW GO ; G
DW HEXADD ; H
DW INPUT ; I
DW PERR ; J
DW PERR ; K
DW LOAD ; L
DW MOVE ; M
DW NAME ; N
DW OUTPUT ; O
IF ZIBO
DW ZTRACE
ELSE
DW PERR ; P
ENDIF
DW QUIT ; Q (QUIT)
DW REG ; R
DW SEARCH ; S
DW TRACE ; T
DW UNASSEM ; U
DW PERR ; V
DW DWRITE ; W
IF SYSVER
DW SETUDEV ; X
ELSE
DW PERR
ENDIF
DW PERR ; Y
DW PERR ; Z
QUIT:
INC BYTE PTR [QFLAG]
MOV BX,[USER_PROC_PDB]
FIND_DEBUG:
IF NOT SYSVER
MOV AH,SET_CURRENT_PDB
INT 21H
ENDIF
CALL ReleaseParity ; let system do normal parity stuff
MOV AX,(EXIT SHL 8)
INT 21H
CODE ENDS
END START
+439
View File
@@ -0,0 +1,439 @@
;
; Device call routines for MSDOS
;
INCLUDE DOSSEG.ASM
IFNDEF KANJI
KANJI EQU 0 ;FALSE
ENDIF
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
TITLE DEV - Device call routines
NAME Dev
i_need IOXAD,DWORD
i_need IOSCNT,WORD
i_need DEVIOBUF,4
i_need IOCALL,BYTE
i_need IOMED,BYTE
i_need IORCHR,BYTE
i_need CALLSCNT,WORD
i_need DMAAdd,DWORD
i_need NullDevPt,DWORD
i_need CallDevAd,DWORD
i_need Attrib,BYTE
i_need NULDEV,DWORD
i_need Name1,BYTE
i_need DevPt,DWORD
i_need DPBHead,DWORD
i_need NumIO,BYTE
i_need ThisDPB,DWORD
i_need DevCall,DWORD
i_need VerFlg,BYTE
SUBTTL IOFUNC -- DO FUNCTION 1-12 I/O
PAGE
IOFUNC_RETRY:
ASSUME DS:NOTHING,ES:NOTHING
invoke restore_world
procedure IOFUNC,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:SI Points to FCB
; AH is function code
; = 0 Input
; = 1 Input Status
; = 2 Output
; = 3 Output Status
; = 4 Flush
; AL = character if output
; Function:
; Perform indicated I/O to device or file
; Outputs:
; AL is character if input
; If a status call
; zero set if not ready
; zero reset if ready (character in AL for input status)
; For regular files:
; Input Status
; Gets character but restores fcb_RR field
; Zero set on EOF
; Input
; Gets character advances fcb_RR field
; Returns ^Z on EOF
; Output Status
; Always ready
; AX altered, all other registers preserved
MOV WORD PTR [IOXAD+2],SS
MOV WORD PTR [IOXAD],OFFSET DOSGROUP:DEVIOBUF
MOV WORD PTR [IOSCNT],1
MOV WORD PTR [DEVIOBUF],AX
IOFUNC2:
TEST [SI.fcb_DEVID],080H
JNZ IOTODEV
JMP IOTOFILE
IOTODEV:
invoke save_world
PUSH DS
PUSH SS
POP ES
PUSH SS
POP DS
ASSUME DS:DOSGROUP
XOR BX,BX
MOV [IOCALL.REQSTAT],BX
MOV BYTE PTR [IOMED],BL
MOV BX,OFFSET DOSGROUP:IOCALL
MOV CX,(DEVRD SHL 8) OR DRDWRHL
OR AH,AH
JZ DCALLR
MOV CX,(DEVRDND SHL 8) OR DRDNDHL
DEC AH
JZ DCALLR
MOV CX,(DEVWRT SHL 8) OR DRDWRHL
DEC AH
JZ DCALLO
MOV CX,(DEVOST SHL 8) OR DSTATHL
DEC AH
JZ DCALLO
DFLUSH:
MOV CX,(DEVIFL SHL 8) OR DFLSHL
DCALLR:
MOV AH,86H
DCALL:
MOV [IOCALL.REQLEN],CL
MOV [IOCALL.REQFUNC],CH
MOV CL,AH
POP DS
ASSUME DS:NOTHING
CALL DEVIOCALL
MOV DI,[IOCALL.REQSTAT]
TEST DI,STERR
JZ OKDEVIO
MOV AH,CL
invoke CHARHARD
CMP AL,1
JZ IOFUNC_RETRY
;Know user must have wanted ignore. Make sure device shows ready so
;that DOS doesn't get caught in a status loop when user simply wants
;to ignore the error.
AND BYTE PTR [IOCALL.REQSTAT+1], NOT (STBUI SHR 8)
OKDEVIO:
PUSH SS
POP DS
ASSUME DS:DOSGROUP
CMP CH,DEVRDND
JNZ DNODRD
MOV AL,BYTE PTR [IORCHR]
MOV [DEVIOBUF],AL
DNODRD: MOV AH,BYTE PTR [IOCALL.REQSTAT+1]
NOT AH ; Zero = busy, not zero = ready
AND AH,STBUI SHR 8
invoke restore_world
ASSUME DS:NOTHING
MOV AX,WORD PTR [DEVIOBUF]
return
DCALLO:
MOV AH,87H
JMP SHORT DCALL
IOTOFILE:
ASSUME DS:NOTHING
OR AH,AH
JZ IOIN
DEC AH
JZ IOIST
DEC AH
JZ IOUT
return ; NON ZERO FLAG FOR OUTPUT STATUS
IOIST:
PUSH WORD PTR [SI.fcb_RR] ; Save position
PUSH WORD PTR [SI.fcb_RR+2]
CALL IOIN
POP WORD PTR [SI.fcb_RR+2] ; Restore position
POP WORD PTR [SI.fcb_RR]
return
IOUT:
CALL SETXADDR
invoke STORE
invoke FINNOSAV
CALL RESTXADDR ; If you change this into a jmp don't come
return ; crying to me when things don't work ARR
IOIN:
CALL SETXADDR
invoke LOAD
PUSH CX
invoke FINNOSAV
POP CX
OR CX,CX ; Check EOF
CALL RESTXADDR
MOV AL,[DEVIOBUF] ; Get byte from trans addr
retnz
MOV AL,1AH ; ^Z if EOF
return
SETXADDR:
POP WORD PTR [CALLSCNT] ; Return address
invoke save_world
PUSH WORD PTR [DMAADD] ; Save Disk trans addr
PUSH WORD PTR [DMAADD+2]
PUSH DS
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV CX,WORD PTR [IOXAD+2]
MOV WORD PTR [DMAADD+2],CX
MOV CX,WORD PTR [IOXAD]
MOV WORD PTR [DMAADD],CX ; Set byte trans addr
MOV CX,[IOSCNT] ; ioscnt specifies length of buffer
POP DS
ASSUME DS:NOTHING
MOV [SI.fcb_RECSIZ],1 ; One byte per record
MOV DX,SI ; FCB to DS:DX
invoke GETRRPOS
JMP SHORT RESTRET ; RETURN ADDRESS
RESTXADDR:
POP WORD PTR [CALLSCNT] ; Return address
POP WORD PTR [DMAADD+2] ; Restore Disk trans addr
POP WORD PTR [DMAADD]
invoke restore_world
RESTRET:JMP WORD PTR [CALLSCNT] ; Return address
IOFUNC ENDP
SUBTTL DEVIOCALL, DEVIOCALL2 - CALL A DEVICE
PAGE
procedure DEVIOCALL,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:SI Points to device FCB
; ES:BX Points to request data
; Function:
; Call the device
; Outputs:
; None
; DS:SI,AX destroyed, others preserved
LDS SI,DWORD PTR [SI.fcb_FIRCLUS]
entry DEVIOCALL2
; As above only DS:SI points to device header on entry, and DS:SI is preserved
MOV AX,[SI.SDEVSTRAT]
MOV WORD PTR [CALLDEVAD],AX
MOV WORD PTR [CALLDEVAD+2],DS
CALL DWORD PTR [CALLDEVAD]
MOV AX,[SI.SDEVINT]
MOV WORD PTR [CALLDEVAD],AX
CALL DWORD PTR [CALLDEVAD]
return
DEVIOCALL ENDP
SUBTTL DEVNAME - LOOK FOR NAME OF DEVICE
PAGE
procedure DEVNAME,NEAR
ASSUME DS:DOSGROUP,ES:DOSGROUP
; Inputs:
; DS,ES:DOSGROUP
; Filename in NAME1
; Function:
; Determine if file is in list of I/O drivers
; Outputs:
; Carry set if name not found
; ELSE
; Zero flag set
; BH = Bit 7,6 = 1, bit 5 = 0 (cooked mode)
; bits 0-4 set from low byte of attribute word
; DEVPT = DWORD pointer to Device header of device
; Registers BX destroyed
PUSH SI
PUSH DI
PUSH CX
IF KANJI
PUSH WORD PTR [NAME1]
CMP [NAME1],5
JNZ NOKTR
MOV [NAME1],0E5H
NOKTR:
ENDIF
TEST BYTE PTR [ATTRIB],attr_volume_id ; If looking for VOL id don't find devs
JNZ RET31
MOV SI,OFFSET DOSGROUP:NULDEV
LOOKIO:
ASSUME DS:NOTHING
TEST [SI.SDEVATT],DEVTYP
JZ SKIPDEV ; Skip block devices
PUSH SI
ADD SI,SDEVNAME
MOV DI,OFFSET DOSGROUP:NAME1
MOV CX,4 ; All devices are 8 letters
REPE CMPSW ; Check for name in list
POP SI
JZ IOCHK ; Found it?
SKIPDEV:
LDS SI,DWORD PTR [SI] ; Get address of next device
CMP SI,-1 ; At end of list?
JNZ LOOKIO
RET31: STC ; Not found
RETNV: PUSH SS
POP DS
ASSUME DS:DOSGROUP
IF KANJI
POP WORD PTR [NAME1]
ENDIF
POP CX
POP DI
POP SI
RET
IOCHK:
ASSUME DS:NOTHING
MOV WORD PTR [DEVPT+2],DS ; Save pointer to device
MOV BH,BYTE PTR [SI.SDEVATT]
OR BH,0C0H
AND BH,NOT 020H ;Clears Carry
MOV WORD PTR [DEVPT],SI
JMP RETNV
DevName ENDP
procedure GetBP,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; AL = Logical unit number (A = 0)
; Function:
; Find Drive Parameter Block
; Outputs:
; ES:BP points to DPB
; [THISDPB] = ES:BP
; Carry set if unit number bad
; No other registers altered
LES BP,[DPBHEAD] ; Just in case drive isn't valid
AND AL,3FH ; Mask out dirty and device bits
CMP AL,BYTE PTR [NUMIO]
CMC
JC GOTDPB ; Get drive A
FNDDPB:
CMP AL,ES:[BP.dpb_drive]
JZ GOTDPB ; Carry is clear if jump executed
LES BP,ES:[BP.dpb_next_dpb]
JMP SHORT FNDDPB
GOTDPB:
MOV WORD PTR [THISDPB],BP
MOV WORD PTR [THISDPB+2],ES
RET
GetBP ENDP
SUBTTL SETREAD, SETWRITE -- SET UP HEADER BLOCK
PAGE
procedure SETREAD,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:BX = Transfer Address
; CX = Record Count
; DX = Starting Record
; AH = Media Byte
; AL = Unit Code
; Function:
; Set up the device call header at DEVCALL
; Output:
; ES:BX Points to DEVCALL
; No other registers effected
PUSH DI
PUSH CX
PUSH AX
MOV CL,DEVRD
SETCALLHEAD:
MOV AL,DRDWRHL
PUSH SS
POP ES
MOV DI,OFFSET DOSGROUP:DEVCALL
STOSB ; length
POP AX
STOSB ; Unit
PUSH AX
MOV AL,CL
STOSB ; Command code
XOR AX,AX
STOSW ; Status
ADD DI,8 ; Skip link fields
POP AX
XCHG AH,AL
STOSB ; Media byte
XCHG AL,AH
PUSH AX
MOV AX,BX
STOSW
MOV AX,DS
STOSW ; Transfer addr
POP CX ; Real AX
POP AX ; Real CX
STOSW ; Count
XCHG AX,DX ; AX=Real DX, DX=real CX, CX=real AX
STOSW ; Start
XCHG AX,CX
XCHG DX,CX
POP DI
MOV BX,OFFSET DOSGROUP:DEVCALL
RET
entry SETWRITE
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:BX = Transfer Address
; CX = Record Count
; DX = Starting Record
; AH = Media Byte
; AL = Unit Code
; Function:
; Set up the device call header at DEVCALL
; Output:
; ES:BX Points to DEVCALL
; No other registers effected
PUSH DI
PUSH CX
PUSH AX
MOV CL,DEVWRT
ADD CL,[VERFLG]
JMP SHORT SETCALLHEAD
SETREAD ENDP
do_ext
CODE ENDS
END
+1084
View File
File diff suppressed because it is too large Load Diff
+507
View File
@@ -0,0 +1,507 @@
TITLE DIRCALL - Directory manipulation internal calls
NAME DIRCALL
; $MKDIR
; $CHDIR
; $RMDIR
.xlist
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
ifndef Kanji
Kanji equ 0
endif
i_need AUXSTACK,BYTE
i_need NoSetDir,BYTE
i_need CURBUF, DWORD
i_need DIRSTART,WORD
i_need THISDPB,DWORD
i_need NAME1,BYTE
i_need LASTENT,WORD
i_need ATTRIB,BYTE
i_need THISFCB,DWORD
i_need AUXSTACK,BYTE
i_need CREATING,BYTE
i_need DRIVESPEC,BYTE
i_need ROOTSTART,BYTE
i_need SWITCH_CHARACTER,BYTE
extrn sys_ret_ok:near,sys_ret_err:near
; XENIX CALLS
BREAK <$MkDir - Make a directory entry>
MKNERRJ: JMP MKNERR
NODEEXISTSJ: JMP NODEEXISTS
procedure $MKDIR,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to asciz name
; Function:
; Make a new directory
; Returns:
; STD XENIX Return
; AX = mkdir_path_not_found if path bad
; AX = mkdir_access_denied If
; Directory cannot be created
; Node already exists
; Device name given
; Disk or directory(root) full
invoke validate_path
JC MKNERRJ
MOV SI,DX
MOV WORD PTR [THISFCB+2],SS
MOV WORD PTR [THISFCB],OFFSET DOSGROUP:AUXSTACK-40 ; Scratch space
MOV AL,attr_directory
MOV WORD PTR [CREATING],0E500h
invoke MAKENODE
ASSUME DS:DOSGROUP
MOV AL,mkdir_path_not_found
JC MKNERRJ
JNZ NODEEXISTSJ
LDS DI,[CURBUF]
ASSUME DS:NOTHING
SUB SI,DI
PUSH SI ; Pointer to fcb_FIRCLUS
PUSH [DI.BUFSECNO] ; Sector of new node
PUSH SS
POP DS
ASSUME DS:DOSGROUP
PUSH [DIRSTART] ; Parent for .. entry
XOR AX,AX
MOV [DIRSTART],AX ; Null directory
invoke NEWDIR
JC NODEEXISTSPOPDEL ; No room
invoke GETENT ; First entry
LES DI,[CURBUF]
MOV ES:[DI.BUFDIRTY],1
ADD DI,BUFINSIZ ; Point at buffer
MOV AX,202EH ; ". "
STOSW
MOV DX,[DIRSTART] ; Point at itself
invoke SETDOTENT
MOV AX,2E2EH ; ".."
STOSW
POP DX ; Parent
invoke SETDOTENT
LES BP,[THISDPB]
POP DX ; Entry sector
XOR AL,AL ; Pre read
invoke GETBUFFR
MOV DX,[DIRSTART]
LDS DI,[CURBUF]
ASSUME DS:NOTHING
ZAPENT:
POP SI ; fcb_Firclus pointer
ADD SI,DI
MOV [SI],DX
XOR DX,DX
MOV [SI+2],DX
MOV [SI+4],DX
DIRUP:
MOV [DI.BUFDIRTY],1
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV AL,ES:[BP.dpb_drive]
invoke FLUSHBUF
SYS_RET_OKJ:
JMP SYS_RET_OK
NODEEXISTSPOPDEL:
POP DX ; Parent
POP DX ; Entry sector
LES BP,[THISDPB]
XOR AL,AL ; Pre read
invoke GETBUFFR
LDS DI,[CURBUF]
ASSUME DS:NOTHING
POP SI ; dir_first pointer
ADD SI,DI
SUB SI,dir_first ; Point back to start of dir entry
MOV BYTE PTR [SI],0E5H ; Free the entry
CALL DIRUP
NODEEXISTS:
MOV AL,mkdir_access_denied
MKNERR:
JMP SYS_RET_ERR
$MKDIR ENDP
BREAK <$ChDir -- Change current directory on a drive>
procedure $CHDIR,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to asciz name
; Function:
; Change current directory
; Returns:
; STD XENIX Return
; AX = chdir_path_not_found if error
invoke validate_path
JC PathTooLong
PUSH DS
PUSH DX
MOV SI,DX
invoke GETPATH
JC PATHNOGOOD
JNZ PATHNOGOOD
ASSUME DS:DOSGROUP
MOV AX,[DIRSTART]
MOV BX,AX
XCHG BX,ES:[BP.dpb_current_dir]
OR AX,AX
POP SI
POP DS
ASSUME DS:NOTHING
JZ SYS_RET_OKJ
MOV DI,BP
ADD DI,dpb_dir_text
MOV DX,DI
CMP [DRIVESPEC],0
JZ NODRIVESPEC
INC SI
INC SI
NODRIVESPEC:
MOV CX,SI
CMP [ROOTSTART],0
JZ NOTROOTPATH
INC SI
INC CX
JMP SHORT COPYTHESTRINGBXZ
NOTROOTPATH:
OR BX,BX ; Previous path root?
JZ COPYTHESTRING ; Yes
XOR BX,BX
ENDLOOP:
CMP BYTE PTR ES:[DI],0
JZ PATHEND
INC DI
INC BX
JMP SHORT ENDLOOP
PATHEND:
MOV AL,'/'
CMP AL,[switch_character]
JNZ SLASHOK
MOV AL,'\' ; Use the alternate character
SLASHOK:
STOSB
INC BX
JMP SHORT CHECK_LEN
PATHNOGOOD:
POP AX
POP AX
PATHTOOLONG:
error error_path_not_found
ASSUME DS:NOTHING
INCBXCHK:
INC BX
BXCHK:
CMP BX,DIRSTRLEN
return
COPYTHESTRINGBXZ:
XOR BX,BX
COPYTHESTRING:
LODSB
OR AL,AL
JNZ FOOB
JMP CPSTDONE
FOOB:
CMP AL,'.'
JZ SEEDOT
CALL COPYELEM
CHECK_LEN:
CMP BX,DIRSTRLEN
JB COPYTHESTRING
MOV AL,ES:[DI-1]
invoke PATHCHRCMP
JNZ OK_DI
DEC DI
OK_DI:
XOR AL,AL
STOSB ; Correctly terminate the path
MOV ES:[BP.dpb_current_dir],-1 ; Force re-validation
JMP SHORT PATHTOOLONG
SEEDOT:
LODSB
OR AL,AL ; Check for null
JZ CPSTDONEDEC
CMP AL,'.'
JNZ COPYTHESTRING ; eat ./
CALL DELELMES ; have ..
LODSB ; eat the /
OR AL,AL ; Check for null
JZ CPSTDONEDEC
JMP SHORT COPYTHESTRING
; Copy one element from DS:SI to ES:DI include trailing / not trailing null
; LODSB has already been done
COPYELEM:
PUSH DI ; Save in case too long
PUSH CX
MOV CX,800h ; length of filename
MOV AH,'.' ; char to stop on
CALL CopyPiece ; go for it!
CALL BXCHK ; did we go over?
JAE POPCXDI ; yep, go home
CMP AH,AL ; did we stop on .?
JZ CopyExt ; yes, go copy ext
OR AL,AL ; did we end on nul?
JZ DECSIRet ; yes, bye
CopyPathEnd:
STOSB ; save the path char
CALL INCBXCHK ; was there room for it?
JAE POPCXDI ; Nope
INC SI ; guard against following dec
DECSIRET:
DEC SI ; point back at null
POP CX
POP AX ; toss away saved DI
return
POPCXDI:
POP CX ; restore
POP DI ; point back...
return
CopyExt:
STOSB ; save the dot
CALL INCBXCHK ; room?
JAE POPCXDI ; nope.
LODSB ; get next char
XOR AH,AH ; NUL here
MOV CX,300h ; at most 3 chars
CALL CopyPiece ; go copy it
CALL BXCHK ; did we go over
JAE POPCXDI ; yep
OR AL,AL ; sucessful end?
JZ DECSIRET ; yes
JMP CopyPathEnd ; go stash path char
DELELMES:
; Delete one path element from ES:DI
DEC DI ; the '/'
DEC BX
IF KANJI
PUSH AX
PUSH CX
PUSH DI
PUSH DX
MOV CX,DI
MOV DI,DX
DELLOOP:
CMP DI,CX
JZ GOTDELE
MOV AL,ES:[DI]
INC DI
invoke TESTKANJ
JZ NOTKANJ11
INC DI
JMP DELLOOP
NOTKANJ11:
invoke PATHCHRCMP
JNZ DELLOOP
MOV DX,DI ; Point to char after '/'
JMP DELLOOP
GOTDELE:
MOV DI,DX
POP DX
POP AX ; Initial DI
SUB AX,DI ; Distance moved
SUB BX,AX ; Set correct BX
POP CX
POP AX
return
ELSE
DELLOOP:
CMP DI,DX
retz
PUSH AX
MOV AL,ES:[DI-1]
invoke PATHCHRCMP
POP AX
retz
DEC DI
DEC BX
JMP SHORT DELLOOP
ENDIF
CPSTDONEDEC:
DEC DI ; Back up over trailing /
CPSTDONE:
STOSB ; The NUL
JMP SYS_RET_OK
; copy a piece CH chars max until the char in AH (or path or NUL)
CopyPiece:
STOSB ; store the character
INC CL ; moved a byte
CALL INCBXCHK ; room enough?
JAE CopyPieceRet ; no, pop CX and DI
OR AL,AL ; end of string?
JZ CopyPieceRet ; yes, dec si and return
IF KANJI
CALL TestKanj ; was it kanji?
JZ NotKanj ; nope
MOVSB ; move the next byte
CALL INCBXCHK ; room for it?
JAE CopyPieceRet ; nope
INC CL ; moved a byte
NotKanj:
ENDIF
CMP CL,CH ; move too many?
JBE CopyPieceNext ; nope
IF KANJI
CALL TestKanj ; was the last byte kanji
JZ NotKanj2 ; no only single byte backup
DEC DI ; back up a char
DEC BX
NotKanj2:
ENDIF
DEC DI ; back up a char
DEC BX
CopyPieceNext:
LODSB ; get next character
invoke PathChrCmp ; end of road?
JZ CopyPieceRet ; yep, return and don't dec SI
CMP AL,AH ; end of filename?
JNZ CopyPiece ; go do name
CopyPieceRet:
return ; bye!
$CHDIR ENDP
BREAK <$RmDir -- Remove a directory>
NOPATHJ: JMP NOPATH
procedure $RMDIR,NEAR ; System call 47
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to asciz name
; Function:
; Delete directory if empty
; Returns:
; STD XENIX Return
; AX = rmdir_path_not_found If path bad
; AX = rmdir_access_denied If
; Directory not empty
; Path not directory
; Root directory specified
; Directory malformed (. and .. not first two entries)
; AX = rmdir_current_directory
invoke Validate_path
JC NoPathJ
MOV SI,DX
invoke GETPATH
JC NOPATHJ
ASSUME DS:DOSGROUP
JNZ NOTDIRPATH
MOV DI,[DIRSTART]
OR DI,DI
JZ NOTDIRPATH
MOV CX,ES:[BP.dpb_current_dir]
CMP CX,-1
JNZ rmdir_current_dir_check
invoke GetCurrDir
invoke Get_user_stack
MOV DX,[SI.user_DX]
MOV DS,[SI.user_DS]
JMP $RMDIR
NOTDIRPATHPOP:
POP AX
POP AX
NOTDIRPATH:
error error_access_denied
rmdir_current_dir_check:
CMP DI,CX
JNZ rmdir_get_buf
error error_current_directory
rmdir_get_buf:
LDS DI,[CURBUF]
ASSUME DS:NOTHING
SUB BX,DI
PUSH BX ; Save entry pointer
PUSH [DI.BUFSECNO] ; Save sector number
PUSH SS
POP DS
ASSUME DS:DOSGROUP
PUSH SS
POP ES
MOV DI,OFFSET DOSGROUP:NAME1
MOV AL,'?'
MOV CX,11
REP STOSB
XOR AL,AL
STOSB
invoke STARTSRCH
invoke GETENTRY
MOV DS,WORD PTR [CURBUF+2]
ASSUME DS:NOTHING
MOV SI,BX
LODSW
CMP AX,(' ' SHL 8) OR '.'
JNZ NOTDIRPATHPOP
ADD SI,32-2
LODSW
CMP AX,('.' SHL 8) OR '.'
JNZ NOTDIRPATHPOP
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV [LASTENT],2 ; Skip . and ..
invoke GETENTRY
MOV [ATTRIB],attr_directory+attr_hidden+attr_system
invoke SRCH
JNC NOTDIRPATHPOP
LES BP,[THISDPB]
MOV BX,[DIRSTART]
invoke RELEASE
POP DX
XOR AL,AL
invoke GETBUFFR
LDS DI,[CURBUF]
ASSUME DS:NOTHING
POP BX
ADD BX,DI
MOV BYTE PTR [BX],0E5H ; Free the entry
JMP DIRUP
NOPATH:
error error_path_not_found
$RMDIR ENDP
do_ext
CODE ENDS
END
+1302
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
msdos mscode dosmes misc getset dircall alloc dev dir +
disk fat rom stdbuf stdcall stdctrlc stdfcb stdproc +
stdio time xenix xenix2;

+274
View File
@@ -0,0 +1,274 @@
;
; Macro file for MSDOS.
;
SUBTTL BREAK a listing into pages and give new subtitles
PAGE
BREAK MACRO subtitle
SUBTTL subtitle
PAGE
ENDM
BREAK <I_NEED: declare a variable external, if necessary, and allocate a size>
;
; declare a variable external and allocate a size
;
I_NEED MACRO sym,len
DATA SEGMENT BYTE PUBLIC 'DATA'
IFIDN <len>,<WORD>
EXTRN &sym:WORD
ELSE
IFIDN <len>,<DWORD>
EXTRN &sym:DWORD
ELSE
EXTRN &sym:BYTE
ENDIF
ENDIF
DATA ENDS
ENDM
;
; call a procedure that may be external. The call will be short.
;
invoke MACRO name
.xcref
IF2
IFNDEF name
EXTRN name:NEAR
ENDIF
ENDIF
.cref
CALL name
ENDM
PAGE
;
; jump to a label that may be external. The jump will be near.
;
transfer MACRO name
.xcref
IF2
IFNDEF name
EXTRN name:NEAR
ENDIF
ENDIF
.cref
JUMP name
ENDM
;
; get a short address in a word
;
short_addr MACRO name
IFDIF <name>,<?>
.xcref
IF2
IFNDEF name
EXTRN name:NEAR
ENDIF
ENDIF
.cref
DW OFFSET DOSGROUP:name
ELSE
DW ?
ENDIF
ENDM
;
; get a long address in a dword
;
long_addr MACRO name
.xcref
IF2
IFNDEF name
EXTRN name:NEAR
ENDIF
.cref
DD name
ENDM
;
; declare a PROC near or far but PUBLIC nonetheless
;
procedure MACRO name,distance
PUBLIC name
name PROC distance
ENDM
PAGE
;
; define a data item to be public and of an appropriate size/type
;
I_AM MACRO name,size
PUBLIC name
IFIDN <size>,<WORD>
name DW ?
ELSE
IFIDN <size>,<DWORD>
name DD ?
ELSE
IFIDN <size>,<BYTE>
name DB ?
ELSE
name DB size DUP (?)
ENDIF
ENDIF
ENDIF
ENDM
PAGE
;
; call the macro chain
;
do_ext macro
endm
PAGE
;
; define an entry in a procedure
;
entry macro name
PUBLIC name
name:
endm
BREAK <ERROR - print a message and then jump to a label>
error macro code
local a
.xcref
MOV AL,code
transfer SYS_RET_ERR
.cref
ENDM
BREAK <JUMP - real jump that links up shortwise>
;
; given a label <lbl> either 2 byte jump to another label <lbl>_J
; if it is near enough or 3 byte jump to <lbl>
;
jump macro lbl
local a
.xcref
a:
ifndef lbl&_J ;; is this the first invocation
JMP lbl
ELSE
IF lbl&_J GE $
JMP lbl
ELSE
IF ($-lbl&_J) GT 126 ;; is the jump too far away?
JMP lbl
ELSE ;; do the short one...
JMP lbl&_J
ENDIF
ENDIF
ENDIF
lbl&_j = a
.cref
endm
BREAK <RETURN - return from a function>
return macro
local a
.xcref
a:
RET
ret_l = a
.cref
endm
BREAK <CONDRET - conditional return>
makelab macro l,cc,ncc
local a
j&ncc a ;; j<NCC> a:
return ;; return
a: ;; a:
ret_&cc = ret_l ;; define ret_<CC> to be ret_l
endm
condret macro cc,ncc
local a,b
ifdef ret_l ;; if ret_l is defined
if (($ - ret_l) le 126) and ($ gt ret_l)
;; if ret_l is near enough then
a: j&cc ret_l ;; a: j<CC> to ret_l
ret_&cc = a ;; define ret_<CC> to be a:
else
makelab a,cc,ncc
endif
else
ifdef ret_&cc ;; if ret_<CC> defined
if (($ - ret_&cc) le 126) and ($ gt ret_&cc)
;; if ret_<CC> is near enough
a: j&cc ret_&cc ;; a: j<CC> to ret_<CC>
ret_&cc = a ;; define ret_<CC> to be a:
else
makelab a,cc,ncc
endif
else
makelab a,cc,ncc
endif
endif
endm
;condret macro cc,ncc
; local a,b
; ifdef ret_l ; if ret_l is defined
; if (($ - ret_l) le 126) and ($ gt ret_l)
; ; if ret_l is near enough then
; a: j&cc ret_l ; a: j<CC> to ret_l
; ret_&cc = a ; define ret_<CC> to be a:
; exitm
; endif
; endif
; ifdef ret_&cc ; if ret_<CC> defined
; if (($ - ret_&cc) le 126) and ($ gt ret_&cc)
; ; if ret_<CC> is near enough
; a: j&cc ret_&cc ; a: j<CC> to ret_<CC>
; ret_&cc = a ; define ret_<CC> to be a:
; exitm
; endif
; endif
; j&ncc a ; j<NCC> a:
; return ; return
; a: ; a:
; ret_&cc = ret_l ; define ret_<CC> to be ret_l
;endm
;
BREAK <RETZ - return if zero, links up shortwise if necessary>
retz macro
condret z,nz
endm
BREAK <RETNZ - return if not zero, links up shortwise if necessary>
retnz macro
condret nz,z
endm
BREAK <RETC - return if carry set, links up shortwise if necessary>
retc macro
condret c,nc
endm
BREAK <RETNC - return if not carry, links up shortwise if necessary>
retnc macro
condret nc,c
endm
BREAK <CONTEXT - set the DOS context to a particular register>
context macro r
PUSH SS
POP r
ASSUME r:DOSGROUP
endm
+355
View File
@@ -0,0 +1,355 @@
INCLUDE STDSW.ASM
KANJI EQU FALSE
Rainbow EQU FALSE
INCLUDE DOSSYM.ASM
;
; segment ordering for MSDOS
;
CONSTANTS SEGMENT BYTE PUBLIC 'CONST'
CONSTANTS ENDS
DATA SEGMENT BYTE PUBLIC 'DATA'
DATA ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
CODE ENDS
LAST SEGMENT BYTE PUBLIC 'LAST'
LAST ENDS
DOSGROUP GROUP CODE,CONSTANTS,DATA,LAST
CONSTANTS SEGMENT BYTE PUBLIC 'CONST'
PUBLIC DIVMES
DIVMES DB 13,10,"Divide overflow",13,10
PUBLIC DivMesLen
DivMesLen DB $-DivMes ; Length of the above message in bytes
;
; The next variable points to the country table for the current country
; ( the table returned by the AL=0 INTERNATIONAL call).
;
PUBLIC Current_Country
IF KANJI
Current_Country DW OFFSET DOSGROUP:JAPTABLE
ELSE
Current_Country DW OFFSET DOSGROUP:USTABLE
ENDIF
;
; The international tabel(s).
; This is simply a sequence of tables of the following form:
;
; BYTE Size of this table excluding this byte and the next
; BYTE Country code represented by this table
; A sequence of n bytes, where n is the number specified
; by the first byte above and is not > internat_block_max,
; in the correct order for being returned by the
; INTERNATIONAL call as follows:
; WORD Date format 0=mdy, 1=dmy, 2=ymd
; 5 BYTE Currency symbol null terminated
; 2 BYTE thousands separator null terminated
; 2 BYTE Decimal point null terminated
; 2 BYTE Date separator null terminated
; 2 BYTE Time separator null terminated
; 1 BYTE Bit field. Currency format.
; Bit 0. =0 $ before # =1 $ after #
; Bit 1. no. of spaces between # and $ (0 or 1)
; 1 BYTE No. of significant decimal digits in currency
; 1 BYTE Bit field. Time format.
; Bit 0. =0 12 hour clock =1 24 hour
; WORD Segment offset for address of case conversion routine
; WORD RESERVED. Filled in by DOS. Segment value for above routine
; 2 BYTE Data list separator null terminated.
; NOTE: The segment part of the DWORD Map_call is set
; by the INTERNATIONAL call. Do not try to initialize
; it to anything meaningful.
;
; The list of tables is terminated by putting a byte of -1 after the last
; table (a table with length -1).
PUBLIC international_table
international_table LABEL BYTE
IF KANJI
DB SIZE internat_block ; Size in bytes of this table
DB 81 ; Country code
JAPTABLE internat_block <2,'\',0,0,0,0,',',0,'.',0,'-',0,':',0,0,0,1,OFFSET DOSGROUP:MAP_DCASE , 0,',',0>
ENDIF
DB SIZE internat_block ; Size in bytes of this table
DB 1 ; Country code
USTABLE internat_block <0,'$',0,0,0,0,',',0,'.',0,'-',0,':',0,0,2,0,OFFSET DOSGROUP:MAP_DCASE,0,',',0>
; Tables for the IBM PC character set follow. The values
; associated with some of the currency symbols may change with
; other character sets. You may wish to add or delete country
; entries. NOTE: It is not a mistake that the JAPANESE entry
; has different currency symbols for the KANJI and
; non-KANJI versions.
IF NOT KANJI
IF IBM
DB SIZE internat_block ; Size in bytes of this table
DB 44 ; Country code
UKTABLE internat_block <1,9Ch,0,0,0,0,',',0,'.',0,'-',0,':',0,0,2,0,OFFSET DOSGROUP:MAP_DCASE,0,',',0>
DB SIZE internat_block ; Size in bytes of this table
DB 49 ; Country code
GRMTABLE internat_block <1,'D','M',0,0,0,'.',0,',',0,'.',0,'.',0,3,2,1,OFFSET DOSGROUP:MAP_DCASE,0,';',0>
DB SIZE internat_block ; Size in bytes of this table
DB 33 ; Country code
FRNTABLE internat_block <1,'F',0,0,0,0,' ',0,',',0,'/',0,':',0,3,2,1,OFFSET DOSGROUP:MAP_DCASE,0,';',0>
DB SIZE internat_block ; Size in bytes of this table
DB 81 ; Country code
JAPTABLE internat_block <2,9DH,0,0,0,0,',',0,'.',0,'-',0,':',0,0,0,1,OFFSET DOSGROUP:MAP_DCASE , 0,',',0>
ENDIF
ENDIF
DB -1 ; End of tables
CONSTANTS ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
;CASE MAPPER ROUTINE FOR 80H-FFH character range
; ENTRY: AL = Character to map
; EXIT: AL = The converted character
; Alters no registers except AL and flags.
; The routine should do nothing to chars below 80H.
;
; Example:
MAP_DCASE PROC FAR
IF NOT KANJI
IF IBM
CMP AL,80H
JB L_RET ;Map no chars below 80H ever
CMP AL,0A7H
JA L_RET ;This routine maps chars between 80H and A7H
SUB AL,80H ;Turn into index value
PUSH DS
PUSH BX
PUSH CS ;Move to DS
POP DS
MOV BX,OFFSET DOSGROUP:TABLE
XLAT ;Get upper case character
POP BX
POP DS
ENDIF
ENDIF
L_RET: RET
MAP_DCASE ENDP
IF NOT KANJI
IF IBM
TABLE: DB 80H,9AH,"E","A",8EH,"A",8FH,80H
DB "E","E","E","I","I","I",8EH,8FH
DB 90H,92H,92H,"O",99H,"O","U","U"
DB "Y",99H,9AH,9BH,9CH,9DH,9EH,9FH
DB "A","I","O","U",0A5H,0A5H,0A6H,0A7H
ENDIF
ENDIF
SUBTTL EDIT FUNCTION ASSIGNMENTS AND HEADERS
PAGE
; The following two tables implement the current buffered input editing
; routines. The tables are pairwise associated in reverse order for ease
; in indexing. That is; The first entry in ESCTAB corresponds to the last
; entry in ESCFUNC, and the last entry in ESCTAB to the first entry in ESCFUNC.
PUBLIC ESCCHAR
ESCCHAR DB ESCCH ;Lead-in character for escape sequences
IF NOT Rainbow
ESCTAB:
IF NOT IBM
IF WANG
DB 0C0h ; ^Z inserter
DB 0C1H ; Copy one char
DB 0C7H ; Skip one char
DB 08AH ; Copy to char
DB 088H ; Skip to char
DB 09AH ; Copy line
DB 0CBH ; Kill line (no change in template)
DB 08BH ; Reedit line (new template)
DB 0C3H ; Backspace
DB 0C6H ; Enter insert mode
IF NOT TOGLINS
DB 0D6H ; Exit insert mode
ENDIF
DB 0C6H ; Escape character
DB 0C6H ; End of table
ELSE
; VT52 equivalences
DB "Z" ; ^Z inserter
DB "S" ; F1 Copy one char
DB "V" ; F4 Skip one char
DB "T" ; F2 Copy to char
DB "W" ; F5 Skip to char
DB "U" ; F3 Copy line
DB "E" ; SHIFT ERASE Kill line (no change in template)
DB "J" ; ERASE Reedit line (new template)
DB "D" ; LEFT Backspace
DB "P" ; BLUE Enter insert mode
DB "Q" ; RED Exit insert mode
DB "R" ; GRAY Escape character
DB "R" ; End of table
ENDIF
ENDIF
IF IBM
DB 64 ; Ctrl-Z - F6
DB 77 ; Copy one char - -->
DB 59 ; Copy one char - F1
DB 83 ; Skip one char - DEL
DB 60 ; Copy to char - F2
DB 62 ; Skip to char - F4
DB 61 ; Copy line - F3
DB 61 ; Kill line (no change to template ) - Not used
DB 63 ; Reedit line (new template) - F5
DB 75 ; Backspace - <--
DB 82 ; Enter insert mode - INS (toggle)
DB 65 ; Escape character - F7
DB 65 ; End of table
ENDIF
ESCEND:
ESCTABLEN EQU ESCEND-ESCTAB
ESCFUNC LABEL WORD
short_addr GETCH ; Ignore the escape sequence
short_addr TWOESC
IF NOT TOGLINS
short_addr EXITINS
ENDIF
short_addr ENTERINS
short_addr BACKSP
short_addr REEDIT
short_addr KILNEW
short_addr COPYLIN
short_addr SKIPSTR
short_addr COPYSTR
short_addr SKIPONE
short_addr COPYONE
IF IBM
short_addr COPYONE
ENDIF
short_addr CTRLZ
ENDIF
;
; OEMFunction key is expected to process a single function
; key input from a device and dispatch to the proper
; routines leaving all registers UNTOUCHED.
;
; Inputs: CS, SS are DOSGROUP
; Outputs: None. This function is expected to JMP to onw of
; the following labels:
;
; GetCh - ignore the sequence
; TwoEsc - insert an ESCChar in the buffer
; ExitIns - toggle insert mode
; EnterIns - toggle insert mode
; BackSp - move backwards one space
; ReEdit - reedit the line with a new template
; KilNew - discard the current line and start from scratch
; CopyLin - copy the rest of the template into the line
; SkipStr - read the next character and skip to it in the template
; CopyStr - read next char and copy from template to line until char
; SkipOne - advance position in template one character
; CopyOne - copy next character in template into line
; CtrlZ - place a ^Z into the template
; Registers that are allowed to be modified by this function are:
; AX, CX, BP
PUBLIC OEMFunctionKey
OEMFunctionKey PROC NEAR
ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
invoke $STD_CON_INPUT_NO_ECHO ; Get the second byte of the sequence
IF NOT Rainbow
MOV CL,ESCTABLEN ; length of table for scan
PUSH DI ; save DI (cannot change it!)
MOV DI,OFFSET DOSGROUP:ESCTAB ; offset of second byte table
REPNE SCASB ; Look it up in the table
POP DI ; restore DI
SHL CX,1 ; convert byte offset to word
MOV BP,CX ; move to indexable register
JMP [BP+OFFSET DOSGROUP:ESCFUNC] ; Go to the right routine
ENDIF
IF Rainbow
TransferIf MACRO value,address
local a
CMP AL,value
JNZ a
transfer address
a:
ENDM
CMP AL,'[' ; is it second lead char
JZ EatParm ; yes, go walk tree
GoGetCh:
transfer GetCh ; no, ignore sequence
EatParm:
invoke $STD_CON_INPUT_NO_ECHO ; get argument
CMP AL,'A' ; is it alphabetic arg?
JAE EatAlpha ; yes, go snarf one up
XOR BP,BP ; init digit counter
JMP InDigit ; jump into internal eat digit routine
EatNum:
invoke $STD_CON_INPUT_NO_ECHO ; get next digit
InDigit:
CMP AL,'9' ; still a digit?
JA CheckNumEnd ; no, go check for end char
SUB AL,'0' ; turn into potential digit
JB GoGetCh ; oops, not a digit, ignore
MOV CX,BP ; save BP for 10 multiply
CBW ; make AL into AX
SHL BP,1 ; 2*BP
SHL BP,1 ; 4*BP
ADD BP,CX ; 5*BP
SHL BP,1 ; 10*BP
ADD BP,AX ; 10*BP + digit
JMP EatNum ; continue with number
CheckNumEnd:
CMP AL,7Eh ; is it end char ~
JNZ GoGetCh ; nope, ignore key sequence
MOV AX,BP
transferIf 1,SkipStr ; FIND key
transferIf 2,EnterIns ; INSERT HERE key
transferIf 3,SkipOne ; REMOVE
transferIf 4,CopyStr ; SELECT
transferIf 17,TwoEsc ; INTERRUPT
transferIf 18,ReEdit ; RESUME
transferIf 19,KilNew ; CANCEL
transferIf 21,CtrlZ ; EXIT
transferIf 29,CopyLin ; DO
JMP GoGetCh
EatAlpha:
CMP AL,'O' ; is it O?
JA GoGetCh ; no, after assume bogus
JZ EatPQRS ; eat the rest of the bogus key
transferIf 'C',CopyOne ; RIGHT
transferIf 'D',BackSp ; LEFT
JMP GoGetCh
EatPQRS:
invoke $STD_CON_INPUT_NO_ECHO ; eat char after O
JMP GoGetCh
ENDIF
OEMFunctionKey ENDP
CODE ENDS
do_ext
END

+17
View File
@@ -0,0 +1,17 @@
;
; segment ordering for MSDOS
;
CONSTANTS SEGMENT BYTE PUBLIC 'CONST'
CONSTANTS ENDS
DATA SEGMENT BYTE PUBLIC 'DATA'
DATA ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
CODE ENDS
LAST SEGMENT BYTE PUBLIC 'LAST'
LAST ENDS
DOSGROUP GROUP CODE,CONSTANTS,DATA,LAST
+963
View File
@@ -0,0 +1,963 @@
include DOSMAC.ASM
IF2
%OUT DOSSYM in Pass 2
ENDIF
IFNDEF ALTVECT
ALTVECT EQU 0 ;FALSE
ENDIF
DOS_MAJOR_VERSION EQU 2
DOS_MINOR_VERSION EQU 11
BREAK <Control character definitions>
c_DEL EQU 7Fh ; ASCII rubout or delete previous char
c_BS EQU 08h ; ^H ASCII backspace
c_CR EQU 0Dh ; ^M ASCII carriage return
c_LF EQU 0Ah ; ^J ASCII linefeed
c_ETB EQU 17h ; ^W ASCII end of transmission
c_NAK EQU 15h ; ^U ASCII negative acknowledge
c_ETX EQU 03h ; ^C ASCII end of text
c_HT EQU 09h ; ^I ASCII tab
BREAK <BPB Definition>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; ;
; C A V E A T P R O G R A M M E R ;
; ;
; Certain structures, constants and system calls below are private to ;
; the DOS and are extremely version-dependent. They may change at any ;
; time at the implementors' whim. As a result, they must not be ;
; documented to the general public. If an extreme case arises, they ;
; must be documented with this warning. ;
; ;
; Those structures and constants that are subject to the above will be ;
; marked and bracketed with the flag: ;
; ;
; C A V E A T P R O G R A M M E R ;
; ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <Bios Parameter Block>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
; Bios Parameter Block definition
; This structure is used to build a full DPB
BPBLOCK STRUC
BPSECSZ DW ? ; Size in bytes of physical sector
BPCLUS DB ? ; Sectors/Alloc unit
BPRES DW ? ; Number of reserved sectors
BPFTCNT DB ? ; Number of FATs
BPDRCNT DW ? ; Number of directory entries
BPSCCNT DW ? ; Total number of sectors
BPMEDIA DB ? ; Media descriptor byte
BPFTSEC DW ? ; Number of sectors taken up by one FAT
BPBLOCK ENDS
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <Disk I/O Buffer Header>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
; Field definition for I/O buffer information
BUFFINFO STRUC
NEXTBUF DD ? ; Pointer to next buffer in list
; The next two items are often refed as a word
BUFDRV DB ? ; Logical drive # assoc with buffer FF = free
BUFDIRTY DB ? ; Dirty flag
BUFPRI DB ? ; Buffer selection priority (see EQUs below)
VISIT DB ? ; Visit flag for buffer pool scans
BUFSECNO DW ? ; Sector number of buffer
; The next two items are often refed as a word
BUFWRTCNT DB ? ; For FAT sectors, # times sector written out
BUFWRTINC DB ? ; " " " , # sectors between each write
BUFDRVDP DD ? ; Pointer to drive parameters
BUFFINFO ENDS
BUFINSIZ EQU SIZE BUFFINFO
; Size of structure in bytes
FREEPRI EQU 0
LBRPRI EQU 2 ; Last byte of buffer read
LBWPRI EQU 4 ; Last byte written
RPRI EQU 6 ; Read but not last byte
WPRI EQU 8 ; Written but not last byte
DIRPRI EQU 15 ; Directory Sector
FATPRI EQU 30 ; FAT sector
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <User stack inside of system call>
; Location of user registers relative user stack pointer
user_environ STRUC
user_AX DW ?
user_BX DW ?
user_CX DW ?
user_DX DW ?
user_SI DW ?
user_DI DW ?
user_BP DW ?
user_DS DW ?
user_ES DW ?
user_IP DW ?
user_CS DW ?
user_F DW ?
user_environ ENDS
BREAK <interrupt definitions>
INTTAB EQU 20H
INTBASE EQU 4 * inttab
ENTRYPOINT EQU INTBASE+40H
IF ALTVECT
ALTTAB EQU 0F0H
ALTBASE EQU 4 * ALTTAB
ENDIF
;
; interrupt assignments
;
IF NOT ALTVECT
int_abort EQU INTTAB ; abort process
int_command EQU int_abort+1 ; call MSDOS
int_terminate EQU int_abort+2 ; int to terminate address
int_ctrl_c EQU int_abort+3 ; ^c trapper
int_fatal_abort EQU int_abort+4 ; hard disk error
int_disk_read EQU int_abort+5 ; logical sector disk read
int_disk_write EQU int_abort+6 ; logical sector disk write
int_keep_process EQU int_abort+7 ; terminate program and stay
; resident
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
int_spooler EQU int_abort+8 ; spooler call
int_fastcon EQU int_abort+9 ; fast CON interrupt
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
ELSE
int_abort EQU INTTAB ; abort process
int_command EQU int_abort+1 ; call MSDOS
int_terminate EQU ALTTAB ; int to terminate address
int_ctrl_c EQU int_terminate+1 ; ^c trapper
int_fatal_abort EQU int_terminate+2 ; hard disk error
int_disk_read EQU int_abort+5 ; logical sector disk read
int_disk_write EQU int_abort+6 ; logical sector disk write
int_keep_process EQU int_abort+7 ; terminate program and stay
; resident
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
int_spooler EQU int_terminate+3 ; spooler call
int_fastcon EQU int_abort+9 ; fast CON interrupt
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
ENDIF
addr_int_abort EQU 4 * int_abort
addr_int_command EQU 4 * int_command
addr_int_terminate EQU 4 * int_terminate
addr_int_ctrl_c EQU 4 * int_ctrl_c
addr_int_fatal_abort EQU 4 * int_fatal_abort
addr_int_disk_read EQU 4 * int_disk_read
addr_int_disk_write EQU 4 * int_disk_write
addr_int_keep_process EQU 4 * int_keep_process
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
addr_int_spooler EQU 4 * int_spooler
addr_int_fastcon EQU 4 * int_fastcon
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <Disk map>
; MSDOS partitions the disk into 4 sections:
;
; phys sector 0: +-------------------+
; | | boot/reserved |
; | +-------------------+
; | | File allocation |
; v | table(s) |
; | (multiple copies |
; | are kept) |
; +-------------------+
; | Directory |
; +-------------------+
; | File space |
; +-------------------+
; | Unaddressable |
; | (to end of disk) |
; +-------------------+
;
; All partition boundaries are sector boundaries. The size of the FAT is
; adjusted to maximize the file space addressable.
BREAK <Directory entry>
;
; +---------------------------+
; | (12 BYTE) filename/ext | 0 0
; +---------------------------+
; | (BYTE) attributes | 11 B
; +---------------------------+
; | (10 BYTE) reserved | 12 C
; +---------------------------+
; | (WORD) time of last write | 22 16
; +---------------------------+
; | (WORD) date of last write | 24 18
; +---------------------------+
; | (WORD) First cluster | 26 1A
; +---------------------------+
; | (DWORD) file size | 28 1C
; +---------------------------+
;
; First byte of filename = E5 -> free directory entry
; = 00 -> end of allocated directory
; Time: Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour
; Date: Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980
;
dir_entry STRUC
dir_name DB 11 DUP (?) ; file name
dir_attr DB ? ; attribute bits
dir_pad DB 10 DUP (?) ; reserved for expansion
dir_time DW ? ; time of last write
dir_date DW ? ; date of last write
dir_first DW ? ; first allocation unit of file
dir_size_l DW ? ; low 16 bits of file size
dir_size_h DW ? ; high 16 bits of file size
dir_entry ENDS
attr_read_only EQU 1h
attr_hidden EQU 2h
attr_system EQU 4h
attr_volume_id EQU 8h
attr_directory EQU 10h
attr_archive EQU 20h
attr_all EQU attr_hidden+attr_system+attr_directory
; OR of hard attributes for FINDENTRY
attr_ignore EQU attr_read_only+attr_archive
; ignore this(ese) attribute(s) during
; search first/next
attr_changeable EQU attr_read_only+attr_hidden+attr_system+attr_archive
; changeable via CHMOD
BREAK <File allocation Table information>
;
; The File Allocation Table uses a 12-bit entry for each allocation unit on
; the disk. These entries are packed, two for every three bytes. The contents
; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result
; to the base address of the Allocation Table; 3) fetching the 16-bit word
; at this address; 4) If N was odd (so that N*1.5 was not an integer), shift
; the word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry
; number zero is used as an end-of-file trap in the OS and is passed to the
; BIOS to help determine disk format. Entry 1 is reserved for future use.
; The first available allocation unit is assigned entry number two, and even
; though it is the first, is called cluster 2. Entries greater than 0FF8H
; are end of file marks; entries of zero are unallocated. Otherwise, the
; contents of a FAT entry is the number of the next cluster in the file.
;
; Clusters with bad sectors are tagged with FF7H. Any non-zero number would
; do because these clusters show as allocated, but are not part of any
; allocation chain and thus will never be allocated to a file. A particular
; number is selected so that disk checking programs know what to do (ie. a
; cluster with entry FF7H which is not in a chain is not an error).
BREAK <DPB structure>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
DIRSTRLEN EQU 64 ; Max length in bytes of directory strings
dpb STRUC
dpb_drive DB ? ; Logical drive # assoc with DPB (A=0,B=1,...)
dpb_UNIT DB ? ; Driver unit number of DPB
dpb_sector_size DW ? ; Size of physical sector in bytes
dpb_cluster_mask DB ? ; Sectors/cluster - 1
dpb_cluster_shift DB ? ; Log2 of sectors/cluster
dpb_first_FAT DW ? ; Starting record of FATs
dpb_FAT_count DB ? ; Number of FATs for this drive
dpb_root_entries DW ? ; Number of directory entries
dpb_first_sector DW ? ; First sector of first cluster
dpb_max_cluster DW ? ; Number of clusters on drive + 1
dpb_FAT_size DB ? ; Number of records occupied by FAT
dpb_dir_sector DW ? ; Starting record of directory
dpb_driver_addr DD ? ; Pointer to driver
dpb_media DB ? ; Media byte
dpb_first_access DB ? ; This is initialized to -1 to force a media
; check the first time this DPB is used
dpb_next_dpb DD ? ; Pointer to next Drive parameter block
dpb_current_dir DW ? ; Cluster number of start of current directory
; 0 indicates root, -1 indicates invalid (disk
; ? changed)
dpb_dir_text DB DIRSTRLEN DUP(?)
; ASCIZ string of current directory
dpb ENDS
DPBSIZ EQU SIZE dpb ; Size of the structure in bytes
DSKSIZ = dpb_max_cluster ; Size of disk (temp used during init only)
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <File Control Block definition>
;
; Field definition for FCBs
; The FCB has the following structure:
;
; +---------------------------+
; | Drive indicator(byte) |
; +---------------------------+
; | Filename (8 chars) |
; +---------------------------+
; | Extension (3 chars) |
; +---------------------------+
; | Current Extent(word) |
; +---------------------------+
; | Record size (word) |
; +---------------------------+
; | File Size (2 words) |
; +---------------------------+
; | Date of write |
; +---------------------------+
; | Time of write |
; +---------------------------+
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
; | Flags: |
; | bit 7=0 file/1 device |
; | bit 6=0 if dirty |
; | bits 0-5 deviceid |
; +---------------------------+
; | first cluster in file |
; +---------------------------+
; | position of last cluster |
; +---------------------------+
; | last cluster accessed | 12 bit-+--- packed in 3 bytes
; +---------------------------+ |
; | parent directory | <------+
; +---------------------------+
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; | next record number |
; +---------------------------+
; | random record number |
; +---------------------------+
;
sys_fcb STRUC
fcb_drive DB ?
fcb_name DB 8 DUP (?)
fcb_ext DB 3 DUP (?)
fcb_EXTENT DW ?
fcb_RECSIZ DW ? ; Size of record (user settable)
fcb_FILSIZ DW ? ; Size of file in bytes; used with the following
; word
fcb_DRVBP DW ? ; BP for SEARCH FIRST and SEARCH NEXT
fcb_FDATE DW ? ; Date of last writing
fcb_FTIME DW ? ; Time of last writing
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
fcb_DEVID DB ? ; Device ID number, bits 0-5 if file.
; bit 7=0 for file, bit 7=1 for I/O device
; If file, bit 6=0 if dirty
; If I/O device, bit 6=0 if EOF (input)
; Bit 5=1 if Raw mode
; Bit 0=1 if console input device
; Bit 1=1 if console output device
; Bit 2=1 if null device
; Bit 3=1 if clock device
fcb_FIRCLUS DW ? ; First cluster of file
fcb_CLUSPOS DW ? ; Position of last cluster accessed
fcb_LSTCLUS DW ? ; Last cluster accessed and directory pack 2 12
DB ? ; bit numbers into 24 bits...
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
fcb_NR DB ? ; Next record
fcb_RR DB 4 DUP (?) ; Random record
sys_fcb ENDS
FILDIRENT = fcb_FILSIZ ; Used only by SEARCH FIRST and SEARCH
; NEXT
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
devid_file_clean EQU 40h ; true if file and not written
devid_file_mask_drive EQU 3Fh ; mask for drive number
devid_device EQU 80h ; true if a device
devid_device_EOF EQU 40h ; true if end of file reached
devid_device_raw EQU 20h ; true if in raw mode
devid_device_special EQU 10h ; true if special device
devid_device_clock EQU 08h ; true if clock device
devid_device_null EQU 04h ; true if null device
devid_device_con_out EQU 02h ; true if console output
devid_device_con_in EQU 01h ; true if consle input
;
; structure of devid field as returned by IOCTL is:
;
; BIT 7 6 5 4 3 2 1 0
; |---|---|---|---|---|---|---|---|
; | I | E | R | S | I | I | I | I |
; | S | O | A | P | S | S | S | S |
; | D | F | W | E | C | N | C | C |
; | E | | | C | L | U | O | I |
; | V | | | L | K | L | T | N |
; |---|---|---|---|---|---|---|---|
; ISDEV = 1 if this channel is a device
; = 0 if this channel is a disk file
;
; If ISDEV = 1
;
; EOF = 0 if End Of File on input
; RAW = 1 if this device is in Raw mode
; = 0 if this device is cooked
; ISCLK = 1 if this device is the clock device
; ISNUL = 1 if this device is the null device
; ISCOT = 1 if this device is the console output
; ISCIN = 1 if this device is the console input
;
; If ISDEV = 0
; EOF = 0 if channel has been written
; Bits 0-5 are the block device number for
; the channel (0 = A, 1 = B, ...)
;
devid_ISDEV EQU 80h
devid_EOF EQU 40h
devid_RAW EQU 20h
devid_SPECIAL EQU 10H
devid_ISCLK EQU 08h
devid_ISNUL EQU 04h
devid_ISCOT EQU 02h
devid_ISCIN EQU 01h
devid_block_dev EQU 1Fh ; mask for block device number
;
; find first/next buffer
;
find_buf STRUC
find_buf_sattr DB ? ; attribute of search
find_buf_drive DB ? ; drive of search
find_buf_name DB 11 DUP (?) ; formatted name
find_buf_LastEnt DW ? ; LastEnt
find_buf_ThisDPB DD ? ; This DPB
find_buf_DirStart DW ? ; DirStart
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
find_buf_attr DB ? ; attribute found
find_buf_time DW ? ; time
find_buf_date DW ? ; date
find_buf_size_l DW ? ; low(size)
find_buf_size_h DW ? ; high(size)
find_buf_pname DB 13 DUP (?) ; packed name
find_buf ENDS
BREAK <Process data block>
;
; Process data block (otherwise known as program header)
;
FilPerProc EQU 20
Process_data_block STRUC
PDB_Exit_Call DW ? ; INT int_abort system terminate
PDB_block_len DW ? ; size of execution block
DB ?
PDB_CPM_Call DB 5 DUP (?) ; ancient call to system
PDB_Exit DD ? ; pointer to exit routine
PDB_Ctrl_C DD ? ; pointer to ^C routine
PDB_Fatal_abort DD ? ; pointer to fatal error
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
PDB_Parent_PID DW ? ; PID of parent (terminate PID)
PDB_JFN_Table DB FilPerProc DUP (?)
; indices into system table
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
PDB_environ DW ? ; seg addr of environment
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
PDB_User_stack DD ? ; stack of self during system calls
PDB_PAD1 DB 1Eh DUP (?)
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
PDB_Call_system DB 5 DUP (?) ; portable method of system call
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
PDB_PAD2 DB 6h DUP (?) ;
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
Process_data_block ENDS
BREAK <EXEC and EXE file structures>
;
; EXEC arg block - load/go program
;
;
; The following get used as arguments to the EXEC system call. They indicate
; whether or not the program is executed or whether or not a program header
; gets created.
;
exec_func_no_execute EQU 1 ; no execute bit
exec_func_overlay EQU 2 ; overlay bit
Exec0 STRUC
Exec0_environ DW ? ; seg addr of environment
Exec0_com_line DD ? ; pointer to asciz command line
Exec0_5C_FCB DD ? ; default fcb at 5C
Exec0_6C_FCB DD ? ; default fcb at 6C
Exec0 ENDS
Exec1 STRUC
Exec1_environ DW ? ; seg addr of environment
Exec1_com_line DD ? ; pointer to asciz command line
Exec1_5C_FCB DD ? ; default fcb at 5C
Exec1_6C_FCB DD ? ; default fcb at 6C
Exec1_SP DW ? ; stack pointer of program
Exec1_SS DW ? ; stack seg register of program
Exec1_IP DW ? ; entry point IP
Exec1_CS DW ? ; entry point CS
Exec1 ENDS
Exec3 STRUC
Exec3_load_addr DW ? ; seg address of load point
Exec3_reloc_fac DW ? ; relocation factor
Exec3 ENDS
;
; Exit codes in upper byte
;
Exit_terminate EQU 0
Exit_abort EQU 0
Exit_Ctrl_C EQU 1
Exit_Hard_Error EQU 2
Exit_Keep_process EQU 3
;
; EXE file header
;
EXE_file STRUC
exe_signature DW ? ; must contain 4D5A (yay zibo!)
exe_len_mod_512 DW ? ; low 9 bits of length
exe_pages DW ? ; number of 512b pages in file
exe_rle_count DW ? ; count of reloc entries
exe_par_dir DW ? ; number of paragraphs before image
exe_min_BSS DW ? ; minimum number of para of BSS
exe_max_BSS DW ? ; max number of para of BSS
exe_SS DW ? ; stack of image
exe_SP DW ? ; SP of image
exe_chksum DW ? ; checksum of file (ignored)
exe_IP DW ? ; IP of entry
exe_CS DW ? ; CS of entry
exe_rle_table DW ? ; byte offset of reloc table
exe_iov DW ? ; overlay number (0 for root)
exe_sym_tab DD ? ; offset of symbol table in file
EXE_file ENDS
exe_valid_signature EQU 5A4Dh
exe_valid_old_signature EQU 4D5Ah
symbol_entry STRUC
sym_value DD ?
sym_type DW ?
sym_len DB ?
sym_name DB 255 dup (?)
symbol_entry ENDS
BREAK <Internal system file table format>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
;
; system file table
;
sft STRUC
sft_link DD ?
sft_count DW ? ; number of entries
sft_table DW ? ; beginning of array of the following
sft ENDS
;
; system file table entry
;
sf_entry STRUC
sf_ref_count DB ? ; number of processes sharing fcb
sf_mode DB ? ; mode of access
sf_attr DB ? ; attribute of file
sf_fcb DB (SIZE sys_fcb) DUP (?)
; actual FCB
sf_entry ENDS
sf_default_number EQU 5h
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <Memory arena structure>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
;
; arena item
;
arena STRUC
arena_signature DB ? ; 4D for valid item, 5A for last item
arena_owner DW ? ; owner of arena item
arena_size DW ? ; size in paragraphs of item
arena ENDS
;
; Current structure of the data returned by the international call
;
internat_block STRUC
Date_tim_format DW ? ; 0-USA, 1-EUR, 2-JAP
Currency_sym DB ? ; Currency Symbol 5 bytes
DB ?
DB ?
DB ?
DB ?
Thous_sep DB ? ; Thousands separator 2 bytes
DB ?
Decimal_sep DB ? ; Decimal separator 2 bytes
DB ?
Date_sep DB ? ; Date separator 2 bytes
DB ?
Time_sep DB ? ; Decimal separator 2 bytes
DB ?
Bit_feild DB ? ; Bit values
; Bit 0 = 0 if currency symbol first
; = 1 if currency symbol last
; Bit 1 = 0 if No space after currency symbol
; = 1 if space after currency symbol
Currency_cents DB ? ; Number of places after currency dec point
Time_24 DB ? ; 1 if 24 hour time, 0 if 12 hour time
Map_call DW ? ; Address of case mapping call (DWORD)
DW ? ; THIS IS TWO WORDS SO IT CAN BE INITIALIZED
; in pieces.
Data_sep DB ? ; Data list separator character
DB ?
internat_block ENDS
;
; Max size of the block returned by the INTERNATIONAL call
;
internat_block_max EQU 32
;
; CAUTION: The routines in ALLOC.ASM rely on the fact that arena_signature
; and arena_owner_system are all equal to zero and are contained in DI. Change
; them and change ALLOC.ASM.
arena_owner_system EQU 0 ; free block indication
arena_signature_normal EQU 4Dh ; valid signature, not end of arena
arena_signature_end EQU 5Ah ; valid signature, last block in arena
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <Machine instruction definitions>
mi_INT EQU 0CDh
mi_Long_JMP EQU 0EAh
mi_Long_CALL EQU 09Ah
mi_Long_RET EQU 0CBh
BREAK <Standard I/O assignments>
stdin EQU 0
stdout EQU 1
stderr EQU 2
stdaux EQU 3
stdprn EQU 4
BREAK <Xenix subfunction assignments>
open_for_read EQU 0
open_for_write EQU 1
open_for_both EQU 2
BREAK <Xenix error codes>
;
; XENIX calls all return error codes through AX. If an error occurred then
; the carry bit will be set and the error code is in AX. If no error occurred
; then the carry bit is reset and AX contains returned info.
;
no_error_occurred EQU 0 ?
error_invalid_function EQU 1
error_file_not_found EQU 2
error_path_not_found EQU 3
error_too_many_open_files EQU 4
error_access_denied EQU 5
error_invalid_handle EQU 6
error_arena_trashed EQU 7
error_not_enough_memory EQU 8
error_invalid_block EQU 9
error_bad_environment EQU 10
error_bad_format EQU 11
error_invalid_access EQU 12
error_invalid_data EQU 13
;**** unused EQU 14
error_invalid_drive EQU 15
error_current_directory EQU 16
error_not_same_device EQU 17
error_no_more_files EQU 18
country_not_found EQU error_file_not_found
alloc_not_enough_memory EQU error_not_enough_memory
alloc_arena_trashed EQU error_arena_trashed
close_invalid_handle EQU error_invalid_handle
close_invalid_function EQU error_invalid_function
chdir_path_not_found EQU error_path_not_found
chmod_path_not_found EQU error_path_not_found
chmod_access_denied EQU error_access_denied
chmod_invalid_function EQU error_invalid_function
creat_access_denied EQU error_access_denied
creat_path_not_found EQU error_path_not_found
creat_too_many_open_files EQU error_too_many_open_files
curdir_invalid_drive EQU error_invalid_drive
dealloc_invalid_block EQU error_invalid_block
dealloc_arena_trashed EQU error_arena_trashed
dup_invalid_handle EQU error_invalid_handle
dup_too_many_open_files EQU error_too_many_open_files
dup2_invalid_handle EQU error_invalid_handle
exec_invalid_function EQU error_invalid_function
exec_bad_environment EQU error_bad_environment
exec_bad_format EQU error_bad_format
exec_not_enough_memory EQU error_not_enough_memory
exec_file_not_found EQU error_file_not_found
filetimes_invalid_function EQU error_invalid_function
filetimes_invalid_handle EQU error_invalid_handle
findfirst_file_not_found EQU error_file_not_found
findfirst_no_more_files EQU error_no_more_files
findnext_no_more_files EQU error_no_more_files
international_invalid_function EQU error_invalid_function
ioctl_invalid_handle EQU error_invalid_handle
ioctl_invalid_function EQU error_invalid_function
ioctl_invalid_data EQU error_invalid_data
lseek_invalid_handle EQU error_invalid_handle
lseek_invalid_function EQU error_invalid_function
mkdir_path_not_found EQU error_path_not_found
mkdir_access_denied EQU error_access_denied
open_invalid_access EQU error_invalid_access
open_file_not_found EQU error_file_not_found
open_access_denied EQU error_access_denied
open_too_many_open_files EQU error_too_many_open_files
read_invalid_handle EQU error_invalid_handle
read_access_denied EQU error_access_denied
rename_file_not_found EQU error_file_not_found
rename_not_same_device EQU error_not_same_device
rename_access_denied EQU error_access_denied
rmdir_path_not_found EQU error_path_not_found
rmdir_access_denied EQU error_access_denied
rmdir_current_directory EQU error_current_directory
setblock_invalid_block EQU error_invalid_block
setblock_arena_trashed EQU error_arena_trashed
setblock_not_enough_memory EQU error_not_enough_memory
setblock_invalid_function EQU error_invalid_function
unlink_file_not_found EQU error_file_not_found
unlink_access_denied EQU error_access_denied
write_invalid_handle EQU error_invalid_handle
write_access_denied EQU error_access_denied
BREAK <system call definitions>
Abort EQU 0 ; 0 0
Std_Con_Input EQU 1 ; 1 1
Std_Con_Output EQU 2 ; 2 2
Std_Aux_Input EQU 3 ; 3 3
Std_Aux_Output EQU 4 ; 4 4
Std_Printer_Output EQU 5 ; 5 5
Raw_Con_IO EQU 6 ; 6 6
Raw_Con_Input EQU 7 ; 7 7
Std_Con_Input_No_Echo EQU 8 ; 8 8
Std_Con_String_Output EQU 9 ; 9 9
Std_Con_String_Input EQU 10 ; 10 A
Std_Con_Input_Status EQU 11 ; 11 B
Std_Con_Input_Flush EQU 12 ; 12 C
Disk_Reset EQU 13 ; 13 D
Set_Default_Drive EQU 14 ; 14 E
FCB_Open EQU 15 ; 15 F
FCB_Close EQU 16 ; 16 10
Dir_Search_First EQU 17 ; 17 11
Dir_Search_Next EQU 18 ; 18 12
FCB_Delete EQU 19 ; 19 13
FCB_Seq_Read EQU 20 ; 20 14
FCB_Seq_Write EQU 21 ; 21 15
FCB_Create EQU 22 ; 22 16
FCB_Rename EQU 23 ; 23 17
Get_Default_Drive EQU 25 ; 25 19
Set_DMA EQU 26 ; 26 1A
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
Get_Default_DPB EQU 31 ; 31 1F
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
FCB_Random_Read EQU 33 ; 33 21
FCB_Random_Write EQU 34 ; 34 22
Get_FCB_File_Length EQU 35 ; 35 23
Get_FCB_Position EQU 36 ; 36 24
Set_Interrupt_Vector EQU 37 ; 37 25
Create_Process_Data_Block EQU 38 ; 38 26
FCB_Random_Read_Block EQU 39 ; 39 27
FCB_Random_Write_Block EQU 40 ; 40 28
Parse_File_Descriptor EQU 41 ; 41 29
Get_Date EQU 42 ; 42 2A
Set_Date EQU 43 ; 43 2B
Get_Time EQU 44 ; 44 2C
Set_Time EQU 45 ; 45 2D
Set_Verify_On_Write EQU 46 ; 46 2E
; Extended functionality group
Get_DMA EQU 47 ; 47 2F
Get_Version EQU 48 ; 48 30
Keep_Process EQU 49 ; 49 31
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
Get_DPB EQU 50 ; 50 32
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
Set_CTRL_C_Trapping EQU 51 ; 51 33
Get_InDOS_Flag EQU 52 ; 52 34
Get_Interrupt_Vector EQU 53 ; 53 35
Get_Drive_Freespace EQU 54 ; 54 36
Char_Oper EQU 55 ; 55 37
International EQU 56 ; 56 38
; Directory Group
MKDir EQU 57 ; 57 39
RMDir EQU 58 ; 58 3A
CHDir EQU 59 ; 59 3B
; File Group
Creat EQU 60 ; 60 3C
Open EQU 61 ; 61 3D
Close EQU 62 ; 62 3E
Read EQU 63 ; 63 3F
Write EQU 64 ; 64 40
Unlink EQU 65 ; 65 41
LSeek EQU 66 ; 66 42
CHMod EQU 67 ; 67 43
IOCtl EQU 68 ; 68 44
XDup EQU 69 ; 69 45
XDup2 EQU 70 ; 70 46
Current_Dir EQU 71 ; 71 47
; Memory Group
Alloc EQU 72 ; 72 48
Dealloc EQU 73 ; 73 49
Setblock EQU 74 ; 74 4A
; Process Group
Exec EQU 75 ; 75 4B
Exit EQU 76 ; 76 4C
Wait EQU 77 ; 77 4D
Find_First EQU 78 ; 78 4E
; Special Group
Find_Next EQU 79 ; 79 4F
; SPECIAL SYSTEM GROUP
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
Set_Current_PDB EQU 80 ; 80 50
Get_Current_PDB EQU 81 ; 81 51
Get_In_Vars EQU 82 ; 82 52
SetDPB EQU 83 ; 83 53
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
Get_Verify_On_Write EQU 84 ; 84 54
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
Dup_PDB EQU 85 ; 85 55
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
Rename EQU 86 ; 86 56
File_Times EQU 87 ; 87 57
AllocOper EQU 88 ; 88 58
; Network extention system calls
GetExtendedError EQU 89 ; 89 59
CreateTempFile EQU 90 ; 90 5A
CreateNewFile EQU 91 ; 91 5B
LockOper EQU 92 ; 92 5C Lock and Unlock
ServerCall EQU 93 ; 93 5D CommitAll, ServerDOSCall,
; CloseByName, CloseUser,
; CloseUserProcess,
; GetOpenFileList
UserIDOper EQU 94 ; 94 5E Get and Set
AssignOper EQU 95 ; 95 5F On, Off, Get, Set, Cancel
Set_Oem_Handler EQU 248 ; 248 F8
OEM_C1 EQU 249 ; 249 F9
OEM_C2 EQU 250 ; 250 FA
OEM_C3 EQU 251 ; 251 FB
OEM_C4 EQU 252 ; 252 FC
OEM_C5 EQU 253 ; 253 FD
OEM_C6 EQU 254 ; 254 FE
OEM_C7 EQU 255 ; 255 FF
SUBTTL
+1846
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+531
View File
@@ -0,0 +1,531 @@
FALSE EQU 0
TRUE EQU NOT FALSE
KANJI EQU FALSE
roprot equ FALSE ;set to TRUE if protection to r/o files
; desired.
FCB EQU 5CH
Comand_Line_Length equ 128
quote_char equ 16h ;quote character = ^V
PAGE
.xlist
INCLUDE DOSSYM.ASM
.list
SUBTTL Contants and Data areas
PAGE
PROMPT EQU "*"
STKSIZ EQU 80H
CODE SEGMENT PUBLIC
CODE ENDS
CONST SEGMENT PUBLIC WORD
EXTRN TXT1:BYTE,TXT2:BYTE,FUDGE:BYTE,HARDCH:DWORD,USERDIR:BYTE
CONST ENDS
DATA SEGMENT PUBLIC WORD
EXTRN OLDLEN:WORD,OLDDAT:BYTE,SRCHFLG:BYTE,COMLINE:WORD
EXTRN PARAM1:WORD,PARAM2:WORD,NEWLEN:WORD,SRCHMOD:BYTE
EXTRN CURRENT:WORD,POINTER:WORD,START:BYTE,ENDTXT:WORD
EXTRN USER_DRIVE:BYTE,LSTNUM:WORD,NUMPOS:WORD,LSTFND:WORD
EXTRN SRCHCNT:WORD
DATA ENDS
DG GROUP CODE,CONST,DATA
CODE SEGMENT PUBLIC
ASSUME CS:DG,DS:DG,SS:DG,ES:DG
PUBLIC REST_DIR,KILL_BL,INT_24,SCANLN,FINDLIN,SHOWNUM
PUBLIC FNDFIRST,FNDNEXT,CRLF,LF,OUT,UNQUOTE
if kanji
PUBLIC TESTKANJ
endif
EXTRN CHKRANGE:NEAR
EDLPROC:
RET1: RET
FNDFIRST:
MOV DI,1+OFFSET DG:TXT1
mov byte ptr[olddat],1 ;replace with old value if none new
CALL GETTEXT
OR AL,AL ;Reset zero flag in case CX is zero
JCXZ RET1
cmp al,1ah ;terminated with a ^Z ?
jne sj8
mov byte ptr[olddat],0 ;do not replace with old value
sj8:
MOV [OLDLEN],CX
XOR CX,CX
CMP AL,0DH
JZ SETBUF
CMP BYTE PTR [SRCHFLG],0
JZ NXTBUF
SETBUF:
DEC SI
NXTBUF:
MOV [COMLINE],SI
MOV DI,1+OFFSET DG:TXT2
CALL GETTEXT
CMP BYTE PTR [SRCHFLG],0
JNZ NOTREPL
CMP AL,0DH
JNZ HAVCHR
DEC SI
HAVCHR:
MOV [COMLINE],SI
NOTREPL:
MOV [NEWLEN],CX
MOV BX,[PARAM1]
OR BX,BX
JNZ CALLER
cmp byte ptr[srchmod],0
jne sj9
mov bx,1 ;start from line number 1
jmp short sj9a
sj9:
MOV BX,[CURRENT]
INC BX ;Default search and replace to current+1
sj9a:
CALL CHKRANGE
CALLER:
CALL FINDLIN
MOV [LSTFND],DI
MOV [NUMPOS],DI
MOV [LSTNUM],DX
MOV BX,[PARAM2]
CMP BX,1
SBB BX,-1 ;Decrement everything except zero
CALL FINDLIN
MOV CX,DI
SUB CX,[LSTFND]
OR AL,-1
JCXZ aret
CMP CX,[OLDLEN]
jae sj10
aret: ret
sj10:
MOV [SRCHCNT],CX
FNDNEXT:
; Inputs:
; [TXT1+1] has string to search for
; [OLDLEN] has length of the string
; [LSTFND] has starting position of search in text buffer
; [LSTNUM] has line number which has [LSTFND]
; [SRCHCNT] has length to be searched
; [NUMPOS] has beginning of line which has [LSTFND]
; Outputs:
; Zero flag set if match found
; [LSTFND],[LSTNUM],[SRCHCNT] updated for continuing the search
; [NUMPOS] has beginning of line in which match was made
MOV AL,[TXT1+1]
MOV CX,[SRCHCNT]
MOV DI,[LSTFND]
SCAN:
OR DI,DI ;Clear zero flag in case CX=0
REPNE SCASB
JNZ RET11
MOV DX,CX
MOV BX,DI ;Save search position
MOV CX,[OLDLEN]
DEC CX
MOV SI,2 + OFFSET DG:TXT1
CMP AL,AL ;Set zero flag in case CX=0
if kanji
dec si ;Want to look at the first character again
dec di
kanjchar:
lodsb
call testkanj
jz nxt_kj_char
xchg ah,al
lodsb
mov bx,[di]
add di,2
cmp ax,bx
jnz not_kj_match
dec cx
loop kanjchar
nxt_kj_char:
cmp al,byte ptr[di]
jnz not_kj_match
inc di
loop kanjchar
not_kj_match:
else
REPE CMPSB
endif
MOV CX,DX
MOV DI,BX
JNZ SCAN
MOV [SRCHCNT],CX
MOV CX,DI
MOV [LSTFND],DI
MOV DI,[NUMPOS]
SUB CX,DI
MOV AL,10
MOV DX,[LSTNUM]
;Determine line number of match
GETLIN:
INC DX
MOV BX,DI
REPNE SCASB
JZ GETLIN
DEC DX
MOV [LSTNUM],DX
MOV [NUMPOS],BX
XOR AL,AL
RET11: RET
GETTEXT:
; Inputs:
; SI points into command line buffer
; DI points to result buffer
; Function:
; Moves [SI] to [DI] until ctrl-Z (1AH) or
; RETURN (0DH) is found. Termination char not moved.
; Outputs:
; AL = Termination character
; CX = No of characters moved.
; SI points one past termination character
; DI points to next free location
XOR CX,CX
GETIT:
LODSB
;-----------------------------------------------------------------------
cmp al,quote_char ;a quote character?
jne sj101 ;no, skip....
lodsb ;yes, get quoted character
call make_cntrl
jmp short sj102
;-----------------------------------------------------------------------
sj101:
CMP AL,1AH
JZ DEFCHK
sj102:
CMP AL,0DH
JZ DEFCHK
STOSB
INC CX
JMP SHORT GETIT
DEFCHK:
OR CX,CX
JZ OLDTXT
PUSH DI
SUB DI,CX
MOV BYTE PTR [DI-1],cl
POP DI
RET
OLDTXT:
cmp byte ptr[olddat],1 ;replace with old text?
je sj11 ;yes...
mov byte ptr[di-1],cl ;zero text buffer char count
ret
sj11:
MOV CL,BYTE PTR [DI-1]
ADD DI,CX
RET
FINDLIN:
; Inputs
; BX = Line number to be located in buffer (0 means last line)
; Outputs:
; DX = Actual line found
; DI = Pointer to start of line DX
; Zero set if BX = DX
; AL,CX destroyed. No other registers affected.
MOV DX,[CURRENT]
MOV DI,[POINTER]
CMP BX,DX
JZ RET4
JA FINDIT
OR BX,BX
JZ FINDIT
MOV DX,1
MOV DI,OFFSET DG:START
CMP BX,DX
JZ RET4
FINDIT:
MOV CX,[ENDTXT]
SUB CX,DI
SCANLN:
MOV AL,10
OR AL,AL ;Clear zero flag
FINLIN:
JCXZ RET4
REPNE SCASB
INC DX
CMP BX,DX
JNZ FINLIN
RET4: RET
SHOWNUM:
; Inputs:
; BX = Line number to be displayed
; Function:
; Displays line number on terminal in 8-character
; format, suppressing leading zeros.
; AX, CX, DX destroyed. No other registers affected.
PUSH BX
MOV AL," "
CALL OUT
CALL CONV10
MOV AL,":"
CALL OUT
MOV AL,"*"
POP BX
CMP BX,[CURRENT]
JZ STARLIN
MOV AL," "
STARLIN:
JMP OUT
CONV10:
;Inputs:
; BX = Binary number to be displayed
; Function:
; Ouputs binary number. Five digits with leading
; zero suppression. Zero prints 5 blanks.
XOR AX,AX
MOV DL,AL
MOV CX,16
CONV:
SHL BX,1
ADC AL,AL
DAA
XCHG AL,AH
ADC AL,AL
DAA
XCHG AL,AH
ADC DL,DL
LOOP CONV
MOV BL,"0"-" "
XCHG AX,DX
CALL LDIG
MOV AL,DH
CALL DIGITS
MOV AL,DL
DIGITS:
MOV DH,AL
SHR AL,1
SHR AL,1
SHR AL,1
SHR AL,1
CALL LDIG
MOV AL,DH
LDIG:
AND AL,0FH
JZ ZERDIG
MOV BL,0
ZERDIG:
ADD AL,"0"
SUB AL,BL
JMP OUT
RET5: RET
CRLF:
MOV AL,13
CALL OUT
LF:
MOV AL,10
OUT:
PUSH DX
XCHG AX,DX
MOV AH,STD_CON_OUTPUT
INT 21H
XCHG AX,DX
POP DX
RET
;-----------------------------------------------------------------------;
; Will scan buffer given pointed to by SI and get rid of quote
;characters, compressing the line and adjusting the length at the
;begining of the line.
; Preserves al registers except flags and AX .
unquote:
push cx
push di
push si
mov di,si
mov cl,[si-1] ;length of buffer
xor ch,ch
mov al,quote_char
cld
unq_loop:
jcxz unq_done ;no more chars in the buffer, exit
repnz scasb ;search for quote character
jnz unq_done ;none found, exit
push cx ;save chars left in buffer
push di ;save pointer to quoted character
push ax ;save quote character
mov al,byte ptr[di] ;get quoted character
call make_cntrl
mov byte ptr[di],al
pop ax ;restore quote character
mov si,di
dec di ;points to the quote character
inc cx ;include the carriage return also
rep movsb ;compact line
pop di ;now points to after quoted character
pop cx
jcxz sj13 ;if quote char was last of line do not adjust
dec cx ;one less char left in the buffer
sj13: pop si
dec byte ptr[si-1] ;one less character in total buffer count also
push si
jmp short unq_loop
unq_done:
pop si
pop di
pop cx
ret
;-----------------------------------------------------------------------;
; Convert the character in AL to the corresponding control
; character. AL has to be between @ and _ to be converted. That is,
; it has to be a capital letter. All other letters are left unchanged.
make_cntrl:
push ax
and ax,11100000b
cmp ax,01000000b
pop ax
jne sj14
and ax,00011111b
sj14:
ret
;---- Kill spaces in buffer --------------------------------------------;
kill_bl:
lodsb ;get rid of blanks
cmp al,' '
je kill_bl
ret
;----- Restore INT 24 vector and old current directory -----------------;
rest_dir:
cmp [fudge],0
je no_fudge
mov ax,(set_interrupt_vector shl 8) or 24h
lds dx,[hardch]
int 21h
push cs
pop ds
mov dx,offset dg:userdir ;restore directory
mov ah,chdir
int 21h
mov dl,[user_drive] ;restore old current drive
mov ah,set_default_drive
int 21h
no_fudge:
ret
;----- INT 24 Processing -----------------------------------------------;
int_24_retaddr dw offset dg:int_24_back
int_24 proc far
assume ds:nothing,es:nothing,ss:nothing
pushf
push cs
push [int_24_retaddr]
push word ptr [hardch+2]
push word ptr [hardch]
ret
int_24 endp
int_24_back:
cmp al,2 ;abort?
jnz ireti
push cs
pop ds
assume ds:dg
call rest_dir
int 20h
ireti:
iret
IF KANJI
TESTKANJ:
CMP AL,81H
JB NOTLEAD
CMP AL,9FH
JBE ISLEAD
CMP AL,0E0H
JB NOTLEAD
CMP AL,0FCH
JBE ISLEAD
NOTLEAD:
PUSH AX
XOR AX,AX ;Set zero
POP AX
RET
ISLEAD:
PUSH AX
XOR AX,AX ;Set zero
INC AX ;Reset zero
POP AX
RET
ENDIF
;-----------------------------------------------------------------------;
CODE ENDS
END EDLPROC

+514
View File
@@ -0,0 +1,514 @@
title LOCATE (EXE2BIN)
;Loader for EXE files under 86-DOS
;The following switch allows use with the "old linker", which put a version
;number where the new linker puts the number of bytes used in the last page.
;If enabled, this will cause a test for 0004 at this location (the old linker
;version number), and if equal, change it to 200H so all of the last page
;will be used.
;VER. 1.5
; 05/21/82 Added rev number
;
;VER. 1.6
; 07/01/82 A little less choosy about size matches
;
;VER. 2.0 Rev. 1 M.A.Ulloa
; 10/08/82 Modified to use new 2.0 system calls for file i/o
;
; Rev. 2 M.A.Ulloa
; 10/27/82 Added the DOS version check
FALSE EQU 0
TRUE EQU NOT FALSE
OLDLINK EQU 0 ;1 to enable, 0 to disable
.xlist
INCLUDE DOSSYM.ASM
.list
subttl Main Code Area
page
code segment byte
code ends
DATA SEGMENT PUBLIC BYTE
EXTRN bad_vers_err:BYTE,NOTFND:BYTE,NOROOM:BYTE,DIRFULL:BYTE
EXTRN CANTFIX:BYTE,RDBAD:BYTE,FULL:BYTE,PROMPT:BYTE,CRLF:BYTE
make db "MAUlloa/Microsoft/V20"
rev db "2"
file1_ext db ".EXE",00h
file2_ext db ".BIN",00h
per1 db 0
per2 db 0
file1 db 64 dup(?)
handle1 dw 1 dup(?)
file2 db 64 dup(?)
handle2 dw 1 dup(?)
INBUF DB 5,0
DB 5 DUP(?)
;The following locations must be defined for storing the header:
RUNVAR LABEL BYTE ;Start of RUN variables
RELPT DW ?
LASTP LABEL WORD
RELSEG DW ?
SIZ LABEL WORD ;Share these locations
PAGES DW ?
RELCNT DW ?
HEADSIZ DW ?
DW ?
LOADLOW DW ?
INITSS DW ?
INITSP DW ?
DW ?
INITIP DW ?
INITCS DW ?
RELTAB DW ?
RUNVARSIZ EQU $-RUNVAR
DATA ENDS
STACK SEGMENT WORD STACK
DB 80H DUP (?)
STACK ENDS
ZLOAD SEGMENT
ZLOAD ENDS
LOAD EQU ZLOAD
CODE SEGMENT BYTE
ASSUME CS:CODE
LOCATE PROC FAR
JMP SHORT LOCSTRT
HEADER DB "Vers 2.00"
LOCSTRT:
MOV SI,81H
PUSH DS
XOR AX,AX
PUSH AX ;Push return address to DS:0
;Code to print header
; PUSH DS
; MOV DX,DATA
; MOV DS,DX
; MOV DX,OFFSET HEADER
; MOV AH,STD_CON_STRING_OUTPUT
; INT 21H
; POP DS
;----- Check Version Number --------------------------------------------;
mov ah,Get_Version
int 21h
cmp al,2
jge vers_ok ; version >= 2, enter locate
push ds
mov dx,data
mov ds,dx
mov dx,offset bad_vers_err
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
pop ds
ret ;long return to DOS
;-----------------------------------------------------------------------;
vers_ok:
MOV BX,WORD PTR DS:2 ;Get size of memory
MOV DX,DATA
MOV ES,DX
assume es:data
;-----------------------------------------------------------------------;
;----- Get the first file name
call kill_bl
jnc sj01
mov ds,dx
jmp bad_file
sj01:
mov di,offset file1
sj0:
lodsb ;get character of file name
cmp al,' '
je sj2
cmp al,0dh
je sj2
cmp al,'.' ;an extension separator found?
jne sj1
mov es:[per1],-1
sj1:
stosb
jmp short sj0
sj2:
dec si
mov byte ptr es:[di],00h ;nul terminate the filename
call kill_bl
jc no_second
;----- Get the second file name
mov di,offset file2
sj3:
lodsb ;get character of file name
cmp al,' '
je sj5
cmp al,0dh
je sj5
cmp al,'.' ;an extension separator found?
jne sj4
mov es:[per2],-1
sj4:
stosb
jmp short sj3
sj5:
mov byte ptr es:[di],00h ;nul terminate
jmp short check_ext
;----- Copy file1 to file2
no_second:
mov ds,dx
assume ds:data
mov si,offset file1
mov di,offset file2
sj6:
lodsb
cmp al,'.'
je sj7
cmp al,00h
je sj7
stosb
jmp short sj6
sj7:
mov byte ptr [di],00h
;----- Check that files have an extension, otherwise set default
check_ext:
mov ds,dx
assume ds:data
cmp [per1],-1
je file1_ok
mov si,offset file1
sj8:
lodsb
cmp al,00h
jne sj8
mov di,si
mov si,offset file1_ext
call put_ext
file1_ok:
cmp [per2],-1
je file2_ok
mov si,offset file2
sj9:
lodsb
cmp al,00h
jne sj9
mov di,si
mov si,offset file2_ext
call put_ext
jmp short file2_ok
;----- Fill in the default extent
put_ext proc near
dec di
mov cx,5 ;move extent: period,extent,null
rep movsb
ret
put_ext endp
;----- Find the first non-blank
kill_bl proc near
cld
sj10:
lodsb
cmp al,' '
je sj10
dec si
cmp al,0dh
clc
jne sj11
stc
sj11:
ret
kill_bl endp
file2_ok:
;-----------------------------------------------------------------------;
mov dx,offset file1
mov ah,open
mov al,0 ;ror reading only
INT 21H ;Open input file
jc bad_file
mov [handle1],ax
jmp exeload
bad_file:
MOV DX,OFFSET NOTFND
xERROR:
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
RET ;FAR return to MS-DOS
TOOBIG:
MOV DX,OFFSET NOROOM
JMP xERROR
BADEXE:
MOV DX,OFFSET CANTFIX
ERRORJ: JMP xERROR
EXELOAD:
MOV DX,OFFSET RUNVAR ;Read header in here
MOV CX,RUNVARSIZ ;Amount of header info we need
push bx
mov bx,[handle1]
MOV AH,read
INT 21H ;Read in header
pop bx
CMP [RELPT],5A4DH ;Check signature word
JNZ BADEXE
MOV AX,[HEADSIZ] ;size of header in paragraphs
ADD AX,31 ;Round up first
CMP AX,1000H ;Must not be >=64K
JAE TOOBIG
AND AX,NOT 31
MOV CL,4
SHL AX,CL ;Header size in bytes
push dx
push cx
push ax
push bx
mov dx,ax
xor cx,cx
mov al,0
mov bx,[handle1]
mov ah,lseek
int 21h
pop bx
pop ax
pop cx
pop dx
XCHG AL,AH
SHR AX,1 ;Convert to pages
MOV DX,[PAGES] ;Total size of file in 512-byte pages
SUB DX,AX ;Size of program in pages
CMP DX,80H ;Fit in 64K?
JAE TOOBIG
XCHG DH,DL
SHL DX,1 ;Convert pages to bytes
MOV AX,[LASTP] ;Get count of bytes in last page
OR AX,AX ;If zero, use all of last page
JZ WHOLEP
IF OLDLINK
CMP AX,4 ;Produced by old linker?
JZ WHOLEP ;If so, use all of last page too
ENDIF
SUB DX,200H ;Subtract last page
ADD DX,AX ;Add in byte count for last page
WHOLEP:
MOV [SIZ],DX
ADD DX,15
SHR DX,CL ;Convert bytes to paragraphs
MOV BP,LOAD
ADD DX,BP ;Size + start = minimum memory (paragr.)
CMP DX,BX ;Enough memory?
JA TOOBIG
MOV DX,OFFSET CANTFIX
MOV AX,[INITSS]
OR AX,[INITSP]
OR AX,[INITCS]
ERRORNZ:
jz xj
JMP ERRORJ ;Must not have SS, SP, or CS to init.
xj: MOV AX,[INITIP]
OR AX,AX ;If IP=0, do binary fix
JZ BINFIX
CMP AX,100H ;COM file must be set up for CS:100
JNZ ERRORNZ
push dx
push cx
push ax
push bx
mov dx,100h ;chop off first 100h
xor cx,cx
mov al,1 ;seek from current position
mov bx,[handle1]
mov ah,lseek
int 21h
pop bx
pop ax
pop cx
pop dx
SUB [SIZ],AX ;And count decreased size
CMP [RELCNT],0 ;Must have no fixups
JNZ ERRORNZ
BINFIX:
XOR BX,BX ;Initialize fixup segment
;See if segment fixups needed
CMP [RELCNT],0
JZ LOADEXE
GETSEG:
MOV DX,OFFSET PROMPT
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
MOV AH,STD_CON_STRING_INPUT
MOV DX,OFFSET INBUF
INT 21H ;Get user response
MOV DX,OFFSET CRLF
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
MOV SI,OFFSET INBUF+2
MOV BYTE PTR [SI-1],0 ;Any digits?
JZ GETSEG
DIGLP:
LODSB
SUB AL,"0"
JC DIGERR
CMP AL,10
JB HAVDIG
AND AL,5FH ;Convert to upper case
SUB AL,7
CMP AL,10
JB DIGERR
CMP AL,10H
JAE DIGERR
HAVDIG:
SHL BX,1
SHL BX,1
SHL BX,1
SHL BX,1
OR BL,AL
JMP DIGLP
DIGERR:
CMP BYTE PTR [SI-1],0DH ;Is last char. a CR?
JNZ GETSEG
LOADEXE:
XCHG BX,BP ;BX has LOAD, BP has fixup
MOV CX,[SIZ]
MOV AH,read
push di
mov di,[handle1]
PUSH DS
MOV DS,BX
XOR DX,DX
push bx
mov bx,di
INT 21H ;Read in up to 64K
pop bx
POP DS
pop di
Jnc HAVEXE ;Did we get it all?
MOV DX,OFFSET RDBAD
jmp xERROR ;Non fatal, print warning
HAVEXE:
CMP [RELCNT],0 ;Any fixups to do?
JZ STORE
MOV AX,[RELTAB] ;Get position of table
push dx
push cx
push ax
push bx
mov dx,ax
xor cx,cx
mov al,0
mov bx,[handle1]
mov ah,lseek
int 21h
pop bx
pop ax
pop cx
pop dx
MOV DX,OFFSET RELPT ;4-byte buffer for relocation address
RELOC:
MOV DX,OFFSET RELPT ;4-byte buffer for relocation address
MOV CX,4
MOV AH,read
push bx
mov bx,[handle1]
INT 21H ;Read in one relocation pointer
pop bx
Jnc RDCMP
JMP BADEXE
RDCMP:
MOV DI,[RELPT] ;Get offset of relocation pointer
MOV AX,[RELSEG] ;Get segment
ADD AX,BX ;Bias segment with actual load segment
MOV ES,AX
ADD ES:[DI],BP ;Relocate
DEC [RELCNT] ;Count off
JNZ RELOC
STORE:
MOV AH,CREAT
MOV DX,OFFSET file2
xor cx,cx
INT 21H
Jc MKERR
mov [handle2],ax
MOV CX,[SIZ]
MOV AH,write
push di
mov di,[handle2]
PUSH DS
MOV DS,BX
XOR DX,DX ;Address 0 in segment
push bx
mov bx,di
INT 21H
pop bx
POP DS
pop di
Jc WRTERR ;Must be zero if more to come
MOV AH,CLOSE
push bx
mov bx,[handle2]
INT 21H
pop bx
RET
WRTERR:
MOV DX,OFFSET FULL
JMP xERROR
MKERR:
MOV DX,OFFSET DIRFULL
JMP xERROR
LOCATE ENDP
CODE ENDS
END LOCATE
+1035
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+362
View File
@@ -0,0 +1,362 @@
;
; FAT operations for MSDOS
;
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
TITLE FAT - FAT maintenance routines
NAME FAT
i_need CURBUF,DWORD
i_need CLUSSPLIT,BYTE
i_need CLUSSAVE,WORD
i_need CLUSSEC,WORD
i_need THISDRV,BYTE
i_need DEVCALL,BYTE
i_need CALLMED,BYTE
i_need CALLRBYT,BYTE
i_need BUFFHEAD,DWORD
i_need CALLXAD,DWORD
i_need CALLBPB,DWORD
SUBTTL UNPACK -- UNPACK FAT ENTRIES
PAGE
ASSUME SS:DOSGROUP
procedure UNPACK,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; BX = Cluster number
; ES:BP = Base of drive parameters
; Outputs:
; DI = Contents of FAT for given cluster
; Zero set means DI=0 (free cluster)
; SI Destroyed, No other registers affected. Fatal error if cluster too big.
CMP BX,ES:[BP.dpb_max_cluster]
JA HURTFAT
CALL MAPCLUSTER
ASSUME DS:NOTHING
MOV DI,[DI]
JNC HAVCLUS
PUSH CX
MOV CL,4
SHR DI,CL
POP CX
STC
HAVCLUS:
AND DI,0FFFH
PUSH SS
POP DS
return
HURTFAT:
PUSH AX
MOV AH,80H ; Signal Bad FAT to INT int_fatal_abort handler
MOV DI,0FFFH ; In case INT int_fatal_abort returns (it shouldn't)
invoke FATAL
POP AX ; Try to ignore bad FAT
return
UNPACK ENDP
SUBTTL PACK -- PACK FAT ENTRIES
PAGE
procedure PACK,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; BX = Cluster number
; DX = Data
; ES:BP = Pointer to drive DPB
; Outputs:
; The data is stored in the FAT at the given cluster.
; SI,DX,DI all destroyed
; No other registers affected
CALL MAPCLUSTER
ASSUME DS:NOTHING
MOV SI,[DI]
JNC ALIGNED
PUSH CX
MOV CL,4
SHL DX,CL
POP CX
AND SI,0FH
JMP SHORT PACKIN
ALIGNED:
AND SI,0F000H
PACKIN:
OR SI,DX
MOV [DI],SI
LDS SI,[CURBUF]
MOV [SI.BUFDIRTY],1
CMP BYTE PTR [CLUSSPLIT],0
PUSH SS
POP DS
ASSUME DS:DOSGROUP
retz
PUSH AX
PUSH BX
PUSH CX
MOV AX,[CLUSSAVE]
MOV DS,WORD PTR [CURBUF+2]
ASSUME DS:NOTHING
ADD SI,BUFINSIZ
MOV [SI],AH
PUSH SS
POP DS
ASSUME DS:DOSGROUP
PUSH AX
MOV DX,[CLUSSEC]
MOV SI,1
XOR AL,AL
invoke GETBUFFRB
LDS DI,[CURBUF]
ASSUME DS:NOTHING
MOV [DI.BUFDIRTY],1
ADD DI,BUFINSIZ
DEC DI
ADD DI,ES:[BP.dpb_sector_size]
POP AX
MOV [DI],AL
PUSH SS
POP DS
POP CX
POP BX
POP AX
return
PACK ENDP
SUBTTL MAPCLUSTER - BUFFER A FAT SECTOR
PAGE
procedure MAPCLUSTER,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; ES:BP Points to DPB
; BX Is cluster number
; Function:
; Get a pointer to the cluster
; Outputs:
; DS:DI Points to contents of FAT for given cluster
; DS:SI Points to start of buffer
; Carry set if cluster data is in high 12 bits of word
; No other registers effected
MOV BYTE PTR [CLUSSPLIT],0
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV AX,BX
SHR AX,1
ADD AX,BX
XOR DX,DX
MOV CX,ES:[BP.dpb_sector_size]
DIV CX ; AX is FAT sector # DX is sector index
ADD AX,ES:[BP.dpb_first_FAT]
DEC CX
PUSH AX
PUSH DX
PUSH CX
MOV DX,AX
XOR AL,AL
MOV SI,1
invoke GETBUFFRB
LDS SI,[CURBUF]
ASSUME DS:NOTHING
LEA DI,[SI.BufInSiz]
POP CX
POP AX
POP DX
ADD DI,AX
CMP AX,CX
JNZ MAPRET
MOV AL,[DI]
PUSH SS
POP DS
ASSUME DS:DOSGROUP
INC BYTE PTR [CLUSSPLIT]
MOV BYTE PTR [CLUSSAVE],AL
MOV [CLUSSEC],DX
INC DX
XOR AL,AL
MOV SI,1
invoke GETBUFFRB
LDS SI,[CURBUF]
ASSUME DS:NOTHING
LEA DI,[SI.BufInSiz]
MOV AL,[DI]
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV BYTE PTR [CLUSSAVE+1],AL
MOV DI,OFFSET DOSGROUP:CLUSSAVE
MAPRET:
POP DX
POP CX
POP BX
MOV AX,BX
SHR AX,1
POP AX
return
MAPCLUSTER ENDP
SUBTTL FATREAD -- CHECK DRIVE GET FAT
PAGE
ASSUME DS:DOSGROUP,ES:NOTHING
procedure FAT_operation,NEAR
FATERR:
AND DI,STECODE ; Put error code in DI
MOV AH,2 ; While trying to read FAT
MOV AL,BYTE PTR [THISDRV] ; Tell which drive
invoke FATAL1
entry FATREAD
ASSUME DS:DOSGROUP,ES:NOTHING
; Function:
; If disk may have been changed, FAT is read in and buffers are
; flagged invalid. If not, no action is taken.
; Outputs:
; ES:BP = Base of drive parameters
; All other registers destroyed
MOV AL,BYTE PTR [THISDRV]
invoke GETBP
MOV AL,DMEDHL
MOV AH,ES:[BP.dpb_UNIT]
MOV WORD PTR [DEVCALL],AX
MOV BYTE PTR [DEVCALL.REQFUNC],DEVMDCH
MOV [DEVCALL.REQSTAT],0
MOV AL,ES:[BP.dpb_media]
MOV BYTE PTR [CALLMED],AL
PUSH ES
PUSH DS
MOV BX,OFFSET DOSGROUP:DEVCALL
LDS SI,ES:[BP.dpb_driver_addr] ; DS:SI Points to device header
ASSUME DS:NOTHING
POP ES ; ES:BX Points to call header
invoke DEVIOCALL2
PUSH SS
POP DS
ASSUME DS:DOSGROUP
POP ES ; Restore ES:BP
MOV DI,[DEVCALL.REQSTAT]
TEST DI,STERR
JNZ FATERR
XOR AH,AH
XCHG AH,ES:[BP.dpb_first_access] ; Reset dpb_first_access
MOV AL,BYTE PTR [THISDRV] ; Use physical unit number
OR AH,BYTE PTR [CALLRBYT]
JS NEWDSK ; new disk or first access?
JZ CHKBUFFDIRT
return ; If Media not changed
CHKBUFFDIRT:
INC AH ; Here if ?Media..Check buffers
LDS DI,[BUFFHEAD]
ASSUME DS:NOTHING
NBUFFER: ; Look for dirty buffers
CMP AX,WORD PTR [DI.BUFDRV]
retz ; There is a dirty buffer, assume Media OK
LDS DI,[DI.NEXTBUF]
CMP DI,-1
JNZ NBUFFER
; If no dirty buffers, assume Media changed
NEWDSK:
invoke SETVISIT
NXBUFFER:
MOV [DI.VISIT],1
CMP AL,[DI.BUFDRV] ; For this drive?
JNZ SKPBUFF
MOV WORD PTR [DI.BUFDRV],00FFH ; Free up buffer
invoke SCANPLACE
SKPBUFF:
invoke SKIPVISIT
JNZ NXBUFFER
LDS DI,ES:[BP.dpb_driver_addr]
TEST [DI.SDEVATT],ISFATBYDEV
JNZ GETFREEBUF
context DS
MOV BX,2
CALL UNPACK ; Read the first FAT sector into CURBUF
LDS DI,[CURBUF]
JMP SHORT GOTGETBUF
GETFREEBUF:
ASSUME DS:NOTHING
PUSH ES ; Get a free buffer for BIOS to use
PUSH BP
LDS DI,[BUFFHEAD]
invoke BUFWRITE
POP BP
POP ES
GOTGETBUF:
ADD DI,BUFINSIZ
MOV WORD PTR [CALLXAD+2],DS
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV WORD PTR [CALLXAD],DI
MOV AL,DBPBHL
MOV AH,BYTE PTR ES:[BP.dpb_UNIT]
MOV WORD PTR [DEVCALL],AX
MOV BYTE PTR [DEVCALL.REQFUNC],DEVBPB
MOV [DEVCALL.REQSTAT],0
MOV AL,BYTE PTR ES:[BP.dpb_media]
MOV [CALLMED],AL
PUSH ES
PUSH DS
PUSH WORD PTR ES:[BP.dpb_driver_addr+2]
PUSH WORD PTR ES:[BP.dpb_driver_addr]
MOV BX,OFFSET DOSGROUP:DEVCALL
POP SI
POP DS ; DS:SI Points to device header
ASSUME DS:NOTHING
POP ES ; ES:BX Points to call header
invoke DEVIOCALL2
POP ES ; Restore ES:BP
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV DI,[DEVCALL.REQSTAT]
TEST DI,STERR
JNZ FATERRJ
MOV AL,BYTE PTR ES:[BP.dpb_media]
LDS SI,[CALLBPB]
ASSUME DS:NOTHING
CMP AL,BYTE PTR [SI.BPMEDIA]
JZ DPBOK
invoke $SETDPB
LDS DI,[CALLXAD] ; Get back buffer pointer
MOV AL,BYTE PTR ES:[BP.dpb_FAT_count]
MOV AH,BYTE PTR ES:[BP.dpb_FAT_size]
MOV WORD PTR [DI.BUFWRTCNT-BUFINSIZ],AX ;Correct buffer info
DPBOK:
context ds
MOV AX,-1
TEST ES:[BP.dpb_current_dir],AX
retz ; If root, leave as root
MOV ES:[BP.dpb_current_dir],AX ; Path may be bad, mark invalid
return
FATERRJ: JMP FATERR
FAT_operation ENDP
do_ext
CODE ENDS
END
+1684
View File
File diff suppressed because it is too large Load Diff
+512
View File
@@ -0,0 +1,512 @@
;
; FCB management routines for MSDOS
;
INCLUDE DOSSEG.ASM
IFNDEF KANJI
KANJI EQU 0 ;FALSE
ENDIF
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
i_need Name1,BYTE
i_need NumIO,BYTE
i_need DevFCB,BYTE
i_need Creating,BYTE
i_need ExtFCB,BYTE
i_need Attrib,BYTE
i_need SpaceFlag,BYTE
i_need Current_Country,WORD
procedure MakeFcb,NEAR
DRVBIT EQU 2
NAMBIT EQU 4
EXTBIT EQU 8
MOV BYTE PTR [SpaceFlag],0
XOR DL,DL ; Flag--not ambiguous file name
TEST AL,DRVBIT ; Use current drive field if default?
JNZ DEFDRV
MOV BYTE PTR ES:[DI],0 ; No - use default drive
DEFDRV:
INC DI
MOV CX,8
TEST AL,NAMBIT ; Use current name fields as defualt?
XCHG AX,BX ; Save bits in BX
MOV AL," "
JZ FILLB ; If not, go fill with blanks
ADD DI,CX
XOR CX,CX ; Don't fill any
FILLB:
REP STOSB
MOV CL,3
TEST BL,EXTBIT ; Use current extension as default
JZ FILLB2
ADD DI,CX
XOR CX,CX
FILLB2:
REP STOSB
XCHG AX,CX ; Put zero in AX
STOSW
STOSW ; Initialize two words after to zero
SUB DI,16 ; Point back at start
TEST BL,1 ; Scan off separators if not zero
JZ SKPSPC
CALL SCANB ; Peel off blanks and tabs
CALL DELIM ; Is it a one-time-only delimiter?
JNZ NOSCAN
INC SI ; Skip over the delimiter
SKPSPC:
CALL SCANB ; Always kill preceding blanks and tabs
NOSCAN:
CALL GETLET
JBE NODRV ; Quit if termination character
CMP BYTE PTR[SI],":" ; Check for potential drive specifier
JNZ NODRV
INC SI ; Skip over colon
SUB AL,"@" ; Convert drive letter to binary drive number
JBE BADDRV ; Valid drive numbers are <= NUMIO
CMP AL,BYTE PTR [NUMIO]
JBE HAVDRV
BADDRV:
MOV DL,-1
HAVDRV:
STOSB ; Put drive specifier in first byte
INC SI
DEC DI ; Counteract next two instructions
NODRV:
DEC SI ; Back up
INC DI ; Skip drive byte
NORMSCAN:
MOV CX,8
CALL GETWORD ; Get 8-letter file name
CMP BYTE PTR [SI],"."
JNZ NODOT
INC SI ; Skip over dot if present
MOV CX,3 ; Get 3-letter extension
CALL MUSTGETWORD
NODOT:
MOV AL,DL
return
NONAM:
ADD DI,CX
DEC SI
return
GETWORD:
CALL GETLET
JBE NONAM ; Exit if invalid character
DEC SI
;
; UGH!!! Horrible bug here that should be fixed at some point:
; If the name we are scanning is longer than CX, we keep on reading!
;
MUSTGETWORD:
CALL GETLET
;
; If spaceFlag is set then we allow spaces in a pathname
;
JB FILLNAM
JNZ MustCheckCX
TEST BYTE PTR [SpaceFlag],0FFh
JZ FILLNAM
CMP AL," "
JNZ FILLNAM
MustCheckCX:
JCXZ MUSTGETWORD
DEC CX
CMP AL,"*" ; Check for ambiguous file specifier
JNZ NOSTAR
MOV AL,"?"
REP STOSB
NOSTAR:
STOSB
IF KANJI
CALL TESTKANJ
JZ NOTDUAL3
JCXZ BNDERR ; Attempt to straddle boundry
MOVSB ; Transfer second byte
DEC CX
JMP SHORT NOTDUAL3
BNDERR:
MOV BYTE PTR ES:[DI-1]," " ; patch up that space
JMP MustGetWord ; go back and scan until delim
NOTDUAL3:
ENDIF
CMP AL,"?"
JNZ MUSTGETWORD
OR DL,1 ; Flag ambiguous file name
JMP MUSTGETWORD
FILLNAM:
MOV AL," "
REP STOSB
DEC SI
return
SCANB:
LODSB
CALL SPCHK
JZ SCANB
DEC SI
return
MakeFCB ENDP
;
; NameTrans is used by FindPath to scan off an element
; of a path. We must allow spaces in pathnames
; Inputs: SS - DOSGROUP
; DS:SI name
; Outputs: DS:SI advanced over spot
; ES:DI point to after Name1
; registers modified: AX, BX, CX, DX
procedure NameTrans,near
MOV BYTE PTR [SpaceFlag],1
PUSH SS
POP ES
MOV DI,OFFSET DOSGROUP:NAME1
PUSH DI
MOV AL,' '
MOV CX,11
REP STOSB
XOR AL,AL
MOV DL,AL
STOSB
POP DI
CMP BYTE PTR [SI],'.'
IF KANJI
JZ FOOBAR
CALL NORMSCAN
CMP [NAME1],0E5H
retnz
MOV [NAME1],5
return
FOOBAR:
ELSE
JNZ NORMSCAN
ENDIF
MOVSB
LODSB
CALL PATHCHRCMP
JZ GOTDOTNAME
OR AL,AL
JZ GOTDOTNAME
CMP AL,'.'
JNZ BADDOTS
STOSB
LODSB
CALL PATHCHRCMP
JZ GOTDOTNAME
OR AL,AL
JZ GOTDOTNAME
DEC SI
BADDOTS:
DEC SI
GOTDOTNAME:
DEC SI
XOR AL,AL
return
nametrans ENDP
SUBTTL BUILDFCB -- MAKE A BLANK FCB FOR A DEVICE
PAGE
procedure BuildFCB,near
ASSUME DS:DOSGROUP,ES:DOSGROUP
; Function:
; Build a blank FCB for I/O to a device
; Outputs:
; Same as GETNAME
MOV AX," "
MOV DI,OFFSET DOSGROUP:DEVFCB+8 ; Point to extent field
STOSW
STOSB ; Blank out extent field
XOR AX,AX
MOV CX,10
REP STOSW ; Fill FCB with zeros
STOSB
invoke DATE16
MOV DI,OFFSET DOSGROUP:DEVFCB+22
XCHG AX,DX
STOSW
XCHG AX,DX
STOSW
XCHG AX,BX ; But device number in AH
MOV BX,OFFSET DOSGROUP:DEVFCB
MOV SI,DI
XOR AL,AL ; Set zero, clear carry
return
BuildFCB ENDP
SUBTTL MOVENAME, LODNAME -- EXAMINE FCB AND SETUP
PAGE
procedure FCB_move,NEAR
entry MOVNAMENOSET
MOV DI,1
JMP SHORT MOVSTART
entry MOVNAME
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS, DX point to FCB or extended FCB
; Outputs:
; DS:DX point to normal FCB
; DS:SI point after end of NAME/EXT in FCB
; ES = DOSGROUP
; If file name OK:
; [NAME1] has name in upper case
; All registers destroyed
; Carry set if bad file name or drive
XOR DI,DI
MOVSTART:
MOV WORD PTR [CREATING],0E500H ; Not creating, not DEL *.*
MOV SI,DX
LODSB
MOV [EXTFCB],AL ; Set flag if extended FCB in use
XOR AH,AH ; Set default attributes
CMP AL,-1 ; Is it an extended FCB?
JNZ HAVATTRB
ADD DX,7 ; Adjust to point to normal FCB
ADD SI,6
MOV AH,[SI-1] ; Attribute byte
LODSB ; Get drive select byte
HAVATTRB:
invoke GETTHISDRV
retc
PUSH DS
PUSH DX
PUSH SI
PUSH AX
;
; DS:DX is pointer to good FCB
; DS:SI is same
;
; Move the file into Name1 and UCASE it
;
PUSH DI
context ES
MOV DI,OFFSET DOSGROUP:NAME1
CALL LodName
POP DI
JC DrvNoSet
;
; are we setting current dir info?
;
OR DI,DI
JNZ DrvNoSet ; do not set dir info
;
; check for device name first, eliminating drive hits on devices
;
context DS
invoke DEVNAME
JNC DrvNoSet ; we have a device
;
; make sure that everything is current
;
invoke FATREAD
ASSUME DS:NOTHING,ES:NOTHING
MOV BYTE PTR [ATTRIB],attr_directory+attr_hidden+attr_system
invoke GETCURRDIR
DrvNoSet:
POP AX
MOV BYTE PTR [ATTRIB],AH
POP SI
POP DX
POP DS
context ES
MOV DI,OFFSET DOSGROUP:NAME1
entry LODNAME
; Inputs: DS:SI point to an FCB
; ES:DI point to an FCB
; Outputs: DS:SI point to after FCB
; ES:DI point to after FCB
; FCB from DS:SI copied and ucased to ES:DI
; Carry set if there was an error.
; Destroys AX,CX
CMP BYTE PTR [SI]," " ; Don't allow blank as first letter
STC ; In case of error
retz
IF KANJI
MOV CX,8
CMP BYTE PTR [SI],0E5H
JNZ MOVCHK
INC SI
MOV AL,5
STOSB
MOVSB
MOV CX,6
MOVCHK:
CALL GETLET
JB RET6
JNZ STOLET ; Is it a delimiter?
CMP AL," " ; This is the only delimiter allowed
STC ; In case of error
JNZ RET6
STOLET:
STOSB
CALL TESTKANJ
JZ MOVLP ;No
LODSB ;Get second byte
DEC CX
JZ BOUNDERR ;Attempt to cross boundry
STOSB
MOVLP:
LOOP MOVCHK
MOV CX,3
MOVCHK2:
CALL GETLET
JB RET6
JNZ STOLET2 ; Is it a delimiter?
CMP AL," " ; This is the only delimiter allowed
STC ; In case of error
retnz
STOLET2:
STOSB
CALL TESTKANJ
JZ MOVLP2 ;No
LODSB ;Get second byte
DEC CX
JNZ DOSTORE
BOUNDERR: ;Attempt to cross boundry
STC
return
DOSTORE:
STOSB
MOVLP2:
LOOP MOVCHK2
ELSE
MOV CX,11
MOVCHK:
CALL GETLET
JB RET6
JNZ STOLET ; Is it a delimiter?
CMP AL," " ; This is the only delimiter allowed
STC ; In case of error
retnz
STOLET:
STOSB
LOOP MOVCHK
ENDIF
CLC ; Got through whole name - no error
RET6: return
FCB_Move ENDP
SUBTTL GETLET, DELIM -- CHECK CHARACTERS AND CONVERT
PAGE
procedure GetLet,NEAR
; Get a byte from [SI], convert it to upper case, and compare for delimiter.
; ZF set if a delimiter, CY set if a control character (other than TAB).
LODSB
CMP AL,"a"
JB CHK1
CMP AL,"z"
JA CHK1
SUB AL,20H ; Convert to upper case
CHK1:
PUSH SI
MOV SI,[Current_Country]
ADD SI,Map_call
PUSH CS ; CS for long return
CALL WORD PTR CS:[SI]
POP SI
entry CHK
CMP AL,"."
retz
CMP AL,'"'
retz
CALL PATHCHRCMP
retz
CMP AL,"["
retz
CMP AL,"]"
retz
DELIM:
CMP AL,":" ; Allow ":" as separator in IBM version
retz
CMP AL,"<"
retz
CMP AL,"|"
retz
CMP AL,">"
retz
CMP AL,"+"
retz
CMP AL,"="
retz
CMP AL,";"
retz
CMP AL,","
retz
SPCHK:
CMP AL,9 ; Filter out tabs too
retz
; WARNING! " " MUST be the last compare
CMP AL," "
return
GetLet ENDP
procedure PATHCHRCMP,NEAR
CMP AL,'/'
retz
CMP AL,'\'
return
PathChrCMP ENDP
IF KANJI
procedure TESTKANJ,NEAR
CMP AL,81H
JB NOTLEAD
CMP AL,9FH
JBE ISLEAD
CMP AL,0E0H
JB NOTLEAD
CMP AL,0FCH
JBE ISLEAD
NOTLEAD:
PUSH AX
XOR AX,AX ;Set zero
POP AX
return
ISLEAD:
PUSH AX
XOR AX,AX ;Set zero
INC AX ;Reset zero
POP AX
return
TESTKANJ ENDP
ENDIF
do_ext
CODE ENDS
END
BIN
View File
Binary file not shown.
+932
View File
@@ -0,0 +1,932 @@
title MSDOS V2.0 FIND
;--------------------------------------------------------------------;
; Revision History: ;
; ;
; V1.1 8/23/82 M.A.Ulloa ;
; ;
; V1.2 9/22/82 M.A.Ulloa ;
; Added the -c and -n options ;
; ;
; 9/23/82 M.A.Ulloa ;
; Added DOS version number control ;
; ;
; 10/07/82 Rev.2 M.A.Ulloa ;
; Changed quote for double quotes, and added ;
; file name printing ;
; ;
; 10/20/82 Rev.3 M.A.Ulloa ;
; Modified IBM name to FIND, and changed the text ;
; of some messages. ;
; ;
; 10/25/82 Rev.4 M.A.Ulloa ;
; Changed name to FIND and all messages to the ;
; IBM form. ;
; ;
; 10/27/82 Rev.5 M.A.Ulloa ;
; Made the correct exit on version check in case ;
; of a 1.x DOS. ;
; ;
; 11/4/82 Rev. 5 A.R. Reynolds ;
; Messages moved to external module ;
; ;
; 11/10/82 Rev. 6 M.A. Ulloa ;
; Corrected problem with line numbers, and a problem ;
; with seeking for 0 chars. ;
; ;
; 03/30/83 Rev. 7 M.A. Ulloa ;
; Added patch area for bug fixing. ;
; ;
; 04/14/83 Rev. 8 M.A. Ulloa ;
; Made changes for Kanji characters. (uhg!) ;
; ;
;--------------------------------------------------------------------;
FALSE equ 0
TRUE equ NOT FALSE
KANJI equ FALSE ;set to true is kanji vers.
;--------------------------------------------------------------------;
; FIND program following the standart UNIX operation. ;
; ;
; FORMAT: ;
; find {option} string {filename {filename} {...}} ;
; ;
; NOTES: ;
; 1) String arguments HAVE to be enclosed ;
; in double quotes. (Two double quotes if a ;
; doble quote is to be included). Only ONE ;
; string argument is presently allowed. ;
; ;
; 2) Options are available: ;
; v All lines but those matching are considered ;
; c Only print a count of matching lines ;
; n Each line is preceded by its relative ;
; line number in the file. ;
; ;
; - Options can be Upper or lower case. ;
; - Format: The switch character followed by an options ;
; character. I.e.: In the IBM PC: /v ;
; ;
; 3) The program returns: ;
; 0 - OK, and some matches ;
; 2 - Some Error ;
; ;
; 4) The maximum line size is determined by ;
; buffer size. Bigger lines will bomb the program. ;
; ;
; 5) If no file name is given then it will asssume ;
; the input is comming from the Standart Input. NO ;
; errors are reported when reading from Standart Input. ;
;--------------------------------------------------------------------;
code segment public
assume cs:code,ss:code,ds:nothing,es:nothing
CR equ 0dh ;A Carriage Return
LF equ 0ah ;A Line Feed
quote_char equ 22h ;A double quote character
buffer_size equ 4096 ;file buffer size
st_buf_size equ 128 ;string arg. buffer size
fname_buf_size equ 64 ;file name buffer size
;----- DOS EQUATES --------------------------------------------------;
std_in equ 0 ;STD input handle
std_out equ 1 ;STD output handle
std_err equ 2 ;STD error handle
dos_ent equ 21h ;DOS entry point
std_con_string_output equ 9
get_version equ 48
char_oper equ 55 ;get configuration parameters
open equ 61 ;DOS std open code
close equ 62 ;DOS std close code
read equ 63 ;DOS std read code
write equ 64 ;DOS std write code
lseek equ 66 ;DOS file seek
exit equ 76 ;DOS process exit code
;----- Misc Data -----------------------------------------------;
make db "***MAUlloa/Microsoft/V12***"
rev db "8"
colon db ": "
n1_buf db "["
n2_buf db 8 dup(0) ;buffer for number conversion
;----- OPTION FLAGS -------------------------------------------------;
; If a flag is set (0ffh) then the option has been selected, if
;reset (0) then it has been not. All options are reset initially.
; NOTE: the order of this table has to remain consistent with the
;options dispatch code. If any changes are made they have to
;correspond with the code.
opt_tbl:
v_flg db 0
c_flg db 0
n_flg db 0
x_flg db 0 ;not used
l_flg db 0 ;not used
;----- LINE COUNTERS ------------------------------------------------;
mtch_cntr dw 0 ;matched lines counter
line_cntr dw 0 ;line counter
;----- MAIN ROUTINE -------------------------------------------------;
start:
;----- CHECK VERSION NUMBER -----------------------------------------;
mov ah,get_version
int 21h
cmp al,2
jge vers_ok
push cs
pop ds
mov dx,offset bad_vers
mov ah,std_con_string_output
int 21h
push es ;bad vers, exit a la 1.x
xor ax,ax
push ax
badfart proc far ;(what a hack!!)
ret
badfart endp
vers_ok:
push cs ;load ES to the right area,
pop es ; for use with DI register
assume es:code
;--------------------------------------------------------------------;
mov si,81h ;Start addrss. of commad line buf.
call kill_bl ;Get rid of blanks
or bx,bx ;A CR found?
jz find_opt ;no, first find the options
args_missing:
mov dx,offset errmsg1 ;empty command line, no args: error.
mov cl,cs:errlen1
call prt_err
mov al,2 ;error code for exit
jmp done
;----- FIND THE OPTION IF ANY ---------------------------------------;
find_opt:
mov ah,char_oper ;get the dos switch char.
mov al,0
int dos_ent ;switch char in DL
push dx
another_opt:
lodsb ;get the first char of command line
cmp al,' ' ;a blank?
je cont_scan
cmp al,CR ;a Carriage Return
je args_missing
pop dx ;get switch character
cmp al,dl ;is it the switch char?
jne find_str ;no, no options: get the string
push dx ;save for another round
lodsb ;get the option character
cmp al,' ' ;a blank?
je cont_scan ;yes, ignore and continue
cmp al,CR ;a CR?
je args_missing ;yes, error...
call make_caps ;Capitalize the character
mov bx,offset opt_tbl ;pointer to option flag table
cmp al,'V' ;the v option?
je opt_v
cmp al,'C' ;the c option?
je opt_c
cmp al,'N' ;the n option?
je opt_n
mov cs:errmsg5_opt,al ;save the option
mov dx,offset errmsg5 ;unknown option: error
mov cl,cs:errlen5
call prt_err
mov dx,offset crlf ;print a CRLF
mov cx,2
call prt_err
jmp another_opt ;process next option
opt_v:
mov di,0
jmp short opt_dispatch
opt_c:
mov di,1
jmp short opt_dispatch
opt_n:
mov di,2
opt_dispatch:
mov es:byte ptr[bx+di],0ffh ;set the corresponding flag
jmp another_opt ;process the rest of the options
cont_scan:
dec si ;adjust SI
call kill_bl ;get rid of blanks
or bx,bx ;A CR found?
jz another_opt ;no, test for other options
jmp args_missing ;yes, error...
;----- FIND STRING ARGUMENT -----------------------------------------;
find_str:
cmp al,quote_char ;string should start with a
jnz bad_str_err ; quote character, if not: error.
mov di,offset st_buffer ;String argument buffer addrss.
xor cx,cx ;Clear to keep string length.
move_str:
lodsb
cmp al,CR ;if a CR is found in the string
jnz str_ok ; then it's a bad string
bad_str_err:
mov dx,offset errmsg2 ;bad string error message
mov cl,cs:errlen2
call prt_err ;print the error.
mov al,2
jmp done
str_ok:
cmp al,quote_char ;look for a quote character
jnz move_char ;not an apost., move to buffer
lodsb ;an apost., check next char.
cmp al,quote_char ;another quote character?
je move_char ;yes, move it to the buffer
dec si ;no, adjust the pointer
mov es:st_length,cx ;store the string length
or cx,cx ;Is the string empty?
jnz other_args ;no: get the rest of the args.
mov al,1 ;empty: no matches(!?)
jmp done
move_char:
stosb ;put in buffer
inc cx ;increment string length
jmp move_str
;----- FIND THE FILE ARGUMENTS --------------------------------------;
other_args: ;Process the rest of the command
; line arguments.
call kill_bl ;get rid of leading blanks
or bx,bx ;At least one argument necessary,
jz further_args ; if a CR not found: ok.
;----- USE STD IN FOR INPUT -----------------------------------------;
push cs
pop ds
mov ax,std_in ;handle
jmp fill
further_args:
call clr_cntrs ;set all counters to zero
mov di,offset file_name_buf ;Set pointer to the name buffer
xor cx,cx ;zero file name length
move_fname:
lodsb
cmp al,' ' ;A blank: end of file name,
je done_move
cmp al,CR ;A CR: idem.
je done_move
stosb ;store in name buffer
inc cx ;increment file name length
jmp move_fname
done_move:
dec si ;Adjust pointer for next round.
mov es:byte ptr[di],00h ;File names are null terminated
push si ;Save SI to continue com. line scan.
push ds ;Save DS register contents for
; later because it points to the
; rest of the arguments.
mov es:file_name_len,cx ;save the name length
;----- OPEN FILE FOR READING ----------------------------------------;
push cs ;Load new DS with CS
pop ds
mov dx,offset file_name_buf ;addrss. of the file name
mov ah,open
mov al,0 ;file open for reading
int dos_ent ;call the DOS
jnc say_name ;if no carry then no errors
jmp open_error
;----- PRINT FILE NAME ----------------------------------------------;
say_name:
push ax ;save file handle
mov dx,offset heading
mov cl,cs:heading_len
xor ch,ch
call prout
mov dx,offset file_name_buf
mov cx,ds:file_name_len
call prout
cmp ds:c_flg,0ffh ;count only flag set?
je xx1
mov dx,offset crlf
mov cx,2
call prout
xx1:
pop ax
;----- Fill Buffer for Matching -------------------------------------;
fill:
mov bx,ax ;retrieve handle
refill:
mov dx,offset buffer ;data buffer addrss.
mov cx,buffer_size
mov ah,read
int dos_ent
jnc no_read_error ;if carry then read error
jmp read_error
no_read_error:
or ax,ax ;if ax=0 then all done
jnz go_match
cmp ds:c_flg,0ffh ;count only flag set?
jne sj2
call print_count
sj2:
cmp bx,std_in ;Using STD IN?
jnz regular
jmp foo ;if so: all done, exit
regular:
mov ah,close ;otherwise close the file
int dos_ent
jmp scan_rest ;get another file
;----- MATCH ROUTINE ------------------------------------------------;
;Note: If input is being taken from a file the stack contains
; (from top to bottom):
; - Pointer to the next command in the command line
; - Pointer to the program segment prefix (to be loaded into
; DS to access the command line.
; if the imput is from the standart input then NONE of it will be
; in the stack.
go_match:
push bx ;save the file handle
mov bp,offset buffer ;ptr to first line of file
mov di,ax ;dispalcement from beg of buffer
cmp ax,buffer_size-1 ;last line of the file?
jg no_last_line ;if yes, add a CRLF just in case
mov bx,bp
cmp byte ptr[bx+di-1],LF ;finished with a LF?
je no_last_line ;yes, it's an OK line.
mov byte ptr[bx+di],CR ;put a CR at the end of the data
inc di
mov byte ptr[bx+di],LF ;put a LF ...
inc di
no_last_line:
push di ;save the # of chars. in the buffer
push bp
mov dx,ds:st_length ;length of the string arg.
dec dx ;adjust for later use
jmp short try_again
more_stuff_o:
jmp more_stuff
;----- SCAN LINES IN THE BUFFER FOR A MATCH -------------------------;
;Note: at this point the stack contains (from top to bottom):
; - Stuff mentioned before
; - File Handle
; - Number of chars. left in the buffer from the next line.
; - Addrs. of the next line in the buffer.
;
; plus, DX has the adjusted length of the string argument.
try_again:
inc ds:line_cntr ;increment line counter
pop bp ;addrs. of next line in the buffer
mov di,bp ;points to beg. of a line
pop cx ;get # of chars left in the buffer
mov bx,cx ;save in case a non-complete line
mov al,LF ;search for a Line Feed
jcxz more_stuff_o ;no chars left in buffer
repnz scasb
jnz more_stuff_o ;no full line left in buffer
push cx ;save chars left in buffer
push di ;points to beg. of next line
mov cx,di
sub cx,bp ;length of the current line
mov bx,cx ;save in case it has a match
dec cx
dec cx ;CRLF characters discounted
jcxz try_again_opt ;if line empty go to next line
mov di,bp ;pointer to the beg. of current line
another_char:
;
; On entry:
; BX line length
; CX adjusted line length
; DX adjusted string argument length
; DI points to beg. of line
;
IF KANJI
push dx ;save for next line
lop:
pop dx
push dx
inc dx ;different algorithm!
mov si,offset st_buffer ;pointer to beg. of string argument
comp_next_char:
push di
mov di,si
call is_prefix ;check for a prefix char
pop di
jnc nopre
lodsw
cmp cx,1 ; Can not compare a two byte char
jz try_again_opt1 ; if there is only one available
cmp ax,word ptr [di]
jz kmatch1
call next_kchar ;no match, advance di to next kanji
jc try_again_opt1 ;not enough chars left in line
jmp short lop ;try another char in line
nopre:
lodsb
cmp al,byte ptr [di]
jz kmatch
call next_kchar ;no match, advance di to next kanji
jc try_again_opt1 ;not enough chars left in line
jmp short lop ;try another char in line
try_again_opt1:
pop dx
jmp try_again_opt
kmatch1:
dec dx ;last char had prefix so it was
; long.
kmatch:
dec dx
jz a_matchk ; no chars left: a match!
call next_kchar
jc try_again_opt1
jmp comp_next_char ; loop if chars left in arg.
a_matchk:
pop dx
ELSE
mov si,offset st_buffer ;pointer to beg. of string argument
lodsb ;get first character of the str. arg.
repnz scasb ;search for a match in current line
jnz try_again_opt ;no match, try the next line
cmp cx,dx ;compare lengths, a full match is not
jb try_again_opt ; possible if CX < DX.
push di ;save addrs. of next char. in the line
push cx ;save the # of chars. left in the line
mov cx,dx ;get the adjusted string arg. length
jcxz a_match ;if a single char string, then match!
repz cmpsb ;compare string with line
jz a_match ;a match found, hurrah!
pop cx ;no match, get # of chars remaining
; in the line.
pop di ;position of the next char. in the line
jmp another_char
;----- A MATCH: CHECK FOR THE v OPTION ------------------------------;
a_match:
pop ax ;adjust stack
pop ax
ENDIF
cmp ds:v_flg,0ffh ;is flag set?
jne prt_line ;no, print the line
jmp try_again
;----- NO MATCH: CHECK FOR THE v OPTION -----------------------------;
try_again_opt:
cmp ds:v_flg,0ffh ;is flag set?
jne try_again ;no goto next line
;----- PRINT THE LINE WITH THE MATCH --------------------------------;
;Note: at this point the stack contains (top to bottom)
; - Stuff mentioned before
;
; plus, BP points to begginig of the current line, BX has the length
;of the current line including the CRLF, and DX the adjusted length of
;the string argument.
prt_line:
cmp ds:c_flg,0ffh ;is count only flag set?
jne no_c_flg
inc ds:mtch_cntr ;yes, increment counter
jmp try_again
no_c_flg:
push dx ;save the adjusted string arg. length
cmp ds:n_flg,0ffh ;is line number flag set?
jne no_n_flg
call prt_lcntr
no_n_flg:
mov dx,bp
mov cx,bx
call prout
pop dx ;restore
jmp try_again
;----- READ MORE TEXT LINES INTO THE BUFFER -------------------------;
; The scanning routines have detected that the buffer does not
;contain a full line any more. More lines have to be read into the
;buffer. But first perform a seek on the file in order to re-read
;the non-complete line into the begining of the buffer.
; Uppon entry BP contains points to the begining of the non-complete
;line, and BX has the number of characters left in the buffer.
; The Stack contains (top to bottom):
; - Pointer to the next command in the command line
; - Pointer to the program segment prefix (to be loaded into
; DS to access the command line).
; - File handle.
more_stuff:
mov dx,bx ;get chars left in buffer
pop bx ;get the handle
or dx,dx ;are there 0 left?
jz no_seek ;yes, do not seek
neg dx ;form two's complement
mov cx,-1
mov al,1 ;seek from the current position
mov ah,lseek ;seek on file
int dos_ent
jc read_error
no_seek:
jmp refill ;no errors: refill the buffer
read_error:
cmp bx,std_in ;Using STD IN?
je foo ;if so: all done, exit
mov ah,close ;close the file
int dos_ent
mov dx,offset errmsg4_pre ;read error
mov cl,cs:errlen4_pre
call prt_file_name ;print the file name in error
mov dx,offset errmsg4_post ;read error
mov cl,cs:errlen4_post
jmp r_error
;----- PRINT ERRORS -------------------------------------------------;
open_error:
mov dx,offset errmsg3_pre ;error in open operation
mov cl,cs:errlen3_pre
call prt_err_2 ;print error message
call prt_file_name ;print the file name in error
mov dx,offset errmsg3_post ;error in open operation
mov cl,cs:errlen3_post
r_error:
call prt_err_2 ;print error message
;----- SCAN THE REST OF THE COMMAND LINE ----------------------------;
scan_rest:
pop ds ;restore pointer to comm. line
pop si ;restore pointer to next comm.
call kill_bl ;look for further args.
or bx,bx ;test for a CR
jnz foo
jmp further_args
foo:
mov al,0 ;Proper code
done:
mov ah,exit ;All done, exit with proper code.
int dos_ent
;--------------------------------------------------------------------;
; Get rid of blanks in command line. ;
; Advances the SI reg till the next non-blank character, if the ;
; character is a CR (0dh) then returns with BX non-zero, otherwise ;
; BX is zero. ;
; ;
; entry: ;
; SI points to the first character on the line to scan. ;
; ;
; exit: ;
; SI points to the first non-blank character found. ;
; BX contains 0D hex if the first non-blank found is ;
; a Carriage Return, otherwise it is 0. ;
; ;
; modifies: ;
; BX, SI, and AX ;
; ;
;--------------------------------------------------------------------;
kill_bl:
cld ;increment
xor bx,bx ;zero bx to start: no CR found
no_bl:
lodsb ;get rid of blanks
cmp al,' '
je no_bl
cmp al,CR
jnz no_cr
mov bx,ax ;make bx non-zero (actually 0dh)
no_cr:
dec si ;adjust pointer
ret
;--------------------------------------------------------------------;
; Clear Counters ;
;--------------------------------------------------------------------;
clr_cntrs:
mov byte ptr es:mtch_cntr,0
mov byte ptr es:line_cntr,0
ret
;--------------------------------------------------------------------;
; Print Count of Matched lines ;
; ;
; Modifies: AX,CX,DX and DI ;
;--------------------------------------------------------------------;
print_count:
push bx ;save handle
cmp bx,std_in ;using std_in?
jz sj3 ;if so do not print file name
mov dx,offset colon
mov cx,2
call prout ;print colon
sj3:
mov ax,ds:mtch_cntr
mov di,offset n2_buf ;buffer for characters
call bin2asc ;convert to ascii
mov dx,offset n2_buf
call prout ;print the number
mov dx,offset crlf
mov cx,2
call prout ;print an end of line
pop bx
ret
;--------------------------------------------------------------------;
; Print relative line number ;
; ;
; Modifies: AX,CX and DI ;
;--------------------------------------------------------------------;
prt_lcntr:
push bx
push dx
mov ax,ds:line_cntr
mov di,offset n2_buf
call bin2asc
mov byte ptr[di],"]"
inc cx
inc cx
mov dx,offset n1_buf
call prout
pop dx
pop bx
ret
;--------------------------------------------------------------------;
; Print string to STD_OUT ;
;--------------------------------------------------------------------;
prout:
mov bx,std_out
mov ah,write
int dos_ent
ret
;--------------------------------------------------------------------;
; Binary to Ascii conversion routine ;
; ;
; Entry: ;
; AX Binary number ;
; DI Points to one past the last char in the ;
; result buffer. ;
; ;
; Exit: ;
; Result in the buffer MSD first ;
; CX Digit count ;
; ;
; Modifies: ;
; AX,BX,CX,DX and DI ;
; ;
;--------------------------------------------------------------------;
bin2asc:
mov bx,0ah
xor cx,cx
go_div:
inc cx
cmp ax,bx
jb div_done
xor dx,dx
div bx
add dl,'0' ;convert to ASCII
push dx
jmp short go_div
div_done:
add al,'0'
push ax
mov bx,cx
deposit:
pop ax
stosb
loop deposit
mov cx,bx
ret
;--------------------------------------------------------------------;
; Print the current file name ;
; ;
; modifies: ;
; DX, CX, BX and AX ;
;--------------------------------------------------------------------;
prt_file_name:
mov dx,offset file_name_buf ;print the file name
mov cx,ds:file_name_len ;retrive file name length
jmp short prt_err_2
;--------------------------------------------------------------------;
; Print an error message to the Standart error ;
; ;
; entry: ;
; DX has the pointer to the message ;
; CX has the length of the message ;
; ;
; modifies: ;
; BX and AX ;
;--------------------------------------------------------------------;
prt_err:
push ds ;Save the current DS
push cs ;Make DS point to the right
pop ds ; place, for DOS use.
call prt_err_2
pop ds
ret
prt_err_2:
xor ch,ch
mov bx,std_err
mov ah,write
int dos_ent ;write error message
ret
;--------------------------------------------------------------------;
; CAPIALIZES THE CHARACTER IN AL ;
; ;
; entry: ;
; AL has the character to Capitalize ;
; ;
; exit: ;
; AL has the capitalized character ;
; ;
; modifies: ;
; AL ;
;--------------------------------------------------------------------;
make_caps:
cmp al,'a'
jb no_cap
cmp al,'z'
jg no_cap
and al,0dfh
no_cap:
ret
IF KANJI
;--------------------------------------------------------------------;
; ADVANCE POINTER TO NEXT KANJI CHARACTER ;
; ;
; entry: DI points to a Kanji string ;
; CX length in bytes of the string ;
; ;
; exit: DI points to next Kanji char ;
; CX has number of bytes left ;
; ;
; modifies: AX ;
; ;
;--------------------------------------------------------------------;
next_kchar:
jcxz no_kleft
call is_prefix
jnc no_p
inc di
dec cx
jcxz no_kleft ; for insurance
no_p:
inc di
dec cx
clc
ret
no_kleft:
stc
ret
;--------------------------------------------------------------------;
; FIND OUT IS THE BYTE IS A KANJI PREFIX ;
; ;
; entry: DI points to a kanji string ;
; ;
; exit: Carry set if it is a kanji prefix ;
; ;
; modifies: AX ;
; ;
;--------------------------------------------------------------------;
is_prefix:
mov al,byte ptr [di]
cmp al,81h
jb nok
cmp al,0a0h
jb isk
cmp al,0e0h
jb nok
cmp al,0fdh
jb isk
nok:
clc
ret
isk:
stc
ret
ENDIF
;----- PATCH AREA ---------------------------------------------------;
patch_area dw 100h dup(?)
;----- BUFFER AREA --------------------------------------------------;
st_length dw 0 ;String argumnet length
st_buffer db st_buf_size dup(?) ;String argument buffer
file_name_len dw 0 ;File name length
file_name_buf db fname_buf_size+1 dup(?) ;File name buffer,(allow for
; null at the end).
buffer db buffer_size+1 dup(?) ;file buffer, the last byte is
;a guard in case of forced insertion
;of a CRLF pair.
;----- ERROR MESSAGES -----------------------------------------------;
EXTRN bad_vers:byte,crlf:byte,errmsg1:byte,errlen1:byte,errmsg2:byte
EXTRN errmsg3_pre:byte,errlen3_pre:byte
EXTRN errmsg3_post:byte,errlen3_post:byte
EXTRN errmsg4_pre:byte,errlen4_pre:byte
EXTRN errmsg4_post:byte,errlen4_post:byte
EXTRN heading:byte,heading_len:byte,errlen2:byte
EXTRN errmsg5:byte,errmsg5_opt:byte,errlen5:byte
code ends
;----- STACK AREA ---------------------------------------------------;
stack segment stack
dw 64 dup(?,?)
stack_top equ $
stack ends
end start
BIN
View File
Binary file not shown.
+1627
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+627
View File
@@ -0,0 +1,627 @@
TITLE GETSET - GETting and SETting MS-DOS system calls
NAME GETSET
;
; System Calls which get and set various things
;
; $GET_VERSION
; $GET_VERIFY_ON_WRITE
; $SET_VERIFY_ON_WRITE
; $SET_CTRL_C_TRAPPING
; $INTERNATIONAL
; $GET_DRIVE_FREESPACE
; $GET_DMA
; $SET_DMA
; $GET_DEFAULT_DRIVE
; $SET_DEFAULT_DRIVE
; $GET_INTERRUPT_VECTOR
; $SET_INTERRUPT_VECTOR
; RECSET
; $CHAR_OPER
;
.xlist
;
; get the appropriate segment definitions
;
INCLUDE DOSSEG.ASM
IFNDEF ALTVECT
ALTVECT EQU 0 ; FALSE
ENDIF
IFNDEF IBM
IBM EQU 0
ENDIF
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
i_need VERFLG,BYTE
i_need CNTCFLAG,BYTE
i_need DMAADD,DWORD
i_need CURDRV,BYTE
i_need Current_Country,WORD
i_need international_table,BYTE
i_need INDOS,BYTE
i_need SYSINITVAR,WORD
i_need NUMIO,BYTE
i_need SWITCH_CHARACTER,BYTE
i_need DEVICE_AVAILABILITY,BYTE
USERNUM DW ? ; 24 bit user number
DB ?
IF IBM
OEMNUM DB 0 ; 8 bit OEM number
ELSE
OEMNUM DB 0FFH ; 8 bit OEM number
ENDIF
MSVERS EQU THIS WORD ; MS-DOS version in hex for $GET_VERSION
MSMAJOR DB DOS_MAJOR_VERSION
MSMINOR DB DOS_MINOR_VERSION
BREAK <$Get_Version -- Return MSDOS version number>
procedure $GET_VERSION,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Return MS-DOS version number
; Outputs:
; OEM number in BH
; User number in BL:CX (24 bits)
; Version number as AL.AH in binary
; NOTE: On pre 1.28 DOSs AL will be zero
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV BX,[USERNUM + 2]
MOV CX,[USERNUM]
MOV AX,[MSVERS]
invoke get_user_stack
ASSUME DS:NOTHING
MOV [SI.user_BX],BX
MOV [SI.user_CX],CX
MOV [SI.user_AX],AX ; Really only sets AH
return
$GET_VERSION ENDP
BREAK <$International - return country-dependent information>
;
; Inputs:
; DS:DX point to a block
; Function:
; give users an idea of what country the application is running
; Outputs:
; AX = number of bytes transferred
; DS:DX ->+---------------------------------+
; | WORD Date/time format |
; +---------------------------------+
; | BYTE ASCIZ currency symbol |
; +---------------------------------+
; | BYTE ASCIZ thousands separator |
; +---------------------------------+
; | BYTE ASCIZ decimal separator |
; +---------------------------------+
procedure $INTERNATIONAL,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV BL,AL
PUSH DS
POP ES
PUSH DX
POP DI
PUSH SS
POP DS
ASSUME DS:DOSGROUP
CMP DI,-1
JZ international_set
OR BL,BL
JNZ international_find
MOV SI,[Current_Country]
MOV AX,WORD PTR [SI-2] ; Get size in AL, country code in AH
MOV BL,AH ; Set country code
JMP SHORT international_copy
international_find:
CALL international_get
JNC international_copy
error country_not_found
international_get:
MOV SI,OFFSET DOSGROUP:international_table
international_next:
LODSW ; Get size in AL, country code in AH
CMP AL,-1
JNZ check_code
STC
RET35:
RET
check_code:
CMP BL,AH
JZ RET35 ; Carry clear
XOR AH,AH
ADD SI,AX
JMP international_next
international_copy:
MOV CL,AL
XOR CH,CH
PUSH DI
REP MOVSB
POP DI
MOV WORD PTR ES:[DI.MAP_CALL + 2],CS ; Set segment for case map call
international_ok:
XOR AX,AX
MOV AL,BL ; Return country code in AX
transfer SYS_RET_OK
international_set:
CALL international_get
JNC international_store
error country_not_found
international_store:
MOV [Current_Country],SI
JMP international_ok
$INTERNATIONAL ENDP
BREAK <$Get_Verify_on_Write - return verify-after-write flag>
procedure $GET_VERIFY_ON_WRITE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; none.
; Function:
; returns flag
; Returns:
; AL = value of VERIFY flag
MOV AL,[VERFLG]
return
$GET_VERIFY_ON_WRITE ENDP
BREAK <$Set_Verify_on_Write - Toggle verify-after-write flag>
procedure $SET_VERIFY_ON_WRITE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = desired value of VERIFY flag
; Function:
; Sets flag
; Returns:
; None
AND AL,1
MOV [VERFLG],AL
return
$SET_VERIFY_ON_WRITE ENDP
BREAK <$Set_CTRL_C_Trapping -- En/Disable ^C check in dispatcher>
procedure $SET_CTRL_C_TRAPPING,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = 0 read ^C status
; AL = 1 Set ^C status, DL = 0/1 for ^C off/on
; Function:
; Enable disable ^C checking in dispatcher
; Outputs:
; If AL = 0 then DL = 0/1 for ^C off/on
OR AL,AL
JNZ CTRL_C_set
invoke get_user_stack
MOV AL,[CNTCFLAG]
MOV BYTE PTR [SI.user_DX],AL
return
CTRL_C_set:
DEC AL
JNZ bad_val
AND DL,01h
MOV [CNTCFLAG],DL
return
bad_val:
MOV AL,0FFH
return
$SET_CTRL_C_TRAPPING ENDP
BREAK <$Get_INDOS_Flag -- Return location of DOS critical-section flag>
procedure $GET_INDOS_FLAG,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Returns location of DOS status for interrupt routines
; Returns:
; Flag location in ES:BX
invoke get_user_stack
MOV [SI.user_BX],OFFSET DOSGROUP:INDOS
MOV [SI.user_ES],SS
return
$GET_INDOS_FLAG ENDP
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
procedure $GET_IN_VARS,NEAR
; Return a pointer to interesting DOS variables This call is version
; dependent and is subject to change without notice in future versions.
; Use at risk.
invoke get_user_stack
MOV [SI.user_BX],OFFSET DOSGROUP:SYSINITVAR
MOV [SI.user_ES],SS
return
$GET_IN_VARS ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <$Get_Drive_Freespace -- Return bytes of free disk space on a drive>
procedure $GET_DRIVE_FREESPACE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DL = Drive number
; Function:
; Return number of free allocation units on drive
; Outputs:
; BX = Number of free allocation units
; DX = Total Number of allocation units on disk
; CX = Sector size
; AX = Sectors per allocation unit
; = -1 if bad drive specified
; This call returns the same info in the same registers (except for FAT pointer)
; as the old FAT pointer calls
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV AL,DL
invoke GETTHISDRV
MOV AX,-1
JC BADFRDRIVE
invoke FATREAD
XOR DX,DX
MOV BX,2
MOV CX,ES:[BP.dpb_max_cluster]
DEC CX
PUSH CX ; Save Total
SCANFREE:
invoke UNPACK
JNZ NOTFREECLUS
INC DX
NOTFREECLUS:
INC BX
LOOP SCANFREE
POP BX ; Remember Total
MOV AL,ES:[BP.dpb_cluster_mask]
INC AL
XOR AH,AH
MOV CX,ES:[BP.dpb_sector_size]
BADFRDRIVE:
invoke get_user_stack
ASSUME DS:NOTHING
MOV [SI. user_CX],CX
MOV [SI.user_DX],BX
MOV [SI.user_BX],DX
MOV [SI.user_AX],AX
return
$GET_DRIVE_FREESPACE ENDP
BREAK <$Get_DMA, $Set_DMA -- Get/Set current DMA address>
procedure $GET_DMA,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Get DISK TRANSFER ADDRESS
; Returns:
; ES:BX is current transfer address
MOV BX,WORD PTR [DMAADD]
MOV CX,WORD PTR [DMAADD+2]
invoke get_user_stack
MOV [SI.user_BX],BX
MOV [SI.user_ES],CX
return
$GET_DMA ENDP
procedure $SET_DMA,NEAR ; System call 26
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX is desired new disk transfer address
; Function:
; Set DISK TRANSFER ADDRESS
; Returns:
; None
MOV WORD PTR [DMAADD],DX
MOV WORD PTR [DMAADD+2],DS
return
$SET_DMA ENDP
BREAK <$Get_Default_DPB,$Get_DPB -- Return pointer to DPB>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
procedure $GET_DEFAULT_DPB,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DL = Drive number (always default drive for call 31)
; Function:
; Return pointer to drive parameter table for default drive
; Returns:
; DS:BX points to the DPB
; AL = 0 If OK, = -1 if bad drive (call 50 only)
MOV DL,0
entry $GET_DPB
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV AL,DL
invoke GETTHISDRV
JC ISNODRV
invoke FATREAD
invoke get_user_stack
ASSUME DS:NOTHING
MOV [SI.user_BX],BP
MOV [SI.user_DS],ES
XOR AL,AL
return
ISNODRV:
MOV AL,-1
return
$GET_Default_dpb ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <$Get_Default_Drive, $Set_Default_Drive -- Set/Get default drive>
procedure $GET_DEFAULT_DRIVE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Return current drive number
; Returns:
; AL = drive number
MOV AL,[CURDRV]
return
$GET_DEFAULT_DRIVE ENDP
procedure $SET_DEFAULT_DRIVE,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DL = Drive number for new default drive
; Function:
; Set the default drive
; Returns:
; AL = Number of drives, NO ERROR RETURN IF DRIVE NUMBER BAD
MOV AL,[NUMIO]
CMP DL,AL
JNB RET17
MOV [CURDRV],DL
RET17: return
$SET_DEFAULT_DRIVE ENDP
BREAK <$Get_Interrupt_Vector - Get/Set interrupt vectors>
procedure $GET_INTERRUPT_VECTOR,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = interrupt number
; Function:
; Get the interrupt vector
; Returns:
; ES:BX is current interrupt vector
CALL RECSET
LES BX,DWORD PTR ES:[BX]
invoke get_user_stack
MOV [SI.user_BX],BX
MOV [SI.user_ES],ES
return
$GET_INTERRUPT_VECTOR ENDP
procedure $SET_INTERRUPT_VECTOR,NEAR ; System call 37
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; AL = interrupt number
; DS:DX is desired new interrupt vector
; Function:
; Set the interrupt vector
; Returns:
; None
CALL RECSET
MOV ES:[BX],DX
MOV ES:[BX+2],DS
return
$SET_INTERRUPT_VECTOR ENDP
IF ALTVECT
VECIN: ; INPUT VECTORS
DB 22H ; Terminate
DB 23H ; ^C
DB 24H ; Hard error
DB 28H ; Spooler
LSTVEC DB ? ; ALL OTHER
VECOUT: ; GET MAPPED VECTOR
DB int_terminate
DB int_ctrl_c
DB int_fatal_abort
DB int_spooler
LSTVEC2 DB ? ; Map to itself
NUMVEC = VECOUT-VECIN
ENDIF
procedure RECSET,NEAR
IF ALTVECT
PUSH SS
POP ES
MOV [LSTVEC],AL ; Terminate list with real vector
MOV [LSTVEC2],AL ; Terminate list with real vector
MOV CX,NUMVEC ; Number of possible translations
MOV DI,OFFSET DOSGROUP:VECIN ; Point to vectors
REPNE SCASB
MOV AL,ES:[DI+NUMVEC-1] ; Get translation
ENDIF
XOR BX,BX
MOV ES,BX
MOV BL,AL
SHL BX,1
SHL BX,1
return
recset ENDP
BREAK <$Char_Oper - hack on paths, switches so that xenix can look like PCDOS>
;
; input: AL = function:
; 0 - read switch char
; 1 - set switch char (char in DL)
; 2 - read device availability
; 3 - set device availability (0/FF in DL)
; DL = 0 means /DEV/ must preceed device names
; DL = Non0 means /DEV/ need not preeceed
; output: (get) DL - character/flag
;
procedure $CHAR_OPER,NEAR
ASSUME DS:NOTHING,ES:NOTHING
PUSH SS
POP DS
ASSUME DS:DOSGROUP
OR AL,AL
JNZ char_oper_set_switch
MOV DL,[switch_character]
JMP SHORT char_oper_ret
char_oper_set_switch:
DEC AL
JNZ char_oper_read_avail
MOV [switch_character],DL
return
char_oper_read_avail:
DEC AL
JNZ char_oper_set_avail
MOV DL,[device_availability]
JMP SHORT char_oper_ret
char_oper_set_avail:
DEC AL
JNZ char_oper_bad_ret
MOV [device_availability],DL
return
char_oper_bad_ret:
MOV AL,0FFh
return
char_oper_ret:
invoke get_user_stack
MOV [SI.user_DX],DX
return
$CHAR_OPER ENDP
BREAK <$SetDPB - Create a valid DPB from a user-specified BPB>
procedure $SETDPB,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; ES:BP Points to DPB
; DS:SI Points to BPB
; Function:
; Build a correct DPB from the BPB
; Outputs:
; ES:BP and DS preserved all others destroyed
MOV DI,BP
ADD DI,2 ; Skip over dpb_drive and dpb_UNIT
LODSW
STOSW ; dpb_sector_size
MOV DX,AX
LODSB
DEC AL
STOSB ; dpb_cluster_mask
INC AL
XOR AH,AH
LOG2LOOP:
TEST AL,1
JNZ SAVLOG
INC AH
SHR AL,1
JMP SHORT LOG2LOOP
SAVLOG:
MOV AL,AH
STOSB ; dpb_cluster_shift
MOV BL,AL
MOVSW ; dpb_first_FAT Start of FAT (# of reserved sectors)
LODSB
STOSB ; dpb_FAT_count Number of FATs
MOV BH,AL
LODSW
STOSW ; dpb_root_entries Number of directory entries
MOV CL,5
SHR DX,CL ; Directory entries per sector
DEC AX
ADD AX,DX ; Cause Round Up
MOV CX,DX
XOR DX,DX
DIV CX
MOV CX,AX ; Number of directory sectors
INC DI
INC DI ; Skip dpb_first_sector
MOVSW ; Total number of sectors in DSKSIZ (temp as dpb_max_cluster)
LODSB
MOV ES:[BP.dpb_media],AL ; Media byte
LODSW ; Number of sectors in a FAT
STOSB ; dpb_FAT_size
MUL BH ; Space occupied by all FATs
ADD AX,ES:[BP.dpb_first_FAT]
STOSW ; dpb_dir_sector
ADD AX,CX ; Add number of directory sectors
MOV ES:[BP.dpb_first_sector],AX
SUB AX,ES:[BP.DSKSIZ]
NEG AX ; Sectors in data area
MOV CL,BL ; dpb_cluster_shift
SHR AX,CL ; Div by sectors/cluster
INC AX
MOV ES:[BP.dpb_max_cluster],AX
MOV ES:[BP.dpb_current_dir],0 ; Current directory is root
return
$SETDPB ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
do_ext
CODE ENDS
END
+18
View File
@@ -0,0 +1,18 @@
;*************************************
; COMMAND EQUs which are switch dependant
IF1
IF IBM
%OUT IBM version
ELSE
%OUT Normal version
ENDIF
IF HIGHMEM
%OUT Highmem version
ENDIF
IF KANJI
%OUT Kanji version
ENDIF
ENDIF
+939
View File
@@ -0,0 +1,939 @@
TITLE COMMAND Initialization
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
ENVIRONSIZ EQU 0A0H ;Must agree with values in EVIRONMENT segment
ENVIRONSIZ2 EQU 092H
CODERES SEGMENT PUBLIC
EXTRN RSTACK:WORD,SETVECT:NEAR,LODCOM:NEAR,CONTC:NEAR,INT_2E:NEAR
EXTRN LOADCOM:NEAR,CHKSUM:NEAR
IF IBMVER
EXTRN EXECHK:NEAR,SYSCALL:NEAR
ENDIF
CODERES ENDS
DATARES SEGMENT PUBLIC
EXTRN DATARESEND:BYTE,LTPA:WORD,MYSEG:WORD,MYSEG1:WORD,MYSEG2:WORD
EXTRN MEMSIZ:WORD,TRNSEG:WORD,ENVIRSEG:WORD,RSWITCHAR:BYTE
EXTRN COMDRV:BYTE,COMLET:BYTE,PERMCOM:BYTE,SINGLECOM:WORD
EXTRN PARENT:WORD,IO_SAVE:WORD,COM_PTR:DWORD,COM_FCB1:DWORD
EXTRN COM_FCB2:DWORD,SUM:WORD,BATCH:WORD,COMSPEC:BYTE
IF IBMVER
EXTRN SYS_CALL:DWORD,EXESEG:WORD,EXESUM:WORD
ENDIF
DATARES ENDS
ENVIRONMENT SEGMENT PUBLIC
EXTRN ENVIREND:BYTE,PATHSTRING:BYTE,ECOMSPEC:BYTE
ENVIRONMENT ENDS
TRANCODE SEGMENT PUBLIC
EXTRN DATINIT:FAR
TRANCODE ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN TRANSPACEEND:BYTE
TRANSPACE ENDS
ZEXEC_DATA SEGMENT PUBLIC
IF IBM
EXTRN ZEXECDATAEND:BYTE
ENDIF
ZEXEC_DATA ENDS
; *******************************************************************
; START OF INIT PORTION
; This code is overlayed the first time the TPA is used.
INIT SEGMENT PUBLIC PARA
EXTRN HEADER:BYTE
EXTRN BADCOMLKMES:BYTE
PUBLIC CONPROC
ASSUME CS:RESGROUP,DS:RESGROUP,ES:RESGROUP,SS:RESGROUP
ORG 0
ZERO = $
CONPROC:
MOV SP,OFFSET RESGROUP:RSTACK
IF HIGHMEM
MOV BX,WORD PTR DS:[PDB_block_len]
MOV AX,OFFSET RESGROUP:ENVIREND + 15
MOV CL,4
SHR AX,CL
PUSH AX ; Save size to alloc
INC AX ; Plus one for arena
SUB BX,AX ; Subtract size of resident
MOV WORD PTR DS:[PDB_block_len],BX
MOV AX,CS
SUB BX,AX
MOV AH,SETBLOCK
INT 21H
POP BX ; Get back size to alloc
MOV AH,ALLOC
INT 21H
MOV [REALRES],AX
MOV ES,AX
XOR SI,SI
MOV DI,SI
MOV CX,OFFSET RESGROUP:ENVIREND
SHR CX,1 ; Length of resident and environment in words
; Last byte doesn't matter
REP MOVSW ; Move to end of memory
MOV DS,AX
MOV BX,AX
MOV AH,SET_CURRENT_PDB
INT 21H
MOV AX,BX
MOV BX,OFFSET RESGROUP:DATARESEND + 15
MOV CL,4
SHR BX,CL ; BX is size for SETBLOCK
MOV WORD PTR DS:[PDB_block_len],BX
ADD WORD PTR DS:[PDB_block_len],AX
MOV [LTPA],CS
MOV AH,SETBLOCK
INT 21H ;Shrink to not include environment
MOV BX,(ENVIRONSIZ + 15) / 16
MOV AH,ALLOC
INT 21H ;Allocate the environment
MOV [ENVIRSEG],AX
MOV CS:[ENVIRSEGSAV],AX
MOV ES,AX
ASSUME ES:ENVIRONMENT
XOR DI,DI
MOV SI,OFFSET RESGROUP:PATHSTRING
MOV CX,ENVIRONSIZ
REP MOVSB
MOV AX,WORD PTR CS:[PDB_block_len]
ENDIF
IF NOT HIGHMEM
MOV AX,OFFSET RESGROUP:ENVIREND + 15
MOV CL,4
SHR AX,CL
MOV CX,CS
ADD AX,CX ; Compute segment of TPA
MOV [LTPA],AX ; Good enough for the moment
MOV AX,WORD PTR DS:[PDB_block_len]
ENDIF
MOV [MYSEG1],DS
MOV [MYSEG2],DS
MOV [MYSEG],DS
MOV [MEMSIZ],AX
MOV DX,OFFSET TRANGROUP:TRANSPACEEND + 15
MOV CL,4
SHR DX,CL
IF IBM
PUSH DX
MOV DX,OFFSET EGROUP:ZEXECDATAEND + 15
MOV CL,4
SHR DX,CL
POP CX
ADD DX,CX
ENDIF
SUB AX,DX
MOV [TRNSEG],AX ; Read it in here
MOV AX,DS:[PDB_environ]
OR AX,AX
JZ BUILDENV ; Need to make an environment
IF HIGHMEM
INC BYTE PTR CS:[CHUCKENV] ; Flag no ENVIRONSEG
ELSE
INC BYTE PTR [CHUCKENV] ; Flag no ENVIRONSEG
ENDIF
JMP SHORT ENVIRONPASSED
BUILDENV:
IF NOT HIGHMEM
MOV AX,OFFSET RESGROUP:PATHSTRING ; Figure environment pointer
MOV CL,4
SHR AX,CL
MOV DX,DS
ADD AX,DX
ELSE
JMP SHORT GOTTHEENVIR
ENDIF
ENVIRONPASSED:
MOV [ENVIRSEG],AX
IF HIGHMEM
DEC AX
MOV ES,AX
INC AX
MOV ES:[arena_owner],DS ; Adjust owner of passed envir
ENDIF
MOV ES,AX
ASSUME ES:ENVIRONMENT
GOTTHEENVIR:
MOV AX,CHAR_OPER SHL 8
INT int_command
MOV [RSWITCHAR],DL
CMP DL,'/'
JNZ IUSESLASH
IF HIGHMEM
MOV CS:[COMSPECT],'\'
ELSE
MOV [COMSPECT],'\'
ENDIF
IF HIGHMEM
CMP BYTE PTR CS:[CHUCKENV],0
ELSE
CMP BYTE PTR [CHUCKENV],0
ENDIF
JNZ IUSESLASH
MOV ES:[ECOMSPEC-10H],'\'
IUSESLASH:
IF IBMVER
PUSH ES
MOV AX,(Get_interrupt_vector SHL 8) + int_command
INT int_command
MOV WORD PTR [SYS_CALL],BX
MOV WORD PTR [SYS_CALL+2],ES
MOV DX,OFFSET RESGROUP:SYSCALL
MOV AX,(Set_interrupt_vector SHL 8) + int_command
INT int_command
POP ES
ENDIF
MOV AL,BYTE PTR DS:[FCB] ; get drive spec for default
MOV AH,DRVCHAR
MOV [COMDRV],AL
ADD AL,40H ; Convert to letter
CMP AL,40H
JZ NOCOMDRV
STD
IF HIGHMEM
CMP BYTE PTR CS:[CHUCKENV],0
ELSE
CMP BYTE PTR [CHUCKENV],0
ENDIF
JNZ NOTWIDENV
PUSH DS
PUSH ES
POP DS
MOV DI,OFFSET ENVIRONMENT:ECOMSPEC + ENVIRONSIZ2 - 1 - 10H
MOV SI,OFFSET ENVIRONMENT:ECOMSPEC + ENVIRONSIZ2 - 3 - 10H
MOV CX,ENVIRONSIZ2 - 2
REP MOVSB
POP DS
MOV WORD PTR ES:[ECOMSPEC-10H],AX
NOTWIDENV:
CLD
IF HIGHMEM
MOV WORD PTR CS:[AUTOBAT],AX
ELSE
MOV WORD PTR [AUTOBAT],AX
ENDIF
MOV [COMLET],AL
NOCOMDRV:
CALL SETVECT ; Set the vectors
MOV SI,80H
LODSB
MOV CL,AL
XOR CH,CH
JCXZ COMRETURNSJ ; No parameters
MOV SI,81H ; Start of parms
CHKARG:
LODSB
CMP AL,' '
JZ NEXTCH
CMP AL,9 ; Tab only other delimiter
JZ NEXTCH
CMP AL,[RSWITCHAR] ; Switch?
JNZ CHKOTHERARGS ; No
DEC CX
JCXZ ARGSDONEJ ; oops
LODSB
OR AL,20H ; Lower case
CMP AL,'p' ; PERMCOM switch
JNZ NEXTCH
JMP SETPERM
NEXTCH:
CMP AL,'d'
JNZ NEXTCH3
IF HIGHMEM
MOV BYTE PTR CS:[PRDATTM],1 ; User explicitly says no date time
ELSE
MOV BYTE PTR [PRDATTM],1 ; User explicitly says no date time
ENDIF
LOOP CHKARG
JMP SHORT ARGSDONEJ
NEXTCH3:
CMP AL,'c'
JNZ NEXTCH2 ; SINGLECOM switch 2
MOV [SINGLECOM],SI ; Point to the rest of the command line
MOV [PERMCOM],0 ; A SINGLECOM must not be a PERMCOM
IF HIGHMEM
MOV BYTE PTR CS:[PRDATTM],1 ; No date or time either, explicit
ELSE
MOV BYTE PTR [PRDATTM],1 ; No date or time either, explicit
ENDIF
ARGSDONEJ:
JMP ARGSDONE
NEXTCH2:
LOOP CHKARG
COMRETURNSJ:
JMP COMRETURNS
CHKOTHERARGS:
DEC SI
MOV DX,SI
PUSH CX
PUSH SI
CONTRLOOP:
LODSB
DEC CX
CMP AL,' '
JZ SETCDEV
CMP AL,9
JZ SETCDEV
JCXZ SETCDEVA
JMP SHORT CONTRLOOP
SETCDEVA:
INC SI
SETCDEV:
MOV BYTE PTR [SI-1],0
MOV AX,(OPEN SHL 8) OR 2 ; Read and write
INT int_command
JC CHKSRCHSPEC ; Wasn't a file
MOV BX,AX
MOV AX,IOCTL SHL 8
INT int_command
TEST DL,80H
JNZ ISADEVICE
MOV AH,CLOSE ; Close initial handle, wasn't a device
INT int_command
JMP CHKSRCHSPEC
ISADEVICE:
XOR DH,DH
OR DL,3 ; Make sure has CON attributes
MOV AX,(IOCTL SHL 8) OR 1
INT int_command
MOV DX,BX ; Save new handle
POP BX ; Throw away saved SI
POP BX ; Throw away saved CX
PUSH CX
MOV CX,3
XOR BX,BX
RCCLLOOP: ; Close 0,1 and 2
MOV AH,CLOSE
INT int_command
INC BX
LOOP RCCLLOOP
MOV BX,DX ; New device handle
MOV AH,XDUP
INT int_command ; Dup to 0
MOV AH,XDUP
INT int_command ; Dup to 1
MOV AH,XDUP
INT int_command ; Dup to 2
MOV AH,CLOSE
INT int_command ; Close initial handle
POP CX
JCXZ ARGSDONEJ2
JMP CHKARG
CHKSRCHSPEC: ; Not a device, so must be directory spec
IF HIGHMEM
MOV BYTE PTR CS:[CHUCKENV],0 ; If search specified -- no inheritance
MOV AX,CS:[ENVIRSEGSAV]
MOV [ENVIRSEG],AX
ELSE
MOV BYTE PTR [CHUCKENV],0 ; If search specified -- no inheritance
MOV AX,OFFSET RESGROUP:PATHSTRING ; Figure environment pointer
MOV CL,4
SHR AX,CL
MOV DX,DS
ADD AX,DX
MOV [ENVIRSEG],AX
ENDIF
MOV ES,AX
MOV BYTE PTR [SI-1],' '
POP SI ; Remember location
POP CX ; and count
IF HIGHMEM
MOV DI,CS:[ECOMLOC]
ELSE
MOV DI,[ECOMLOC]
ENDIF
COMTRLOOP:
LODSB
DEC CX
CMP AL,' '
JZ SETCOMSR
CMP AL,9
JZ SETCOMSR
STOSB
IF KANJI
XOR AH,AH
ENDIF
JCXZ SETCOMSR
IF KANJI
CALL ITESTKANJ
JZ COMTRLOOP
DEC CX
MOVSB
INC AH
JCXZ SETCOMSR
ENDIF
JMP SHORT COMTRLOOP
SETCOMSR:
PUSH SI
PUSH CX
PUSH DS
IF HIGHMEM
PUSH CS
POP DS
ENDIF
MOV SI,OFFSET RESGROUP:COMSPECT
MOV CX,14
MOV AL,ES:[DI-1]
IF KANJI
OR AH,AH
JNZ INOTROOT ; Last char was KANJI second byte, might be '\'
ENDIF
CALL PATHCHRCMPR
JNZ INOTROOT
INC SI ; Don't make a double /
DEC CX
INOTROOT:
REP MOVSB
MOV DX,[ECOMLOC] ; Now lets make sure its good!
PUSH ES
POP DS
MOV AX,OPEN SHL 8
INT int_command ; Open COMMAND.COM
POP DS
JC SETCOMSRBAD ; No COMMAND.COM here
MOV BX,AX ; Handle
MOV AH,CLOSE
INT int_command ; Close COMMAND.COM
SETCOMSRRET:
POP CX
POP SI
ARGSDONEJ2:
JCXZ ARGSDONE
JMP CHKARG
SETCOMSRBAD:
IF HIGHMEM
PUSH DS
PUSH CS
POP DS
ENDIF
MOV DX,OFFSET RESGROUP:BADCOMLKMES
MOV AH,STD_CON_STRING_OUTPUT
INT int_command
MOV SI,OFFSET RESGROUP:COMSPECT
MOV DI,[ECOMLOC]
MOV CX,14
REP MOVSB ; Get my default back
IF HIGHMEM
POP DS
ENDIF
JMP SHORT SETCOMSRRET
CHKARGJ:
JMP CHKARG
SETPERM:
INC [PERMCOM]
IF HIGHMEM
CMP BYTE PTR CS:[PRDATTM],-1
ELSE
CMP BYTE PTR [PRDATTM],-1
ENDIF
JNZ LOOPIT
IF HIGHMEM
MOV BYTE PTR CS:[PRDATTM],0 ; If not set explicit, set to prompt
ELSE
MOV BYTE PTR [PRDATTM],0 ; If not set explicit, set to prompt
ENDIF
LOOPIT:
LOOP CHKARGJ
ARGSDONE:
CMP [PERMCOM],0
JZ COMRETURNS
PUSH ES ; Save environment pointer
MOV AH,SET_CURRENT_PDB
MOV BX,DS
MOV ES,BX
INT int_command ; Current process is me
MOV DI,PDB_Exit ; Diddle the addresses in my header
MOV AX,OFFSET RESGROUP:LODCOM
STOSW
MOV AX,DS
STOSW
MOV AX,OFFSET RESGROUP:CONTC
STOSW
MOV AX,DS
STOSW
MOV WORD PTR DS:[PDB_Parent_PID],DS ; Parent is me forever
MOV DX,OFFSET RESGROUP:INT_2E
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 02EH
INT int_command ;Set magic interrupt
POP ES ;Remember environment
COMRETURNS:
MOV AX,WORD PTR DS:[PDB_Parent_PID]
MOV [PARENT],AX ; Save parent
MOV WORD PTR DS:[PDB_Parent_PID],DS ; Parent is me
MOV AX,WORD PTR DS:[PDB_JFN_Table]
MOV [IO_SAVE],AX ; Get the default stdin and out
MOV WORD PTR [COM_PTR+2],DS ; Set all these to resident
MOV WORD PTR [COM_FCB1+2],DS
MOV WORD PTR [COM_FCB2+2],DS
MOV DI,OFFSET RESGROUP:COMSPEC
IF HIGHMEM
MOV SI,CS:[ECOMLOC]
CMP BYTE PTR CS:[CHUCKENV],0
ELSE
MOV SI,[ECOMLOC]
CMP BYTE PTR [CHUCKENV],0
ENDIF
MOV AX,DS ; XCHG ES,DS
PUSH ES
POP DS
MOV ES,AX
JZ COPYCOMSP ; All set up for copy
PUSH CS
POP DS
MOV SI,OFFSET RESGROUP:COMSPSTRING
PUSH ES
PUSH DI
CALL IFINDE
MOV SI,DI
PUSH ES
POP DS
POP DI
POP ES
JNC COPYCOMSP
COMSPECNOFND:
IF HIGHMEM
MOV DS,CS:[ENVIRSEG]
MOV SI,CS:[ECOMLOC]
ELSE
MOV SI,[ECOMLOC]
ADD SI,OFFSET RESGROUP:PATHSTRING
PUSH CS
POP DS
ENDIF
COPYCOMSP:
LODSB
STOSB
OR AL,AL
JNZ COPYCOMSP
IF HIGHMEM
MOV DS,CS:[REALRES]
PUSH CS
POP ES
MOV AH,DEALLOC
INT 21H
CMP BYTE PTR CS:[CHUCKENV],0
JZ GOTENVIR ; Environment is ok
MOV ES,CS:[ENVIRSEGSAV]
MOV AH,DEALLOC
INT 21H
ELSE
PUSH CS
POP DS
MOV BX,OFFSET RESGROUP:DATARESEND + 15
MOV CL,4
SHR BX,CL
MOV AH,SETBLOCK
INT int_command ; Shrink me to the resident only
CMP BYTE PTR [CHUCKENV],0
JNZ GOTENVIR ; Environment was passed
MOV BX,(ENVIRONSIZ + 15) /16
MOV AH,ALLOC
INT int_command ; "ALLOCATE" the environment
MOV DS,[ENVIRSEG]
MOV [ENVIRSEG],AX
MOV ES,AX
XOR SI,SI
MOV DI,SI
MOV CX,ENVIRONSIZ
REP MOVSB
PUSH CS
POP DS
ENDIF
GOTENVIR:
CALL LOADCOM ; Load the transient in the right place
CALL CHKSUM ; Compute the checksum
MOV [SUM],DX ; Save it
IF IBM
MOV AX,[MEMSIZ]
MOV DX,OFFSET EGROUP:ZEXECDATAEND + 15
MOV CL,4
SHR DX,CL
SUB AX,DX
MOV [EXESEG],AX
CALL EXECHK
MOV [EXESUM],DX
ENDIF
IF MSVER
CMP [SINGLECOM],0
JNZ NOPHEAD ; Don't print header if SINGLECOM
IF HIGHMEM
PUSH DS
PUSH CS
POP DS
ENDIF
MOV DX,OFFSET RESGROUP:HEADER
MOV AH,STD_CON_STRING_OUTPUT
INT int_command
IF HIGHMEM
POP DS
ENDIF
NOPHEAD:
ENDIF
IF HIGHMEM
CMP BYTE PTR CS:[PRDATTM],0
ELSE
CMP BYTE PTR [PRDATTM],0
ENDIF
JNZ NODTTM ; Don't do AUTOEXEC or date time
MOV BX,3 ; 48 BYTES ENOUGH
MOV AH,ALLOC
INT int_command
JC DODTTM ; PRETEND NO BATCH
MOV [BATCH],AX
MOV ES,AX
XOR DI,DI
IF HIGHMEM
CMP BYTE PTR CS:[AUTOBAT],0
ELSE
CMP BYTE PTR [AUTOBAT],0
ENDIF
JNZ NOAUTSET
MOV AH,GET_DEFAULT_DRIVE
INT int_command
ADD AL,'A'
IF HIGHMEM
MOV CS:[AUTOBAT],AL
ELSE
MOV [AUTOBAT],AL
ENDIF
NOAUTSET:
IF HIGHMEM
PUSH DS
PUSH CS
POP DS
ENDIF
MOV SI,OFFSET RESGROUP:AUTOBAT
MOV CX,8
REP MOVSW ; NAME
MOV AX,-1
MOV CL,10
REP STOSW ; PARMS
MOV DX,OFFSET RESGROUP:AUTOBAT
MOV AX,OPEN SHL 8
INT int_command ; See if AUTOEXEC.BAT exists
JC NOABAT
MOV BX,AX
MOV AH,CLOSE
INT int_command
IF HIGHMEM
POP DS
ENDIF
JMP SHORT DRV0
NOABAT:
IF HIGHMEM
POP DS
ENDIF
MOV ES,[BATCH] ; Not found--turn off batch job
MOV AH,DEALLOC
INT int_command
MOV [BATCH],0 ; AFTER DEALLOC in case of ^C
DODTTM:
IF HIGHMEM
MOV AX,OFFSET TRANGROUP:DATINIT
MOV WORD PTR CS:[INITADD],AX
MOV AX,[TRNSEG]
MOV WORD PTR CS:[INITADD+2],AX
CALL DWORD PTR CS:[INITADD]
ELSE
MOV AX,OFFSET TRANGROUP:DATINIT
MOV WORD PTR[INITADD],AX
MOV AX,[TRNSEG]
MOV WORD PTR[INITADD+2],AX
CALL DWORD PTR [INITADD]
ENDIF
NODTTM:
IF IBMVER
CMP [SINGLECOM],0
JNZ DRV0 ; Don't print header if SINGLECOM
MOV DX,OFFSET RESGROUP:HEADER
MOV AH,STD_CON_STRING_OUTPUT
INT int_command
ENDIF
DRV0:
IF HIGHMEM
PUSH DS
MOV AX,OFFSET RESGROUP:LODCOM
PUSH AX
MQQ PROC FAR
RET
MQQ ENDP
ELSE
JMP LODCOM ; Allocate the transient
ENDIF
PATHCHRCMPR:
CMP [RSWITCHAR],'/'
JZ RNOSLASHT
CMP AL,'/'
JZ RET41
RNOSLASHT:
CMP AL,'\'
RET41:
RET
IFINDE:
CALL IFIND ; FIND THE NAME
JC IFIND2 ; CARRY MEANS NOT FOUND
JMP ISCASB1 ; SCAN FOR = SIGN
;
; On return of FIND1, ES:DI points to beginning of name
;
IFIND:
CLD
CALL ICOUNT0 ; CX = LENGTH OF NAME
IF HIGHMEM
MOV ES,CS:[REALRES]
ASSUME ES:RESGROUP
MOV ES,ES:[ENVIRSEG]
ASSUME ES:NOTHING
ELSE
MOV ES,[ENVIRSEG]
ENDIF
XOR DI,DI
IFIND1:
PUSH CX
PUSH SI
PUSH DI
IFIND11:
LODSB
IF KANJI
CALL ITESTKANJ
JZ NOTKANJ4
DEC SI
LODSW
INC DI
INC DI
CMP AX,ES:[DI-2]
JNZ IFIND12
DEC CX
LOOP IFIND11
JMP SHORT IFIND12
NOTKANJ4:
ENDIF
CALL IUPCONV
INC DI
CMP AL,ES:[DI-1]
JNZ IFIND12
LOOP IFIND11
IFIND12:
POP DI
POP SI
POP CX
JZ IFIND2
PUSH CX
CALL ISCASB2 ; SCAN FOR A NUL
POP CX
CMP BYTE PTR ES:[DI],0
JNZ IFIND1
STC ; INDICATE NOT FOUND
IFIND2:
RET
ICOUNT0:
PUSH DS
POP ES
MOV DI,SI
PUSH DI ; COUNT NUMBER OF CHARS UNTIL "="
CALL ISCASB1
JMP SHORT ICOUNTX
PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL
CALL ISCASB2
ICOUNTX:
POP CX
SUB DI,CX
XCHG DI,CX
RET
ISCASB1:
MOV AL,"=" ; SCAN FOR AN =
JMP SHORT ISCASBX
ISCASB2:
XOR AL,AL ; SCAN FOR A NUL
ISCASBX:
MOV CX,100H
REPNZ SCASB
RET
IF KANJI
ITESTKANJ:
CMP AL,81H
JB NOTLEAD
CMP AL,9FH
JBE ISLEAD
CMP AL,0E0H
JB NOTLEAD
CMP AL,0FCH
JBE ISLEAD
NOTLEAD:
PUSH AX
XOR AX,AX ;Set zero
POP AX
RET
ISLEAD:
PUSH AX
XOR AX,AX ;Set zero
INC AX ;Reset zero
POP AX
RET
ENDIF
IUPCONV:
CMP AL,"a"
JB IRET22
CMP AL,"z"
JA IRET22
SUB AL,20H ; Lower-case changed to upper-case
IRET22:
RET
ICONDEV LABEL BYTE
DB "/DEV/"
DB "CON",0,0,0,0,0,0 ; Room for 8 char device
BADCSPFL DB 0
COMSPECT DB "/COMMAND.COM",0,0
AUTOBAT DB 0,":\AUTOEXEC.BAT",0
PRDATTM DB -1 ;Init not to prompt for date time
INITADD DD ?
CHUCKENV DB 0
ECOMLOC DW OFFSET ENVIRONMENT:ECOMSPEC-10H
IF HIGHMEM
REALRES DW ?
ENVIRSEGSAV DW ?
ENDIF
COMSPSTRING DB "COMSPEC="
INIT ENDS
END
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2025 Broken Pipe
Copyright (c) 1983 Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+648
View File
@@ -0,0 +1,648 @@
TITLE MISC - Miscellanious routines for MS-DOS
NAME MISC
;
; Miscellaneous system calls most of which are CAVEAT
;
; $SLEAZEFUNC
; $SLEAZEFUNCDL
; $GET_INDOS_FLAG
; $GET_IN_VARS
; $GET_DEFAULT_DPB
; $GET_DPB
; $DISK_RESET
; $SETDPB
; $Dup_PDB
; $CREATE_PROCESS_DATA_BLOCK
; SETMEM
;
.xlist
;
; get the appropriate segment definitions
;
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
ifndef Kanji
Kanji equ 0
endif
ENTRYPOINTSEG EQU 0CH
MAXDIF EQU 0FFFH
SAVEXIT EQU 10
i_need LASTBUFFER,DWORD
i_need INDOS,BYTE
i_need SYSINITVAR,BYTE
i_need CurrentPDB,WORD
i_need CreatePDB,BYTE
i_need EXIT_TYPE,BYTE
i_need EXIT_CODE,WORD
i_need LASTENT,WORD
i_need THISDPB,DWORD
i_need ATTRIB,BYTE
i_need EXTFCB,BYTE
i_need DMAADD,DWORD
i_need DIRSTART,WORD
i_need CURBUF,DWORD
i_need USER_SP,WORD
i_need ENTLAST,WORD
i_need THISDRV,BYTE
ASSUME SS:DOSGROUP
BREAK <SleazeFunc -- get a pointer to media byte>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
procedure $SLEAZEFUNC,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Return Stuff sort of like old get fat call
; Outputs:
; DS:BX = Points to FAT ID byte (IBM only)
; GOD help anyone who tries to do ANYTHING except
; READ this ONE byte.
; DX = Total Number of allocation units on disk
; CX = Sector size
; AL = Sectors per allocation unit
; = -1 if bad drive specified
MOV DL,0
entry $SLEAZEFUNCDL
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV AL,DL
invoke GETTHISDRV
MOV AL,-1
JC BADSLDRIVE
invoke FATREAD
MOV DX,ES:[BP.dpb_max_cluster]
DEC DX
MOV AL,ES:[BP.dpb_cluster_mask]
INC AL
MOV CX,ES:[BP.dpb_sector_size]
ADD BP,dpb_media
BADSLDRIVE:
invoke get_user_stack
ASSUME DS:NOTHING
MOV [SI.user_CX],CX
MOV [SI.user_DX],DX
MOV [SI.user_BX],BP
MOV [SI.user_DS],ES
return
$SLEAZEFUNC ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <$ABORT -- Terminate a process>
procedure $ABORT,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; CS:00 must point to valid program header block
; Function:
; Restore terminate and Cntrl-C addresses, flush buffers
; and transfer to the terminate address
; Returns:
; TO THE TERMINATE ADDRESS
XOR AL,AL
MOV [exit_type],exit_abort
;
; abort_inner must have AL set as the exit code!
;
entry abort_inner
MOV AH,[exit_type]
MOV [exit_code],AX
invoke Get_user_stack
MOV DS,[SI.user_CS] ; set up old interrupts
XOR AX,AX
MOV ES,AX
MOV SI,SAVEXIT
MOV DI,addr_int_terminate
MOVSW
MOVSW
MOVSW
MOVSW
MOVSW
MOVSW
transfer reset_environment
$ABORT ENDP
BREAK <$Dir_Search_First -- Start a directory search>
procedure $DIR_SEARCH_FIRST,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to unopenned FCB
; Function:
; Directory is searched for first matching entry and the directory
; entry is loaded at the disk transfer address
; Returns:
; AL = -1 if no entries matched, otherwise 0
invoke GETFILE
ASSUME DS:DOSGROUP
SAVPLCE:
; Search-for-next enters here to save place and report
; findings.
MOV DL,0 ; Do not XOR!!!
JC KILLSRCH
OR AH,AH ; Is it I/O device?
JS KILLIT ; If so, sign bit will end search
MOV AX,[LASTENT]
INC DL
KILLIT:
MOV ES:[DI.FILDIRENT],AX
MOV AX,WORD PTR [THISDPB]
MOV ES:[DI.fcb_DRVBP],AX
MOV AX,WORD PTR [THISDPB+2]
MOV ES:[DI.fcb_DRVBP+2],AX
MOV AX,[DIRSTART]
MOV ES:[DI.fcb_DRVBP+4],AX
; Information in directory entry must be copied into the first
; 33 bytes starting at the disk transfer address.
MOV SI,BX
LES DI,[DMAADD]
MOV AX,00FFH
CMP AL,[EXTFCB]
JNZ NORMFCB
STOSW
INC AL
STOSW
STOSW
MOV AL,[ATTRIB]
STOSB
NORMFCB:
MOV AL,[THISDRV]
INC AL
STOSB ; Set drive number
OR DL,DL
JZ DOSRELATIVE
MOV DS,WORD PTR [CURBUF+2]
ASSUME DS:NOTHING
DOSRELATIVE:
IF KANJI
MOVSW
CMP BYTE PTR ES:[DI-2],5
JNZ NOTKTRAN
MOV BYTE PTR ES:[DI-2],0E5H
NOTKTRAN:
MOV CX,15
ELSE
MOV CX,16
ENDIF
REP MOVSW ; Copy 32 bytes of directory entry
XOR AL,AL
return
ASSUME DS:NOTHING
KILLSRCH1:
PUSH DS
POP ES ; Make ES:DI point to the FCB
KILLSRCH:
MOV AX,-1
MOV WORD PTR ES:[DI.FILDIRENT],AX
return
$DIR_SEARCH_FIRST ENDP
BREAK <$Dir_Search_Next -- Find next matching directory entry>
procedure $DIR_SEARCH_NEXT,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX points to unopenned FCB returned by $DIR_SEARCH_FIRST
; Function:
; Directory is searched for the next matching entry and the directory
; entry is loaded at the disk transfer address
; Returns:
; AL = -1 if no entries matched, otherwise 0
invoke MOVNAMENOSET
ASSUME ES:DOSGROUP
MOV DI,DX
JC NEAR PTR KILLSRCH1
MOV AX,[DI.FILDIRENT]
LES BP,DWORD PTR [DI.fcb_DRVBP]
OR AX,AX
JS NEAR PTR KILLSRCH1
MOV BX,[DI.fcb_DRVBP+4]
PUSH DX
PUSH DS
PUSH AX
MOV WORD PTR [THISDPB],BP
MOV WORD PTR [THISDPB+2],ES
invoke SetDirSrch
ASSUME DS:DOSGROUP
POP AX
MOV [ENTLAST],-1
invoke GetEnt
invoke NextEnt
POP ES
ASSUME ES:NOTHING
POP DI
JMP SAVPLCE
$DIR_SEARCH_NEXT ENDP
BREAK <$Get_FCB_File_Length -- Return size of file in current records>
procedure $GET_FCB_FILE_LENGTH,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX points to unopenned FCB
; Function:
; Set random record field to size of file
; Returns:
; AL = -1 if no entries matched, otherwise 0
invoke GETFILE
ASSUME DS:DOSGROUP
MOV AL,-1
retc
ADD DI,fcb_RR ; Write size in RR field
MOV CX,WORD PTR ES:[DI.fcb_RECSIZ-fcb_RR]
OR CX,CX
JNZ RECOK
MOV CX,128
RECOK:
XOR DX,DX ; Intialize size to zero
INC SI
INC SI ; Point to length field
MOV DS,WORD PTR [CURBUF+2]
ASSUME DS:NOTHING
MOV AX,[SI+2] ; Get high word of size
DIV CX
PUSH AX ; Save high part of result
LODSW ; Get low word of size
DIV CX
OR DX,DX ; Check for zero remainder
POP DX
JZ DEVSIZ
INC AX ; Round up for partial record
JNZ DEVSIZ ; Propagate carry?
INC DX
DEVSIZ:
STOSW
MOV AX,DX
STOSB
MOV AL,0
CMP CX,64
JAE RET14 ; Only 3-byte field if fcb_RECSIZ >= 64
MOV ES:[DI],AH
RET14: return
$GET_FCB_FILE_LENGTH ENDP
BREAK <$Get_Fcb_Position -- Set random record field to current position>
procedure $GET_FCB_POSITION,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX points to openned FCB
; Function:
; Sets random record field to be same as current record fields
; Returns:
; None
invoke GETREC
MOV WORD PTR [DI+fcb_RR],AX
MOV [DI+fcb_RR+2],DL
CMP [DI.fcb_RECSIZ],64
JAE RET16
MOV [DI+fcb_RR+2+1],DH ; Set 4th byte only if record size < 64
RET16: return
$GET_FCB_POSITION ENDP
BREAK <$Disk_Reset -- Flush out all dirty buffers>
procedure $DISK_RESET,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Flush and invalidate all buffers
; Returns:
; Nothing
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV AL,-1
invoke FLUSHBUF
MOV WORD PTR [LASTBUFFER+2],-1
MOV WORD PTR [LASTBUFFER],-1
invoke SETVISIT
ASSUME DS:NOTHING
NBFFR: ; Free ALL buffers
MOV [DI.VISIT],1 ; Mark as visited
CMP BYTE PTR [DI.BUFDRV],-1
JZ SKPBF ; Save a call to PLACEBUF
MOV WORD PTR [DI.BUFDRV],00FFH
invoke SCANPLACE
SKPBF:
invoke SKIPVISIT
JNZ NBFFR
return
$DISK_RESET ENDP
procedure $RAW_CON_IO,NEAR ; System call 6
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DL = -1 if input
; else DL is output character
; Function:
; Input or output raw character from console, no echo
; Returns:
; AL = character
MOV AL,DL
CMP AL,-1
JNZ RAWOUT
LES DI,DWORD PTR [user_SP] ; Get pointer to register save area
XOR BX,BX
invoke GET_IO_FCB
retc
MOV AH,1
invoke IOFUNC
JNZ RESFLG
invoke SPOOLINT
OR BYTE PTR ES:[DI.user_F],40H ; Set user's zero flag
XOR AL,AL
return
RESFLG:
AND BYTE PTR ES:[DI.user_F],0FFH-40H ; Reset user's zero flag
RILP:
invoke SPOOLINT
entry $RAW_CON_INPUT ; System call 7
; Inputs:
; None
; Function:
; Input raw character from console, no echo
; Returns:
; AL = character
XOR BX,BX
invoke GET_IO_FCB
retc
MOV AH,1
invoke IOFUNC
JZ RILP
XOR AH,AH
invoke IOFUNC
return
;
; Output the character in AL to stdout
;
entry RAWOUT
PUSH BX
MOV BX,1
invoke GET_IO_FCB
JC RAWRET1
TEST [SI.fcb_DEVID],080H ; output to file?
JZ RAWNORM ; if so, do normally
PUSH DS
PUSH SI
LDS SI,DWORD PTR [SI.fcb_FIRCLUS] ; output to special?
TEST BYTE PTR [SI+SDEVATT],ISSPEC
POP SI
POP DS
JZ RAWNORM ; if not, do normally
INT int_fastcon ; quickly output the char
JMP SHORT RAWRET
RAWNORM:
CALL RAWOUT3
RAWRET: CLC
RAWRET1:
POP BX
return
;
; Output the character in AL to handle in BX
;
entry RAWOUT2
invoke GET_IO_FCB
retc
RAWOUT3:
PUSH AX
JMP SHORT RAWOSTRT
ROLP:
invoke SPOOLINT
RAWOSTRT:
MOV AH,3
CALL IOFUNC
JZ ROLP
POP AX
MOV AH,2
CALL IOFUNC
CLC ; Clear carry indicating successful
return
$RAW_CON_IO ENDP
ASSUME DS:NOTHING,ES:NOTHING
; This routine is called at DOS init
procedure OUTMES,NEAR ; String output for internal messages
LODS CS:BYTE PTR [SI]
CMP AL,"$"
retz
invoke OUT
JMP SHORT OUTMES
return
OutMes ENDP
ASSUME SS:DOSGROUP
BREAK <$Parse_File_Descriptor -- Parse an arbitrary string into an FCB>
procedure $PARSE_FILE_DESCRIPTOR,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:SI Points to a command line
; ES:DI Points to an empty FCB
; Bit 0 of AL = 1 At most one leading separator scanned off
; = 0 Parse stops if separator encountered
; Bit 1 of AL = 1 If drive field blank in command line - leave FCB
; = 0 " " " " " " - put 0 in FCB
; Bit 2 of AL = 1 If filename field blank - leave FCB
; = 0 " " " - put blanks in FCB
; Bit 3 of AL = 1 If extension field blank - leave FCB
; = 0 " " " - put blanks in FCB
; Function:
; Parse command line into FCB
; Returns:
; AL = 1 if '*' or '?' in filename or extension, 0 otherwise
; DS:SI points to first character after filename
invoke MAKEFCB
PUSH SI
invoke get_user_stack
POP [SI.user_SI]
return
$PARSE_FILE_DESCRIPTOR ENDP
BREAK <$Create_Process_Data_Block,SetMem -- Set up process data block>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
procedure $Dup_PDB,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV BYTE PTR [CreatePDB], 0FFH ; indicate a new process
$Dup_PDB ENDP
procedure $CREATE_PROCESS_DATA_BLOCK,NEAR
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
; Inputs:
; DX = Segment number of new base
; Function:
; Set up program base and copy term and ^C from int area
; Returns:
; None
; Called at DOS init
MOV ES,DX
TEST BYTE PTR [CreatePDB],0FFh
JZ create_PDB_old
MOV DS,[CurrentPDB]
JMP SHORT Create_copy
Create_PDB_old:
invoke get_user_stack
MOV DS,[SI.user_CS]
Create_copy:
XOR SI,SI ; copy all 80h bytes
MOV DI,SI
MOV CX,80H
REP MOVSW
TEST BYTE PTR [CreatePDB],0FFh ; Shall we create a process?
JZ Create_PDB_cont ; nope, old style call
;
; Here we set up for a new process...
;
PUSH CS
POP DS
ASSUME DS:DOSGROUP
XOR BX,BX ; dup all jfns
MOV CX,FilPerProc
Create_dup_jfn:
PUSH ES ; save new PDB
invoke get_jfn_pointer ; ES:DI is jfn
JC create_skip ; not a valid jfn
PUSH ES ; save him
PUSH DI
invoke get_sf_from_jfn ; get sf pointer
JC create_no_inc
INC ES:[DI].sf_ref_count ; new fh
create_no_inc:
POP DI
POP ES ; get old jfn
MOV AL,ES:[DI] ; get sfn
POP ES
PUSH ES
MOV AL,ES:[BX] ; copy into new place!
create_skip:
POP ES
INC BX ; next jfn...
LOOP create_dup_jfn
PUSH [CurrentPDB] ; get current process
POP BX
PUSH BX
POP ES:[PDB_Parent_PID] ; stash in child
MOV [CurrentPDB],ES
ASSUME DS:NOTHING
MOV DS,BX
;
; end of new process create
;
Create_PDB_cont:
MOV BYTE PTR [CreatePDB],0h ; reset flag
MOV AX,DS:[2] ; set up size for fall through
entry SETMEM
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
; Inputs:
; AX = Size of memory in paragraphs
; DX = Segment
; Function:
; Completely prepares a program base at the
; specified segment.
; Called at DOS init
; Outputs:
; DS = DX
; ES = DX
; [0] has INT int_abort
; [2] = First unavailable segment ([ENDMEM])
; [5] to [9] form a long call to the entry point
; [10] to [13] have exit address (from int_terminate)
; [14] to [17] have ctrl-C exit address (from int_ctrl_c)
; [18] to [21] have fatal error address (from int_fatal_abort)
; DX,BP unchanged. All other registers destroyed.
XOR CX,CX
MOV DS,CX
MOV ES,DX
MOV SI,addr_int_terminate
MOV DI,SAVEXIT
MOV CX,6
REP MOVSW
MOV ES:[2],AX
SUB AX,DX
CMP AX,MAXDIF
JBE HAVDIF
MOV AX,MAXDIF
HAVDIF:
MOV BX,ENTRYPOINTSEG
SUB BX,AX
MOV CL,4
SHL AX,CL
MOV DS,DX
MOV WORD PTR DS:[PDB_CPM_Call+1],AX
MOV WORD PTR DS:[PDB_CPM_Call+3],BX
MOV DS:[PDB_Exit_Call],(int_abort SHL 8) + mi_INT
MOV BYTE PTR DS:[PDB_CPM_Call],mi_Long_CALL
MOV WORD PTR DS:[PDB_Call_System],(int_command SHL 8) + mi_INT
MOV BYTE PTR DS:[PDB_Call_System+2],mi_Long_RET
return
$CREATE_PROCESS_DATA_BLOCK ENDP
do_ext
CODE ENDS
END
BIN
View File
Binary file not shown.
+17
View File
@@ -0,0 +1,17 @@
TITLE MORE Messages
CODE SEGMENT PUBLIC
PUBLIC MORETXT,BADVER,CRLFTXT,BUFFER
MORETXT DB 13,"-- More --$"
BADVER DB "MORE: Incorrect DOS version"
CRLFTXT DB 13,10,"$"
;
; THIS VARIABLE MUST BE DEFINED LAST!
;
BUFFER DB 4098 DUP (?)
CODE ENDS
END

+615
View File
@@ -0,0 +1,615 @@
;
; MSCODE.ASM -- MSDOS code
;
INCLUDE DOSSEG.ASM
INCLUDE STDSW.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
IFNDEF KANJI
KANJI EQU 0 ; FALSE
ENDIF
IFNDEF IBM
IBM EQU 0
ENDIF
IFNDEF HIGHMEM
HIGHMEM EQU 0
ENDIF
i_need USER_SP,WORD
i_need USER_SS,WORD
i_need SAVEDS,WORD
i_need SAVEBX,WORD
i_need INDOS,BYTE
i_need NSP,WORD
i_need NSS,WORD
i_need CURRENTPDB,WORD
i_need AUXSTACK,BYTE
i_need CONSWAP,BYTE
i_need IDLEINT,BYTE
i_need NOSETDIR,BYTE
i_need ERRORMODE,BYTE
i_need IOSTACK,BYTE
i_need WPERR,BYTE
i_need DSKSTACK,BYTE
i_need CNTCFLAG,BYTE
i_need LEAVEADDR,WORD
i_need NULLDEVPT,DWORD
IF NOT IBM
i_need OEM_HANDLER,DWORD
ENDIF
EXTRN DSKSTATCHK:NEAR,GETBP:NEAR,DSKREAD:NEAR,DSKWRITE:NEAR
BREAK <Copyright notice and version>
CODSTRT EQU $
IF NOT IBM
IF NOT KANJI
PUBLIC HEADER
HEADER DB 13,10,"Microsoft MS-DOS version "
DB DOS_MAJOR_VERSION + "0"
DB "."
DB (DOS_MINOR_VERSION / 10) + "0"
DB (DOS_MINOR_VERSION MOD 10) + "0"
IF HIGHMEM
DB "H"
ENDIF
ENDIF
IF KANJI
PUBLIC HEADER
HEADER DB 13,10,82h,"M"+1fh,82h,"i"+20h,82h,"c"+20h,82h,"r"+20h,82h,"o"+20h
DB 82h,"s"+20h,82h,"o"+20h,82h,"f"+20h,82h,"t"+20h
DB 81h,40h,82h,"M"+1fh,82h,"S"+1fh,81h,5dh+1fh
DB 82h,"D"+1fh,82h,"O"+1fh,82h,"S"+1fh,81h,40h
DB 82h,DOS_MAJOR_VERSION+"0"+1fh
DB 81h,25h+1fh
DB 82h,(DOS_MINOR_VERSION / 10)+"0"+1fh
DB 82h,(DOS_MINOR_VERSION MOD 10)+"0"+1fh
DB 94h,0c5h
ENDIF
DB 13,10
DB "Copyright 1981,82,83 Microsoft Corp.",13,10,"$"
ENDIF
BREAK <System call entry points and dispatcher>
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
procedure SYSTEM_CALL,NEAR
entry QUIT ; INT 20H entry point
MOV AH,0
JMP SHORT SAVREGS
entry COMMAND ; Interrupt call entry point (INT 21H)
IF NOT IBM
CMP AH,SET_OEM_HANDLER
JB NOTOEM
JMP $SET_OEM_HANDLER
NOTOEM:
ENDIF
CMP AH,MAXCOM
JBE SAVREGS
BADCALL:
MOV AL,0
entry IRET
IRET
entry CALL_ENTRY ; System call entry point and dispatcher
POP AX ; IP from the long call at 5
POP AX ; Segment from the long call at 5
POP [User_SP] ; IP from the CALL 5
PUSHF ; Start re-ordering the stack
CLI
PUSH AX ; Save segment
PUSH [User_SP] ; Stack now ordered as if INT had been used
CMP CL,MAXCALL ; This entry point doesn't get as many calls
JA BADCALL
MOV AH,CL
SAVREGS:
CALL save_world
MOV [SaveDS],DS
MOV [SaveBX],BX
MOV BX,CS
MOV DS,BX
ASSUME DS:DOSGROUP
INC [INDOS] ; Flag that we're in the DOS
MOV AX,[user_SP]
MOV [NSP],AX
MOV AX,[user_SS]
MOV [NSS],AX
POP AX
PUSH AX
MOV [user_SP],SP
MOV [user_SS],SS
;
; save user stack in his area for later returns (possibly from EXEC)
; Here comes multitasking!!!
;
MOV DS,[CurrentPDB]
MOV WORD PTR DS:[PDB_User_stack],SP
MOV WORD PTR DS:[PDB_User_stack+2],SS
MOV BX,CS ; no holes here.
MOV SS,BX
ASSUME SS:DOSGROUP
entry REDISP
MOV SP,OFFSET DOSGROUP:AUXSTACK ; Enough stack for interrupts
STI ; Stack OK now
PUSH CS
POP DS
XOR BH,BH
MOV [CONSWAP],BH
MOV [IDLEINT],1
MOV BYTE PTR [NoSetDir],0 ; set directories on search
MOV BL,AH
SHL BX,1
CLD
OR AH,AH
JZ DSKROUT ; ABORT
CMP AH,12
JBE IOROUT ; Character I/O
CMP AH,GET_CURRENT_PDB ; INT 24 needs GET,SET PDB
JZ IOROUT
CMP AH,SET_CURRENT_PDB
JNZ DSKROUT
IOROUT:
CMP [ERRORMODE],0
JNZ DISPCALL ; Stay on AUXSTACK if INT 24
MOV SP,OFFSET DOSGROUP:IOSTACK
JMP SHORT DISPCALL
DSKROUT:
MOV [ERRORMODE],0 ; Cannot make non 1-12 calls in
MOV [WPERR],-1 ; error mode, so good place to
; make sure flags are reset
MOV SP,OFFSET DOSGROUP:DSKSTACK
TEST [CNTCFLAG],-1
JZ DISPCALL
PUSH AX
invoke DSKSTATCHK
POP AX
DISPCALL:
PUSH [LEAVEADDR]
PUSH CS:[BX+DISPATCH]
MOV BX,[SaveBX]
MOV DS,[SaveDS]
ASSUME DS:NOTHING
return
entry LEAVE
ASSUME SS:NOTHING ; User routines may misbehave
CLI
DEC [INDOS]
MOV SP,[user_SP]
MOV SS,[user_SS]
MOV BP,SP
MOV BYTE PTR [BP.user_AX],AL
MOV AX,[NSP]
MOV [user_SP],AX
MOV AX,[NSS]
MOV [user_SS],AX
CALL restore_world
IRET
SYSTEM_CALL ENDP
;
; restore_world restores all registers ('cept SS:SP, CS:IP, flags) from
; the stack prior to giving the user control
;
ASSUME DS:NOTHING,ES:NOTHING
restore_tmp DW ?
procedure restore_world,NEAR
POP restore_tmp ; POP restore_tmp
POP AX ; PUSH ES
POP BX ; PUSH DS
POP CX ; PUSH BP
POP DX ; PUSH DI
POP SI ; PUSH SI
POP DI ; PUSH DX
POP BP ; PUSH CX
POP DS ; PUSH BX
POP ES ; PUSH AX
world_ret:
PUSH restore_tmp ; PUSH restore_tmp
return
restore_world ENDP
;
; save_world saves complete registers on the stack
;
procedure save_world,NEAR
POP restore_tmp
PUSH ES
PUSH DS
PUSH BP
PUSH DI
PUSH SI
PUSH DX
PUSH CX
PUSH BX
PUSH AX
JMP SHORT world_ret
save_world ENDP
;
; get_user_stack returns the user's stack (and hence registers) in DS:SI
;
procedure get_user_stack,NEAR
LDS SI,DWORD PTR [user_SP]
return
get_user_stack ENDP
; Standard Functions
DISPATCH LABEL WORD
.lall
short_addr $ABORT ; 0 0
.xall
short_addr $STD_CON_INPUT ; 1 1
short_addr $STD_CON_OUTPUT ; 2 2
short_addr $STD_AUX_INPUT ; 3 3
short_addr $STD_AUX_OUTPUT ; 4 4
short_addr $STD_PRINTER_OUTPUT ; 5 5
short_addr $RAW_CON_IO ; 6 6
short_addr $RAW_CON_INPUT ; 7 7
short_addr $STD_CON_INPUT_NO_ECHO ; 8 8
short_addr $STD_CON_STRING_OUTPUT ; 9 9
short_addr $STD_CON_STRING_INPUT ; 10 A
short_addr $STD_CON_INPUT_STATUS ; 11 B
short_addr $STD_CON_INPUT_FLUSH ; 12 C
short_addr $DISK_RESET ; 13 D
short_addr $SET_DEFAULT_DRIVE ; 14 E
short_addr $FCB_OPEN ; 15 F
short_addr $FCB_CLOSE ; 16 10
short_addr $DIR_SEARCH_FIRST ; 17 11
short_addr $DIR_SEARCH_NEXT ; 18 12
short_addr $FCB_DELETE ; 19 13
short_addr $FCB_SEQ_READ ; 20 14
short_addr $FCB_SEQ_WRITE ; 21 15
short_addr $FCB_CREATE ; 22 16
short_addr $FCB_RENAME ; 23 17
short_addr CPMFUNC ; 24 18
short_addr $GET_DEFAULT_DRIVE ; 25 19
short_addr $SET_DMA ; 26 1A
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
short_addr $SLEAZEFUNC ; 27 1B
short_addr $SLEAZEFUNCDL ; 28 1C
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
short_addr CPMFUNC ; 29 1D
short_addr CPMFUNC ; 30 1E
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
short_addr $GET_DEFAULT_DPB ; 31 1F
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
short_addr CPMFUNC ; 32 20
short_addr $FCB_RANDOM_READ ; 33 21
short_addr $FCB_RANDOM_WRITE ; 34 22
short_addr $GET_FCB_FILE_LENGTH ; 35 23
short_addr $GET_FCB_POSITION ; 36 24
MAXCALL = ($-DISPATCH)/2 - 1
; Extended Functions
short_addr $SET_INTERRUPT_VECTOR ; 37 25
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
short_addr $CREATE_PROCESS_DATA_BLOCK ; 38 26
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
short_addr $FCB_RANDOM_READ_BLOCK ; 39 27
short_addr $FCB_RANDOM_WRITE_BLOCK ; 40 28
short_addr $PARSE_FILE_DESCRIPTOR ; 41 29
short_addr $GET_DATE ; 42 2A
short_addr $SET_DATE ; 43 2B
short_addr $GET_TIME ; 44 2C
short_addr $SET_TIME ; 45 2D
short_addr $SET_VERIFY_ON_WRITE ; 46 2E
; Extended functionality group
short_addr $GET_DMA ; 47 2F
short_addr $GET_VERSION ; 48 30
short_addr $Keep_Process ; 49 31
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
short_addr $GET_DPB ; 50 32
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
short_addr $SET_CTRL_C_TRAPPING ; 51 33
short_addr $GET_INDOS_FLAG ; 52 34
short_addr $GET_INTERRUPT_VECTOR ; 53 35
short_addr $GET_DRIVE_FREESPACE ; 54 36
short_addr $CHAR_OPER ; 55 37
short_addr $INTERNATIONAL ; 56 38
; XENIX CALLS
; Directory Group
short_addr $MKDIR ; 57 39
short_addr $RMDIR ; 58 3A
short_addr $CHDIR ; 59 3B
; File Group
short_addr $CREAT ; 60 3C
short_addr $OPEN ; 61 3D
short_addr $CLOSE ; 62 3E
short_addr $READ ; 63 3F
short_addr $WRITE ; 64 40
short_addr $UNLINK ; 65 41
short_addr $LSEEK ; 66 42
short_addr $CHMOD ; 67 43
short_addr $IOCTL ; 68 44
short_addr $DUP ; 69 45
short_addr $DUP2 ; 70 46
short_addr $CURRENT_DIR ; 71 47
; Memory Group
short_addr $ALLOC ; 72 48
short_addr $DEALLOC ; 73 49
short_addr $SETBLOCK ; 74 4A
; Process Group
short_addr $EXEC ; 75 4B
short_addr $EXIT ; 76 4C
short_addr $WAIT ; 77 4D
short_addr $FIND_FIRST ; 78 4E
; Special Group
short_addr $FIND_NEXT ; 79 4F
; SPECIAL SYSTEM GROUP
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
short_addr $SET_CURRENT_PDB ; 80 50
short_addr $GET_CURRENT_PDB ; 81 51
short_addr $GET_IN_VARS ; 82 52
short_addr $SETDPB ; 83 53
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
short_addr $GET_VERIFY_ON_WRITE ; 84 54
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
; C A V E A T P R O G R A M M E R ;
; ;
short_addr $DUP_PDB ; 85 55
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
short_addr $RENAME ; 86 56
short_addr $FILE_TIMES ; 87 57
short_addr $AllocOper ; 88 58
MAXCOM = ($-DISPATCH)/2 - 1
CPMFUNC:
XOR AL,AL
return
IF NOT IBM
BREAK <Set_OEM_Handler -- Set OEM sys call address and handle OEM Calls>
$SET_OEM_HANDLER:
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; User registers, User Stack, INTS disabled
; If CALL F8, DS:DX is new handler address
; Function:
; Process OEM INT 21 extensions
; Outputs:
; Jumps to OEM_HANDLER if appropriate
JNE DO_OEM_FUNC ; If above F8 try to jump to handler
MOV WORD PTR [OEM_HANDLER],DX ; Set Handler
MOV WORD PTR [OEM_HANDLER+2],DS
IRET ; Quick return, Have altered no registers
DO_OEM_FUNC:
CMP WORD PTR [OEM_HANDLER],-1
JNZ OEM_JMP
JMP BADCALL ; Handler not initialized
OEM_JMP:
JMP [OEM_HANDLER]
ENDIF
ASSUME SS:DOSGROUP
;
; $Set_current_PDB takes BX and sets it to be the current process
; *** THIS FUNCTION CALL IS SUBJECT TO CHANGE!!! ***
;
procedure $SET_CURRENT_PDB,NEAR
ASSUME DS:NOTHING,SS:NOTHING
MOV [CurrentPDB],BX
return
$SET_CURRENT_PDB ENDP
;
; $get_current_PDB returns in BX the current process
; *** THIS FUNCTION CALL IS SUBJECT TO CHANGE!!! ***
;
procedure $GET_CURRENT_PDB,NEAR
ASSUME DS:NOTHING,SS:NOTHING
invoke get_user_stack
PUSH [CurrentPDB]
POP [SI.user_BX]
return
$GET_CURRENT_PDB ENDP
; ;
; C A V E A T P R O G R A M M E R ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
BREAK <NullDev -- Driver for null device>
procedure SNULDEV,FAR
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
MOV WORD PTR [NULLDEVPT],BX
MOV WORD PTR [NULLDEVPT+2],ES
return
SNULDEV ENDP
procedure INULDEV,FAR
PUSH ES
PUSH BX
LES BX,[NULLDEVPT]
OR ES:[BX.REQSTAT],STDON ; Set done bit
POP BX
POP ES
return
INULDEV ENDP
BREAK <AbsDRD, AbsDWRT -- INT int_disk_read, int_disk_write handlers>>
IF IBM
ERRIN: ; Codes returned by BIOS
DB 2 ; NO RESPONSE
DB 6 ; SEEK FAILURE
DB 12 ; GENERAL ERROR
DB 4 ; BAD CRC
DB 8 ; SECTOR NOT FOUND
DB 0 ; WRITE ATTEMPT ON WRITE-PROTECT DISK
ERROUT: ; DISK ERRORS RETURNED FROM INT 25 and 26
DB 80H ; NO RESPONSE
DB 40H ; Seek failure
DB 2 ; Address Mark not found
DB 8 ; DMA OVERRUN
DB 4 ; SECTOR NOT FOUND
DB 3 ; WRITE ATTEMPT TO WRITE-PROTECT DISK
NUMERR EQU $-ERROUT
ENDIF
procedure ABSDRD,FAR
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
CLI
MOV [user_SS],SS
MOV [user_SP],SP
PUSH CS
POP SS
ASSUME SS:DOSGROUP
MOV SP,OFFSET DOSGROUP:DSKSTACK
INC BYTE PTR [INDOS]
STI
CLD
PUSH ES
PUSH DS
PUSH SS
POP DS
ASSUME DS:DOSGROUP
invoke GETBP
POP DS
ASSUME DS:NOTHING
JC ILEAVE
invoke DSKREAD
TLEAVE:
JZ ILEAVE
IF IBM
; Translate the error code to ancient 1.1 codes
PUSH ES
PUSH CS
POP ES
XOR AH,AH ; Nul error code
MOV CX,NUMERR ; Number of possible error conditions
MOV DI,OFFSET DOSGROUP:ERRIN ; Point to error conditions
REPNE SCASB
JNZ LEAVECODE ; Not found
MOV AH,ES:[DI+NUMERR-1] ; Get translation
LEAVECODE:
POP ES
ENDIF
STC
ILEAVE:
POP ES
CLI
DEC BYTE PTR [INDOS]
MOV SP,[user_SP]
MOV SS,[user_SS]
ASSUME SS:NOTHING
STI
return
ABSDRD ENDP
procedure ABSDWRT,FAR
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
CLI
MOV [user_SS],SS
MOV [user_SP],SP
PUSH CS
POP SS
ASSUME SS:DOSGROUP
MOV SP,OFFSET DOSGROUP:DSKSTACK
INC BYTE PTR [INDOS]
STI
CLD
PUSH ES
PUSH DS
PUSH SS
POP DS
ASSUME DS:DOSGROUP
invoke GETBP
POP DS
ASSUME DS:NOTHING
JC ILEAVE
invoke DSKWRITE
JMP TLEAVE
ABSDWRT ENDP
procedure SYS_RETURN,NEAR
ASSUME DS:NOTHING,ES:NOTHING
entry SYS_RET_OK
call get_user_stack
PUSH [SI.user_F]
POPF
CLC
JMP SHORT DO_RET
entry SYS_RET_ERR
XOR AH,AH ; hack to allow for smaller error rets
call get_user_stack
PUSH [SI.user_F]
POPF
STC
DO_RET:
MOV [SI.user_AX],AX ; Really only sets AH
PUSHF
POP [SI.user_F] ; dump on his flags
return
SYS_RETURN ENDP
do_ext
CODE ENDS
END

+342
View File
@@ -0,0 +1,342 @@
SUBTTL Initialized data and data used at DOS initialization
PAGE
; DATA AREA for MS-DOS
IFNDEF KANJI
KANJI EQU 0 ;FALSE
ENDIF
CONSTANTS SEGMENT BYTE PUBLIC 'CONST'
EXTRN international_table:BYTE
EXTRN Current_Country:WORD
ORG 0
CONSTRT EQU $ ; Start of constants segment
PUBLIC DevStrLen
DEVSTRLEN DB 3 ; Size of below
PUBLIC DevString
DEVSTRING DB "DEV" ; Dummy device directory
;
; Table of routines for assignable devices
;
; MSDOS allows assignment if the following standard devices:
; stdin (usually CON input)
; stdout (usually CON output)
; auxin (usually AUX input)
; auxout (usually AUX output)
; stdlpt (usually PRN output)
;
; SPECIAL NOTE:
; Status of a file is a strange idea. We choose to handle it in this manner:
; If we're not at end-of-file, then we always say that we have a character.
; Otherwise, we return ^Z as the character and set the ZERO flag. In this
; manner we can support program written under the old DOS (they use ^Z as EOF
; on devices) and programs written under the new DOS (they use the ZERO flag
; as EOF).
; Default FCBs for boot up
sftabl LABEL DWORD ; file table
DW -1
DW -1
DW sf_default_number ; Number of entries in table
DB sf_default_number DUP ( (SIZE sf_entry) DUP (0))
I_AM NoSetDir,BYTE ; true -> do not set directory
I_am DidCTRLC,BYTE ; true -> we did a ^C exit
I_am SpaceFlag,BYTE ; true -> embedded spaces are allowed
; in FCB
; the next two variables relate to the position of the logical stdout/stdin
; cursor. They are only meaningful when stdin/stdout are assigned to the
; console.
i_am CARPOS,BYTE ; cursor position in stdin
i_am STARTPOS,BYTE ; position of cursor at beginning
; of buffered input call
I_AM PFLAG,BYTE
I_AM VERFLG,BYTE ; Initialize with verify off
I_AM CONTPOS,WORD
PUBLIC CHARCO
CHARCO DB 00000011B ; Allows statchks every 4 chars...
I_AM DMAADD,DWORD ; User's disk transfer address
; (disp/seg)
ORG $-CONSTRT-4
DW 80H
DW ?
ENDMEM DW ?
PUBLIC switch_character
switch_character DB '/'
PUBLIC device_availability
device_availability DB 0FFH
I_AM FirstArena,WORD ; first free block found
I_AM BestArena,WORD ; best free block found
I_AM LastArena,WORD ; last free block found
I_AM AllocMethod,BYTE ; how to alloc first(best)last
I_AM arena_head,WORD
; The following block of data is used by SYSINIT. Do not change the order or
; size of this block
PUBLIC SYSINITVAR
SYSINITVAR LABEL WORD
I_AM DPBHEAD,DWORD ; Pointer to head of DPB-FAT list
I_AM sft_addr,DWORD ; Pointer to first FCB table
ORG $-CONSTRT-4
short_addr sftabl
DW ? ; DOS segment set at INIT
; The following address points to the CLOCK device
i_am BCLOCK,DWORD
; The following address is used by DISKSTATCHK it is always points to the
; console input device header
I_AM BCON,DWORD ; Console device entry points
i_am NUMIO,BYTE ; Number of disk tables
MAXSEC DW 0 ; Maximum allowed sector size
I_AM BUFFHEAD,DWORD ; Pointer to head of buffer queue
DEVHEAD LABEL DWORD
I_AM NULDEV,DWORD ; Set to list start passed by
; BIOS at DOS Init
DW DEVTYP OR ISNULL
short_addr SNULDEV
short_addr INULDEV
DB "NUL "
i_am DAY,BYTE
i_am MONTH,BYTE
i_am YEAR,WORD
i_am DAYCNT,WORD
i_am WEEKDAY,BYTE
ORG $-CONSTRT-7
DB 0,0
DW 0,-1
DB 0
I_AM CURDRV,BYTE ; Default to drive A
I_AM LASTENT,WORD
i_am INDOS,BYTE ; DOS status for interrupt processing
ORG $-CONSTRT-1
DB 0
I_AM ErrorMode,BYTE ; Flag for INT 24 processing
PUBLIC WPErr
WPERR DB -1 ; Write protect error flag
I_AM CONSWAP,BYTE
PUBLIC IDLEINT
IDLEINT DB 1
PUBLIC CNTCFLAG
CNTCFLAG DB 0 ; ^C check in dispatch disabled
PUBLIC LastBuffer
LASTBUFFER LABEL DWORD ; Buffer queue recency pointer
DW -1
DW -1
; Combination of all device call parameters
PUBLIC DEVCALL
DEVCALL SRHEAD <>
CALLUNIT LABEL BYTE
CALLFLSH LABEL WORD
I_AM CALLMED,BYTE
CALLBR LABEL DWORD
PUBLIC CALLXAD
CALLXAD LABEL DWORD
I_AM CALLRBYT,BYTE
DB 3 DUP(?)
PUBLIC CallBPB
CALLBPB LABEL DWORD
I_AM CALLSCNT,WORD
CALLSSEC DW ?
I_AM CALLDEVAD,DWORD ; stash for device entry point
; Same as above for I/O calls
PUBLIC IOCall
IOCALL SRHEAD <>
IOFLSH LABEL WORD
PUBLIC IORCHR
IORCHR LABEL BYTE
I_AM IOMED,BYTE
I_AM IOXAD,DWORD
I_AM IOSCNT,WORD
I_AM IOSSEC,WORD
; Call struct for DSKSTATCHK
PUBLIC DSKSTCALL
DSKSTCALL DB DRDNDHL
DB 0
PUBLIC DSKSTCOM
DSKSTCOM DB DEVRDND
I_AM DSKSTST,WORD
DB 8 DUP (0)
I_AM DSKCHRET,BYTE
short_addr DEVIOBUF
DW ? ; DOS segment set at Init
PUBLIC DSKSTCNT
DSKSTCNT DW 1
DW 0
; Days in year
i_am YRTAB,8
ORG $-CONSTRT-8
DB 200,166 ; Leap year
DB 200,165
DB 200,165
DB 200,165
; Days of each month
i_am MONTAB,12
ORG $-CONSTRT-12
DB 31 ; January
DB 28 ; February--reset each
; time year changes
DB 31 ; March
DB 30 ; April
DB 31 ; May
DB 30 ; June
DB 31 ; July
DB 31 ; August
DB 30 ; September
DB 31 ; October
DB 30 ; November
DB 31 ; December
IF NOT IBM
PUBLIC OEM_HANDLER
OEM_HANDLER DD -1
ENDIF
;WARNING For HIGHMEM version, these two vars must be at the end of the
; Constants segment to prevent them getting overwritten.
I_AM CurrentPDB,WORD
i_am CreatePDB,BYTE ; flag for creating a process
PUBLIC LEAVEADDR
LEAVEADDR LABEL WORD
short_addr LEAVE
CONSTANTS ENDS
SUBTTL Uninitialized data overlayed by initialization code
PAGE
DATA SEGMENT WORD PUBLIC 'DATA'
; Init code overlaps with data area below
ORG 0
i_am INBUF,128
I_AM CONBUF,131 ; The rest of INBUF and console buffer
i_am TIMEBUF,6
I_AM DEVIOBUF,2 ; Buffer for I/O under file assignment
I_AM EXITHOLD,DWORD
PUBLIC DevFCB
DEVFCB LABEL BYTE ; Uses NAME1, NAME2, NAME3 combined
; WARNING.. do not alter size or relative location of the following 4 items
; without first examining FCB_RENAME
I_AM NAME1,12 ; File name buffer
I_AM ATTRIB,BYTE
I_AM NAME2,13
I_AM NAME3,14
I_AM EXTFCB,BYTE
; WARNING - the following two items are accessed as a word
I_AM CREATING,BYTE
I_AM DELALL,BYTE
I_AM FoundDel,BYTE
I_AM user_SP,WORD
I_AM user_SS,WORD
I_AM CONTSTK,WORD
I_AM SECCLUSPOS,BYTE ; Position of first sector
; within cluster
I_AM DSKERR,BYTE
I_AM TRANS,BYTE
I_AM READOP,BYTE
I_AM THISDRV,BYTE
I_AM THISDPB,DWORD
I_AM CLUSFAC,BYTE
; WARNING - the following two items are accessed as a word
I_AM DRIVESPEC,BYTE
I_AM ROOTSTART,BYTE
I_AM CLUSSPLIT,BYTE
i_am INSMODE,BYTE
I_AM CLUSSAVE,WORD
I_AM CLUSSEC,WORD
I_AM PREREAD,WORD ; 0 means preread; 1 means optional
I_AM FATBYT,WORD
I_AM DEVPT,DWORD
I_AM THISFCB,DWORD ; Address of user FCB
I_AM NEXTADD,WORD
I_AM RECPOS,4
I_AM RECCNT,WORD
I_AM LASTPOS,WORD
I_AM CLUSNUM,WORD
I_AM DIRSEC,WORD
I_AM DIRSTART,WORD
I_AM SECPOS,WORD ; Position of first sector accessed
I_AM VALSEC,WORD ; Number of valid (previously written)
; sectors
I_AM BYTSECPOS,WORD ; Position of first byte within sector
I_AM BYTPOS,4 ; Byte position in file of access
I_AM BYTCNT1,WORD ; No. of bytes in first sector
I_AM BYTCNT2,WORD ; No. of bytes in last sector
I_AM SECCNT,WORD ; No. of whole sectors
I_AM ENTFREE,WORD
I_AM ENTLAST,WORD
I_AM NXTCLUSNUM,WORD
I_AM GROWCNT,DWORD
I_AM CURBUF,DWORD
I_AM VOLID,BYTE
I_AM NULLDEVPT,DWORD
I_AM CINSAV,DWORD
I_AM CINDSAV,BYTE
I_AM COUTDSAV,BYTE
I_AM COUTSAV,DWORD
PUBLIC SaveBX
SaveBX DW ?
PUBLIC SaveDS
SaveDS DW ?
I_AM ConC_spsave,WORD
I_AM exit_code,WORD ; exit code of last proc.
I_am exit_type,BYTE ; type of exit...
IF IBM
;For 2.00 this pads the DOS so that on a 2 disk IBM PC with no
;CONFIG.SYS file the space taken up by BIOS, DOS, res COMMAND is
;about 24K
IBMPAD DB 540h DUP(?)
ENDIF
; make those pushes fast!!!
EVEN
DB 0A0H DUP (?)
I_am AuxStack,0A0h
I_AM DSKSTACK,0A0h ; Stack space
PUBLIC IOSTACK
IOSTACK LABEL BYTE
PUBLIC NSS
NSS DW ?
PUBLIC NSP
NSP DW ?
PAGE
INCLUDE MSINIT.ASM

+12
View File
@@ -0,0 +1,12 @@
TITLE Standard MSDOS
NAME MSDOS_2
; Number of disk I/O buffers
INCLUDE STDSW.ASM
INCLUDE MSHEAD.ASM
INCLUDE MSDATA.ASM
END

+198
View File
@@ -0,0 +1,198 @@
; TITLE MSHEAD.ASM -- MS-DOS DEFINITIONS
PAGE
; MS-DOS High-performance operating system for the 8086 version 1.28
; by Microsoft MSDOS development group:
; Tim Paterson (Ret.)
; Aaron Reynolds
; Nancy Panners (Parenting)
; Mark Zbikowski
; Chris Peters (BIOS) (ret.)
; ****************** Revision History *************************
; >> EVERY change must noted below!! <<
;
; 0.34 12/29/80 General release, updating all past customers
; 0.42 02/25/81 32-byte directory entries added
; 0.56 03/23/81 Variable record and sector sizes
; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack
; 0.74 04/15/81 Recognize I/O devices with file names
; 0.75 04/17/81 Improve and correct buffer handling
; 0.76 04/23/81 Correct directory size when not 2^N entries
; 0.80 04/27/81 Add console input without echo, Functions 7 & 8
; 1.00 04/28/81 Renumber for general release
; 1.01 05/12/81 Fix bug in `STORE'
; 1.10 07/21/81 Fatal error trapping, NUL device, hidden files, date & time,
; RENAME fix, general cleanup
; 1.11 09/03/81 Don't set CURRENT BLOCK to 0 on open; fix SET FILE SIZE
; 1.12 10/09/81 Zero high half of CURRENT BLOCK after all (CP/M programs don't)
; 1.13 10/29/81 Fix classic "no write-through" error in buffer handling
; 1.20 12/31/81 Add time to FCB; separate FAT from DPT; Kill SMALLDIR; Add
; FLUSH and MAPDEV calls; allow disk mapping in DSKCHG; Lots
; of smaller improvements
; 1.21 01/06/82 HIGHMEM switch to run DOS in high memory
; 1.22 01/12/82 Add VERIFY system call to enable/disable verify after write
; 1.23 02/11/82 Add defaulting to parser; use variable escape character Don't
; zero extent field in IBM version (back to 1.01!)
; 1.24 03/01/82 Restore fcn. 27 to 1.0 level; add fcn. 28
; 1.25 03/03/82 Put marker (00) at end of directory to speed searches
; 1.26 03/03/82 Directory buffers searched as a circular queue, current buffer
; is searched first when possible to minimize I/O
; 03/03/82 STORE routine optimized to tack on partial sector tail as
; full sector write when file is growing
; 03/09/82 Multiple I/O buffers
; 03/29/82 Two bugs: Delete all case resets search to start at beginning
; of directory (infinite loop possible otherwise), DSKRESET
; must invalidate all buffers (disk and directory).
; 1.27 03/31/82 Installable device drivers
; Function call 47 - Get pointer to device table list
; Function call 48 - Assign CON AUX LIST
; 04/01/82 Spooler interrupt (INT 28) added.
; 1.28 04/15/82 DOS retructured to use ASSUMEs and PROC labels around system
; call entries. Most CS relative references changed to SS
; relative with an eye toward putting a portion of the DOS in
; ROM. DOS source also broken into header, data and code pieces
; 04/15/82 GETDMA and GETVECT calls added as 24 and 32. These calls
; return the current values.
; 04/15/82 INDOS flag implemented for interrupt processing along with
; call to return flag location (call 29)
; 04/15/82 Volume ID attribute added
; 04/17/82 Changed ABORT return to user to a long ret from a long jump to
; avoid a CS relative reference.
; 04/17/82 Put call to STATCHK in dispatcher to catch ^C more often
; 04/20/82 Added INT int_upooler into loop ^S wait
; 04/22/82 Dynamic disk I/O buffer allocation and call to manage them
; call 49.
; 04/23/82 Added GETDSKPTDL as call 50, similar to GETFATPT(DL), returns
; address of DPB
; 04/29/82 Mod to WRTDEV to look for ^C or ^S at console input when
; writting to console device via file I/O. Added a console
; output attribute to devices.
; 04/30/82 Call to en/dis able ^C check in dispatcher Call 51
; 04/30/82 Code to allow assignment of func 1-12 to disk files as well
; as devices.... pipes, redirection now possible
; 04/30/82 Expanded GETLIST call to 2.0 standard
; 05/04/82 Change to INT int_fatal_abort callout int HARDERR. DOS SS
; (data segment) stashed in ES, INT int_fatal_abort routines must
; preserve ES. This mod so HARDERR can be ROMed.
; 1.29 06/01/82 Installable block and character devices as per 2.0 spec
; 06/04/82 Fixed Bug in CLOSE regarding call to CHKFATWRT. It got left
; out back about 1.27 or so (oops). ARR
; 1.30 06/07/82 Directory sector buffering added to main DOS buffer queue
; 1.40 06/15/82 Tree structured directories. XENIX Path Parser MKDIR CHDIR
; RMDIR Xenix calls
; 1.41 06/13/82 Made GETBUFFR call PLACEBUF
; 1.50 06/17/82 FATs cached in buffer pool, get FAT pointer calls disappear
; Frees up lots of memory.
; 1.51 06/24/82 BREAKDOWN modified to do EXACT one sector read/write through
; system buffers
; 1.52 06/30/82 OPEN, CLOSE, READ, WRITE, DUP, DUP2, LSEEK implemented
; 1.53 07/01/82 OPEN CLOSE mod for Xenix calls, saves and gets remote dir
; 1.54 07/11/82 Function calls 1-12 make use of new 2.0 PDB. Init code
; changed to set file handle environment.
; 2.00 08/01/82 Number for IBM release
; 01/19/83 No environ bug in EXEC
; 01/19/83 MS-DOS OEM INT 21 extensions (SET_OEM_HANDLER)
; 01/19/83 Performance bug fix in cooked write to NUL
; 01/27/83 Growcnt fixed for 32-bits
; 01/27/83 Find-first problem after create
; 2.01 02/17/83 International DOS
; 2.11 08/12/83 Dos split into several more modules for assembly on
; an IBM PC
;
; *************************************************************
SUBTTL EQUATES
PAGE
; Interrupt Entry Points:
; INTBASE: ABORT
; INTBASE+4: COMMAND
; INTBASE+8: BASE EXIT ADDRESS
; INTBASE+C: CONTROL-C ABORT
; INTBASE+10H: FATAL ERROR ABORT
; INTBASE+14H: BIOS DISK READ
; INTBASE+18H: BIOS DISK WRITE
; INTBASE+1CH: END BUT STAY RESIDENT (NOT SET BY DOS)
; INTBASE+20H: SPOOLER INTERRUPT
; INTBASE+40H: Long jump to CALL entry point
ENTRYPOINTSEG EQU 0CH
MAXDIF EQU 0FFFH
SAVEXIT EQU 10
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
SUBTTL ^C, terminate/abort/exit and Hard error actions
PAGE
;
; There are three kinds of context resets that can occur during normal DOS
; functioning: ^C trap, terminate/abort/exit, and Hard-disk error. These must
; be handles in a clean fashion that allows nested executions along with the
; ability to trap one's own errors.
;
; ^C trap - A process may elect to catch his own ^Cs. This is achieved by
; using the $GET_INTERRUPT_VECTOR and $SET_INTERRUPT_VECTOR as
; follows:
;
; $GET_INTERRUPT_VECTOR for INT int_ctrl_c
; Save it in static memory.
; $SET_INTERRUPT_VECTOR for INT int_ctrl_c
;
; The interrupt service routine must preserve all registers and
; return carry set iff the operation is to be aborted (via abort
; system call), otherwise, carry is reset and the operation is
; restarted. ANY DEVIATION FROM THIS WILL LEAD TO UNRELIABLE
; RESULTS.
;
; To restore original ^C processing (done on terminate/abort/exit),
; restore INT int_ctrl_c from the saved vector.
;
; Hard-disk error -- The interrupt service routine for INT int_fatal_abort must
; also preserve registers and return one of three values in AL: 0 and
; 1 imply retry and ignore (???) and 2 indicates an abort. The user
; himself is not to issue the abort, rather, the dos will do it for
; him by simulating a normal abort/exit system call. ANY DEVIATION
; FROM THIS WILL LEAD TO UNRELIABLE RESULTS.
;
; terminate/abort/exit -- The user may not, under any circumstances trap an
; abort call. This is reserved for knowledgeable system programs.
; ANY DEVIATION FROM THIS WILL LEAD TO UNRELIABLE RESULTS.
SUBTTL SEGMENT DECLARATIONS
PAGE
; The following are all of the segments used. They are declared in the order
; that they should be placed in the executable
;
; segment ordering for MSDOS
;
START SEGMENT BYTE PUBLIC 'START'
START ENDS
CONSTANTS SEGMENT BYTE PUBLIC 'CONST'
CONSTANTS ENDS
DATA SEGMENT WORD PUBLIC 'DATA'
DATA ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
CODE ENDS
LAST SEGMENT BYTE PUBLIC 'LAST'
LAST ENDS
DOSGROUP GROUP CODE,CONSTANTS,DATA,LAST
; The following segment is defined such that the data/const classes appear
; before the code class for ROMification
START SEGMENT BYTE PUBLIC 'START'
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
JMP DOSINIT
START ENDS

+408
View File
@@ -0,0 +1,408 @@
; TITLE MSINIT.ASM -- MS-DOS INITIALIZATION CODE
ORG 0 ; reset to beginning of data segment
; Init code below overlaps with data area
INITBLOCK DB 110H DUP(0) ; Allow for segment round up
INITSP DW ?
INITSS DW ?
BUFFSTRT DW ?
ASSUME CS:DOSGROUP,DS:DOSGROUP,ES:DOSGROUP,SS:NOTHING
EXTRN QUIT:NEAR,IRET:NEAR,ABSDRD:FAR,ABSDWRT:FAR
EXTRN COMMAND:NEAR,CALL_ENTRY:NEAR
IF NOT IBM
EXTRN HEADER:BYTE
ENDIF
MOVDPB:
; This section of code is safe from being overwritten by block move
MOV SP,CS:[INITSP]
MOV SS,CS:[INITSS]
REP MOVS BYTE PTR [DI],[SI]
CLD
MOV WORD PTR ES:[DMAADD+2],DX
MOV SI,WORD PTR [DPBHEAD] ; Address of first DPB
MOV WORD PTR ES:[DPBHEAD+2],ES
MOV WORD PTR ES:[sft_addr+2],ES
MOV CL,[NUMIO] ; Number of DPBs
XOR CH,CH
SETFINDPB:
MOV WORD PTR ES:[SI.dpb_next_dpb+2],ES
MOV ES:[SI.dpb_first_access],-1 ; Never accessed before
ADD SI,DPBSIZ ; Point to next DPB
LOOP SETFINDPB
SUB SI,DPBSIZ
MOV WORD PTR ES:[SI.dpb_next_dpb+2],-1
MOV DI,[BUFFSTRT] ; Set up one default buffer
MOV WORD PTR ES:[BUFFHEAD+2],ES
MOV WORD PTR ES:[BUFFHEAD],DI
MOV WORD PTR ES:[DI.BUFDRV],00FFH
MOV ES:[DI.BUFPRI],FREEPRI
MOV WORD PTR ES:[DI.NEXTBUF],-1
MOV WORD PTR ES:[DI.NEXTBUF+2],-1
PUSH ES
INC DX ; Leave enough room for the ARENA
MOV BYTE PTR [CreatePDB],0FFh ; create jfns and set CurrentPDB
invoke $CREATE_PROCESS_DATA_BLOCK ; Set up segment
ASSUME DS:NOTHING,ES:NOTHING
POP ES
ASSUME ES:DOSGROUP
;
; set up memory arena
;SPECIAL NOTE FOR HIGHMEM VERSION
; At this point a process header has been built where the start of the
; CONSTANTS segment as refed by CS is. From this point until the return
; below be careful about references off of CS.
;
PUSH AX
MOV AX,[CurrentPDB]
MOV ES:[CurrentPDB],AX ; Put it in the REAL location
MOV BYTE PTR ES:[CreatePDB],0h ; reset flag in REAL location
DEC AX
MOV ES:[arena_head],AX
PUSH DS
MOV DS,AX
MOV DS:[arena_signature],arena_signature_end
MOV DS:[arena_owner],arena_owner_system
SUB AX,ES:[ENDMEM]
NEG AX
DEC AX
MOV DS:[arena_size],AX
POP DS
POP AX
MOV DI,OFFSET DOSGROUP:sftabl + sft_table ; Point to sft 0
MOV AL,3
STOSB ; Adjust Refcount
MOV DI,OFFSET DOSGROUP:SYSINITVAR
XXX PROC FAR
RET
XXX ENDP
DATA ENDS
; the next segment defines a new class that MUST appear last in the link map.
; This defines several important locations for the initialization process that
; must be the first available locations of free memory.
LAST SEGMENT BYTE PUBLIC 'LAST'
PUBLIC SYSBUF
PUBLIC MEMSTRT
SYSBUF LABEL WORD
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
DOSINIT:
CLI
CLD
MOV [ENDMEM],DX
MOV [INITSP],SP
MOV [INITSS],SS
MOV SP,OFFSET DOSGROUP:INITSTACK
MOV AX,CS
MOV SS,AX
ASSUME SS:DOSGROUP
MOV WORD PTR [DEVHEAD+2],DS
MOV WORD PTR [DEVHEAD],SI ; DS:SI Points to CONSOLE Device
CALL CHARINIT
PUSH SI
ADD SI,SDEVNAME ; Point to name
PUSH CS
POP ES
ASSUME ES:DOSGROUP
MOV DI,OFFSET DOSGROUP:sftabl + sft_table ; Point to sft 0
MOV AL,3
STOSB ; Refcount
DEC AL
STOSB ; Access rd/wr
XOR AL,AL
STOSB ; Drive byte
STOSB ; attribute
MOV CX,4
REP MOVSW ; Name
MOV CL,3
MOV AL," "
REP STOSB ; Extension
ADD DI,12 ; Skip
MOV AL,0C0H OR ISCIN OR ISCOUT
STOSB
POP SI
MOV AX,SI
STOSW ; Device pointer in FIRCLUS
MOV AX,DS
STOSW
OR BYTE PTR [SI.SDEVATT],ISCIN OR ISCOUT
MOV WORD PTR [BCON],SI
MOV WORD PTR [BCON+2],DS
CHAR_INIT_LOOP:
LDS SI,DWORD PTR [SI] ; AUX device
CALL CHARINIT
TEST BYTE PTR [SI.SDEVATT],ISCLOCK
JZ CHAR_INIT_LOOP
MOV WORD PTR [BCLOCK],SI
MOV WORD PTR [BCLOCK+2],DS
MOV BP,OFFSET DOSGROUP:MEMSTRT ; ES:BP points to DPB
PERDRV:
LDS SI,DWORD PTR [SI] ; Next device
CMP SI,-1
JZ CONTINIT
CALL CHARINIT
TEST [SI.SDEVATT],DEVTYP
JNZ PERDRV ; Skip any other character devs
MOV CL,[CALLUNIT]
XOR CH,CH
MOV [SI.SDEVNAME],CL ; Number of units in name field
MOV DL,[NUMIO]
XOR DH,DH
ADD [NUMIO],CL
PUSH DS
PUSH SI
LDS BX,[CALLBPB]
PERUNIT:
MOV SI,[BX] ; DS:SI Points to BPB
INC BX
INC BX ; On to next BPB
MOV ES:[BP.dpb_drive],DL
MOV ES:[BP.dpb_UNIT],DH
PUSH BX
PUSH CX
PUSH DX
invoke $SETDPB
MOV AX,ES:[BP.dpb_sector_size]
CMP AX,[MAXSEC]
JBE NOTMAX
MOV [MAXSEC],AX
NOTMAX:
POP DX
POP CX
POP BX
MOV AX,DS ; Save DS
POP SI
POP DS
MOV WORD PTR ES:[BP.dpb_driver_addr],SI
MOV WORD PTR ES:[BP.dpb_driver_addr+2],DS
PUSH DS
PUSH SI
INC DH
INC DL
MOV DS,AX
ADD BP,DPBSIZ
LOOP PERUNIT
POP SI
POP DS
JMP PERDRV
CONTINIT:
PUSH CS
POP DS
ASSUME DS:DOSGROUP
; Calculate true address of buffers, FATs, free space
MOV DI,BP ; First byte after current DPBs
MOV BP,[MAXSEC]
MOV AX,OFFSET DOSGROUP:SYSBUF
MOV [BUFFSTRT],AX
ADD AX,BP ; One I/O buffer
ADD AX,BUFINSIZ
MOV WORD PTR [DPBHEAD],AX ; True start of DPBs
MOV DX,AX
SUB DX,OFFSET DOSGROUP:SYSBUF
MOV BP,DX
ADD BP,DI ; Allocate buffer space
SUB BP,ADJFAC ; True address of free memory
PUSH BP
MOV DI,OFFSET DOSGROUP:MEMSTRT ; Current start of DPBs
ADD DI,dpb_next_dpb ; Point at dpb_next_dpb field
MOV CL,[NUMIO]
XOR CH,CH
TRUEDPBAD:
ADD AX,DPBSIZ ; Compute address of next DPB
STOSW ; Set the link to next DPB
ADD DI,DPBSIZ-2 ; Point at next address
LOOP TRUEDPBAD
SUB DI,DPBSIZ ; Point at last dpb_next_dpb field
MOV AX,-1
STOSW ; End of list
ADD BP,15 ;True start of free space (round up to segment)
MOV CL,4
SHR BP,CL ; Number of segments for DOS resources
MOV DX,CS
ADD DX,BP ; First free segment
MOV BX,0FH
MOV CX,[ENDMEM]
IF HIGHMEM
SUB CX,BP
MOV BP,CX ; Segment of DOS
MOV DX,CS ; Program segment
ENDIF
IF NOT HIGHMEM
MOV BP,CS
ENDIF
; BP has segment of DOS (whether to load high or run in place)
; DX has program segment (whether after DOS or overlaying DOS)
; CX has size of memory in paragraphs (reduced by DOS size if HIGHMEM)
MOV [ENDMEM],CX
MOV ES,BP
ASSUME ES:DOSGROUP
IF HIGHMEM
XOR SI,SI
MOV DI,SI
MOV CX,OFFSET DOSGROUP:SYSBUF ;# bytes to move
SHR CX,1 ;# words to move (carry set if odd)
REP MOVSW ; Move DOS to high memory
JNC NOTODD
MOVSB
NOTODD:
ENDIF
MOV WORD PTR ES:[DSKCHRET+3],ES
XOR AX,AX
MOV DS,AX
MOV ES,AX
ASSUME DS:NOTHING,ES:NOTHING
MOV DI,INTBASE+2
MOV AX,BP
MOV BYTE PTR DS:[ENTRYPOINT],mi_Long_JMP
MOV WORD PTR DS:[ENTRYPOINT+1],OFFSET DOSGROUP:CALL_ENTRY
MOV WORD PTR DS:[ENTRYPOINT+3],AX
EXTRN DIVOV:near
MOV WORD PTR DS:[0],OFFSET DOSGROUP:DIVOV ; Set default divide
; trap address
MOV DS:[2],AX
MOV CX,17
REP STOSW ; Set 9 segments (skip 2 between each)
IF ALTVECT
MOV DI,ALTBASE+2
MOV CX,15
REP STOSW ; Set 8 segments (skip 2 between each)
ENDIF
MOV WORD PTR DS:[addr_int_abort],OFFSET DOSGROUP:QUIT
MOV WORD PTR DS:[addr_int_command],OFFSET DOSGROUP:COMMAND
MOV WORD PTR DS:[addr_int_terminate],100H
MOV WORD PTR DS:[addr_int_terminate+2],DX
MOV WORD PTR DS:[addr_int_ctrl_c],OFFSET DOSGROUP:IRET
; Ctrl-C exit
MOV WORD PTR DS:[addr_int_fatal_abort],OFFSET DOSGROUP:IRET
; Fatal error exit
MOV WORD PTR DS:[addr_int_disk_read],OFFSET DOSGROUP:ABSDRD
; INT 25
MOV WORD PTR DS:[addr_int_disk_write],OFFSET DOSGROUP:ABSDWRT
; INT 26
EXTRN Stay_resident:NEAR
MOV WORD PTR DS:[addr_int_keep_process],OFFSET DOSGROUP:Stay_resident
MOV WORD PTR DS:[addr_int_spooler],OFFSET DOSGROUP:IRET ; Spooler
IF NOT ALTVECT
MOV CX,12
XOR AX,AX
MOV DI,2AH*4
REP STOSW ;Zero interrupt locs for ints 2AH-2FH
ENDIF
PUSH CS
POP DS
PUSH CS
POP ES
ASSUME DS:DOSGROUP,ES:DOSGROUP
MOV AX,OFFSET DOSGROUP:INITBLOCK
ADD AX,0Fh ; round to a paragraph
MOV CL,4
SHR AX,CL
MOV DI,DS
ADD DI,AX
INC DI
MOV [CurrentPDB],DI
PUSH BP
PUSH DX ; Save COMMAND address
MOV AX,[ENDMEM]
MOV DX,DI
invoke SETMEM ; Basic Header
ASSUME DS:NOTHING,ES:NOTHING
PUSH CS
POP DS
ASSUME DS:DOSGROUP
MOV DI,PDB_JFN_Table
XOR AX,AX
STOSW
STOSB ; 0,1 and 2 are CON device
MOV AL,0FFH
MOV CX,FilPerProc - 3
REP STOSB ; Rest are unused
PUSH CS
POP ES
ASSUME ES:DOSGROUP
MOV WORD PTR [sft_addr+2],DS ; Must be set to print messages
; After this points the char device functions for CON will work for
; printing messages
IF NOT IBM
IF NOT ALTVECT
MOV SI,OFFSET DOSGROUP:HEADER
invoke OUTMES
PUSH CS ; Outmes stomps on segments
POP DS
PUSH CS
POP ES
ENDIF
ENDIF
; Move the FATs into position
POP DX ; Restore COMMAND address
POP BP
POP CX ; True address of free memory
MOV SI,OFFSET DOSGROUP:MEMSTRT ; Place to move DPBs from
MOV DI,WORD PTR [DPBHEAD] ; Place to move DPBs to
SUB CX,DI ; Total length of DPBs
CMP DI,SI
JBE MOVJMP ; Are we moving to higher or
; lower memory?
DEC CX ; Move backwards to higher memory
ADD DI,CX
ADD SI,CX
INC CX
STD
MOVJMP:
MOV ES,BP
ASSUME ES:DOSGROUP
JMP MOVDPB
CHARINIT:
ASSUME DS:NOTHING,ES:NOTHING
; DS:SI Points to device header
MOV [DEVCALL.REQLEN],DINITHL
MOV [DEVCALL.REQUNIT],0
MOV [DEVCALL.REQFUNC],DEVINIT
MOV [DEVCALL.REQSTAT],0
PUSH ES
PUSH BX
PUSH AX
MOV BX,OFFSET DOSGROUP:DEVCALL
PUSH CS
POP ES
invoke DEVIOCALL2
POP AX
POP BX
POP ES
RET
DB 80H DUP(?)
INITSTACK LABEL BYTE
DW ?
MEMSTRT LABEL WORD
ADJFAC EQU MEMSTRT-SYSBUF
do_ext
LAST ENDS

+1645
View File
File diff suppressed because it is too large Load Diff
+130
View File
@@ -0,0 +1,130 @@
;
; process control system calls for MSDOS
;
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
i_need CurrentPDB,WORD
i_need CreatePDB,BYTE
i_need NUMIO,BYTE
i_need Exit_type,BYTE
i_need INDOS,BYTE
i_need DMAADD,DWORD
i_need DidCTRLC,BYTE
SUBTTL $WAIT - return previous process error code
PAGE
;
; process control data
;
i_need exit_code,WORD ; code of exit
;
; Assembler usage:
; MOV AH, Wait
; INT int_command
; AX has the exit code
procedure $WAIT,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV AX,[exit_code]
XOR DX,DX
MOV [exit_code],DX
transfer SYS_RET_OK
$WAIT ENDP
IF IBM
procedure $EXEC,NEAR
error error_invalid_function
$EXEC ENDP
ENDIF
IF NOT IBM
INCLUDE EXEC.ASM
ENDIF
SUBTTL Terminate and stay resident handler
PAGE
;
; Input: DX is an offset from CurrentPDB at which to
; truncate the current block.
;
; output: The current block is truncated (expanded) to be [DX+15]/16
; paragraphs long. An exit is simulated via resetting CurrentPDB
; and restoring the vectors.
;
procedure $Keep_process,NEAR
ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
PUSH AX ; keep exit code around
MOV BYTE PTR [Exit_type],Exit_keep_process
MOV ES,[CurrentPDB]
CMP DX,6h ; keep enough space around for system
JAE Keep_shrink ; info
MOV DX,6h
keep_shrink:
MOV BX,DX
PUSH BX
PUSH ES
invoke $SETBLOCK ; ignore return codes.
POP DS
POP BX
JC keep_done ; failed on modification
MOV AX,DS
ADD AX,BX
MOV DS:[PDB_block_len],AX
keep_done:
POP AX
JMP SHORT exit_inner ; and let abort take care of the rest
$Keep_process ENDP
procedure Stay_resident,NEAR
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
MOV AX,(Keep_process SHL 8) + 0 ; Lower part is return code
ADD DX,15
MOV CL,4
SHR DX,CL
transfer COMMAND
Stay_resident ENDP
SUBTTL $EXIT - return to parent process
PAGE
;
; Assembler usage:
; MOV AL, code
; MOV AH, Exit
; INT int_command
; Error return:
; None.
;
procedure $EXIT,NEAR
ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
XOR AH,AH
XCHG AH,BYTE PTR [DidCTRLC]
OR AH,AH
MOV BYTE PTR [Exit_type],exit_terminate
JZ exit_inner
MOV BYTE PTR [Exit_type],exit_ctrl_c
Exit_inner:
invoke get_user_stack
PUSH [CurrentPDB]
POP [SI.user_CS]
transfer abort_inner
$EXIT ENDP
do_ext
CODE ENDS
END
BIN
View File
Binary file not shown.
+97 -1
View File
@@ -1,2 +1,98 @@
# MS-DOS 2.11
MS-DOS 2.11 Source Code
MS-DOS 2.11 source code released by CHM, with files from the MS-DOS 2.00 OAK removed (as they are not MS-DOS 2.11 source files). CHM did not preserve the directory structure of the original source code. Timestamps provided below for reference:
```
1983/08/18 14:26:36 11,648 ALLOC.ASM
1983/08/19 11:53:04 14,716 BUF.ASM
1983/08/18 16:10:38 26,880 CHKDSK.ASM
1983/08/18 16:14:44 14,080 CHKMES.ASM
1983/08/18 16:12:18 40,704 CHKPROC.ASM
1983/08/25 15:06:18 900 COMEQU.ASM
1983/08/18 15:18:16 128 COMLINK
1983/08/18 14:59:06 23,936 COMMAND.ASM
1983/08/25 15:04:08 782 COMSEG.ASM
1980/01/01 00:13:10 512 COMSW.ASM
1983/08/18 15:14:20 20,480 COPY.ASM
1983/08/18 15:15:16 18,304 COPYPROC.ASM
1983/08/18 15:15:56 9,472 CPARSE.ASM
1983/08/19 11:55:50 14,764 CTRLC.ASM
1983/08/18 16:03:54 34,304 DEBASM.ASM
1983/08/18 15:58:12 27,008 DEBCOM1.ASM
1983/10/20 10:28:10 37,356 DEBCOM2.ASM
1983/08/18 16:07:06 38,912 DEBCONST.ASM
1983/08/18 16:07:40 2,816 DEBDATA.ASM
1980/01/01 01:12:36 1,280 DEBEQU.ASM
1980/01/01 00:49:10 5,248 DEBMES.ASM
1983/08/18 16:05:14 21,888 DEBUASM.ASM
1983/08/18 15:56:58 22,016 DEBUG.ASM
1983/08/18 14:27:22 12,032 DEV.ASM
1983/08/18 14:28:48 29,568 DIR.ASM
1983/08/18 14:25:40 14,592 DIRCALL.ASM
1983/08/18 14:30:38 38,016 DISK.ASM
1980/01/01 00:51:48 6,656 DISKCOPY.ASM
1980/01/01 00:52:38 7,808 DISKMES.ASM
1983/08/25 16:46:20 141 DOSLINK
1983/09/12 10:41:22 4,395 DOSMAC.ASM
1983/09/28 14:41:50 14,098 DOSMES.ASM
1983/08/25 15:04:22 357 DOSSEG.ASM
1983/08/25 15:05:44 44,887 DOSSYM.ASM
1980/01/01 02:08:10 56,960 EDLIN.ASM
1983/08/18 16:21:46 3,200 EDLMES.ASM
1983/09/22 23:03:32 13,190 EDLPROC.ASM
1980/01/01 00:45:06 13,824 EXE2BIN.ASM
1983/08/19 11:59:32 31,011 EXEC.ASM
1980/01/01 00:45:24 768 EXEMES.ASM
1983/08/18 14:31:30 10,112 FAT.ASM
1980/01/01 00:26:22 65,024 FC.ASM
1983/08/19 11:52:32 13,392 FCB.ASM
1980/01/01 00:26:42 2,048 FCMES.ASM
1980/01/01 00:28:36 39,168 FIND.ASM
1980/01/01 00:29:22 1,408 FINDMES.ASM
1980/01/01 14:48:16 46,720 FORMAT.ASM
1983/09/22 22:00:04 4,529 FORMES.ASM
1983/08/18 14:14:38 18,048 GETSET.ASM
1983/08/25 15:06:00 303 IFEQU.ASM
1983/08/18 15:01:24 24,832 INIT.ASM
1983/08/18 14:13:16 18,304 MISC.ASM
1980/01/01 02:39:20 3,712 MORE.ASM
1983/09/22 21:23:54 313 MOREMES.ASM
1980/01/03 05:25:56 22,208 MSCODE.ASM
1980/01/01 00:15:46 11,520 MSDATA.ASM
1980/01/03 05:18:14 176 MSDOS.ASM
1980/01/01 00:10:14 9,216 MSHEAD.ASM
1980/01/01 00:24:52 13,568 MSINIT.ASM
1980/01/01 02:42:56 48,000 PRINT.ASM
1983/08/19 11:55:22 3,222 PROC.ASM
1983/08/18 15:00:18 6,784 RDATA.ASM
1980/01/01 00:39:06 5,760 RECMES.ASM
1980/01/01 03:01:58 23,808 RECOVER.ASM
1983/08/18 14:32:20 14,336 ROM.ASM
1983/08/18 14:59:40 6,912 RUCODE.ASM
1983/09/22 22:27:04 17,099 SORT.ASM
1980/01/01 03:07:50 2,688 SORTMES.ASM
1983/08/18 14:32:46 256 STDBUF.ASM
1983/08/18 14:33:56 256 STDCALL.ASM
1983/08/18 14:39:02 256 STDCTRLC.ASM
1980/01/03 07:40:50 193 STDFCB.ASM
1980/01/03 07:41:02 210 STDIO.ASM
1980/01/03 06:27:54 185 STDPROC.ASM
1980/01/01 00:12:18 1,280 STDSW.ASM
1983/08/19 11:54:24 9,726 STRIN.ASM
1983/09/22 21:29:40 22,784 SYS.ASM
1980/01/03 06:26:22 21,220 SYSCALL.ASM
1980/01/01 00:44:22 512 SYSIMES.ASM
1983/10/12 21:24:26 37,644 SYSINIT.ASM
1983/09/22 21:52:50 1,206 SYSMES.ASM
1983/09/08 01:48:06 33,664 TCODE.ASM
1983/08/18 15:05:08 13,568 TCODE2.ASM
1983/08/18 15:10:32 16,896 TCODE3.ASM
1983/08/18 15:11:40 27,392 TCODE4.ASM
1983/09/08 01:49:00 24,576 TCODE5.ASM
1980/01/01 00:38:32 9,088 TDATA.ASM
1983/08/18 14:45:52 7,040 TIME.ASM
1983/08/18 15:17:42 4,480 TSPC.ASM
1983/08/18 15:13:22 7,808 TUCODE.ASM
1980/01/01 00:03:04 896 UINIT.ASM
1980/01/03 06:57:14 25,984 XENIX.ASM
1983/08/18 14:51:18 17,792 XENIX2.ASM
```
BIN
View File
Binary file not shown.
+876
View File
@@ -0,0 +1,876 @@
TITLE RECOVER MS-DOS File/Disk Recovery Utility
;----------------------------------------------------------
;
; Recover - Program to rebuild an ms.dos directory
;
; Copyright 1982 by Microsoft Corporation
; Written by Chris Peters, April 1982
;
;-----------------------------------------------------------
;
;REV 1.5 added header message ARR
;
FALSE EQU 0
TRUE EQU NOT FALSE
IBMVER EQU true
KANJI EQU FALSE
bdos equ 21h
boot equ 20h
aread equ 25h
awrite equ 26h
INCLUDE DOSSYM.ASM
;
cr equ 0dh
lf equ 0ah
;
fcb equ 5ch
code segment public
code ends
const segment public byte
const ends
data segment public byte
data ends
dg group code,const,data
code segment public
assume cs:dg,ds:dg,es:dg,ss:dg
PUBLIC PCRLF,PRINT,INT_23,convert
EXTRN dskwrt:NEAR,dskrd:NEAR,DSKERR:NEAR,report:NEAR
org 100h
recover:jmp rec_start
HEADER DB "Vers 1.50"
;-----------------------------------------------------------------------;
hardch dd ?
the_root db 0 ;root directory flag
fudge db 0 ;directory changed flag
user_drive db 0
drive db 0
dirchar db "/",0
userdir db "/",0
db (dirstrlen) dup(0)
fname_buffer db 128 dup(0)
;-----------------------------------------------------------------------;
pcrlf: mov dx,offset dg: crlf
print: mov ah,STD_CON_STRING_OUTPUT
int bdos
pret: ret
;
convert:push bx
xor ax,ax
mov bx,ax
mov bp,ax
mov cx,32
convlp: shl si,1
rcl di,1
xchg ax,bp
call convwrd
xchg ax,bp
xchg ax,bx
call convwrd
xchg ax,bx
adc al,0
loop convlp
mov cx,1810h
xchg dx,ax
call digit
xchg ax,bx
call outword
mov ax,bp
call outword
pop dx
call print
ret2: ret
;
outword:push ax
mov dl,ah
call outbyte
pop dx
outbyte:mov dh,dl
shr dl,1
shr dl,1
shr dl,1
shr dl,1
call digit
mov dl,dh
digit: and dl,0fh
jz blankzer
xor cl,cl
blankzer:
dec ch
and cl,ch
or dl,30h
sub dl,cl
cmp dl,30h
jl ret2
mov ah,STD_CON_OUTPUT
int bdos
ret
;
convwrd:adc al,al
daa
xchg al,ah
adc al,al
daa
xchg al,ah
ret
;
; bx = fat[ax]
;
getfat: mov bx,offset dg: fattbl
push ax
mov si,ax
sar ax,1
pushf
add si,ax
mov bx,word ptr [bx][si]
popf
jnc getfat1
mov cl,4
shr bx,cl
getfat1:and bh,00001111b
pop ax
mov cx,secsiz
ret
;
; fat[ax] = dx
;
setfat: mov bx,offset dg: fattbl
push ax
push dx
mov si,ax
sar ax,1
pushf
add si,ax
mov ax,word ptr [bx][si]
popf
jnc setfat2
and ax,000fh
mov cl,4
shl dx,cl
setfat1:or ax,dx
mov word ptr [bx][si],ax
pop dx
pop ax
ret
setfat2:and ax,0f000h
jmp setfat1
load: mov dx,firfat
mov al,byte ptr fatnum
mov byte ptr fatcnt,al
mov al,byte ptr drive
mov cx,fatsiz
mov bx,offset dg: fattbl
ret66: ret
readft: call load
readit: call dskrd
cmp [fndfat],0 ;save location of readable fat sector
jnz fdfat
mov [fndfat],dx
fdfat: cmp word ptr [bx+1],-1
jz ret66
add dx,cx ;try to read the other fats
dec byte ptr fatcnt
jnz readit
mov dx,[fndfat] ;see if any readable at all
or dx,dx
jz readft ;if not disk is blown, keep trying
call dskrd
ret
wrtfat: call load
wrtit: push ax
push bx
push cx
push dx
call dskwrt
pop dx
pop cx
pop bx
pop ax
wrtok: add dx,cx
dec byte ptr fatcnt
jnz wrtit
ret
printerr:
call print
jmp rabort
rec_start:
;Code to print header
; PUSH AX
; MOV DX,OFFSET DG:HEADER
; CALL print
; POP AX
DOSVER_HIGH EQU 0200H ;2.00 in hex
PUSH AX ;Save DRIVE validity info
MOV AH,GET_VERSION
INT 21H
XCHG AH,AL ;Turn it around to AH.AL
CMP AX,DOSVER_HIGH
JAE OKDOS
GOTBADDOS:
MOV DX,OFFSET DG:BADVER
CALL PRINT
INT 20H
OKDOS: POP AX
cmp al,0ffH
JZ BADDRVSPECJ
mov si,80h
lodsb
or al,al
jz noparm
look: lodsb
cmp al," "
jz look
cmp al,9
jz look
cmp al,13
jnz gotparm
noparm:
jmp noname
BADDRVSPECJ: JMP BADDRVSPEC
gotparm:
mov ah,DISK_RESET
int bdos ;empty buffer queue
mov ah,get_default_drive ;save current drive
int 21h
mov [user_drive],al
mov bx,fcb ;determine input command
mov al,[bx]
dec al
cmp al,-1
jnz drvok1
mov al,[user_drive]
drvok1:
mov [drive],al
add [drvlet],al
add [drvlet1],al
mov dx,offset dg: askmsg
call print
mov ah,STD_CON_INPUT_FLUSH
mov al,1 ;wait for a key
int bdos
cmp al,17h
jnz drvok2
mov dx,offset dg: egomes
jmp printerr
egomes: db "Chris Peters helped with the new dos!",cr,lf
db "Microsoft rules ok$"
drvok2:
IF IBMVER
MOV AL,DRIVE ;This is for ibm's single drive sys
PUSH DS
MOV BX,50H
MOV DS,BX
MOV DS:(BYTE PTR 4),AL ;Indicate drive changed
POP DS
ENDIF
;----- Process Pathnames -----------------------------------------------;
mov ax,(char_oper shl 8) ;get switch character
int 21h
cmp dl,"/"
jnz slashok ;if not / , then not PC
mov [dirchar],"\" ;in PC, dir separator = \
mov [userdir],"\"
slashok:
mov si,81h ;point to cammand line
mov di,offset dg: fname_buffer
xor cx,cx ;zero pathname length
kill_bl:
lodsb ;get rid of blanks
cmp al,9
je kill_bl
cmp al,' '
je kill_bl
cmp al,13 ;A carriage return?
jne next_char
jmp noname ;yes, file name missing
next_char:
stosb ;put patname in buffer
inc cx
lodsb
cmp al,' '
je name_copied
cmp al,9
je name_copied
cmp al,13 ; a CR ?
jne next_char
name_copied:
mov byte ptr [di],0 ;nul terminate the pathname
dec di ;adjust to the end of the pathname
;----- Scan for directory ----------------------------------------------;
IF KANJI
mov dx,offset dg: [fname_buffer]
PUSH DX
PUSH DI
MOV BX,DI
MOV DI,DX
DELLOOP:
CMP DI,BX
JZ GOTDELE
MOV AL,[DI]
INC DI
CALL TESTKANJ
JZ NOTKANJ11
INC DI
JMP DELLOOP
NOTKANJ11:
cmp al,[dirchar]
JNZ DELLOOP
MOV DX,DI ;Point to char after '/'
DEC DX
DEC DX ;Point to char before '/'
JMP DELLOOP
GOTDELE:
MOV DI,DX
POP AX ;Initial DI
POP DX
SUB AX,DI ;Distance moved
SUB CX,AX ;Set correct CX
CMP DX,DI
JB sja ;Found a pathsep
JA sjb ;Started with a pathsep, root
MOV AX,[DI]
CALL TESTKANJ
JNZ same_dirj
XCHG AH,AL
cmp al,[dirchar]
jz sja ;One character directory
same_dirj:
ELSE
mov al,[dirchar] ;get directory separator character
std ;scan backwards
repnz scasb ;(cx has the pathname length)
cld ;reset direction, just in case
jz sja
ENDIF
jmp same_dir ;no dir separator char. found, the
; file is in the current directory
; of the corresponding drive. Ergo,
; the FCB contains the data already.
sja:
jcxz sjb ;no more chars left, it refers to root
cmp byte ptr [di],':' ;is the prvious character a disk def?
jne not_root
sjb:
mov [the_root],01h ;file is in the root
not_root:
inc di ;point to dir separator char.
mov al,0
stosb ;nul terminate directory name
pop ax
push di ;save pointer to file name
mov [fudge],01h ;remember that the current directory
; has been changed.
;----- Save current directory for exit ---------------------------------;
mov dl,byte ptr ds:[fcb] ;get specified drive if any
or dl,dl ;default disk?
jz same_drive
dec dl ;adjust to real drive (a=0,b=1,...)
mov ah,set_default_drive ;change disks
int 21h
cmp al,-1 ;error?
jne same_drive
BADDRVSPEC:
mov dx,offset dg: baddrv
jmp printerr
same_drive:
mov ah,get_default_dpb
int 21h
assume ds:nothing
cmp al,-1 ;bad drive? (should always be ok)
jne drvisok
mov dx,offset dg: baddrv
jmp printerr
drvisok:
cmp [bx.dpb_current_dir],0
je curr_is_root
mov si,bx
add si,dpb_dir_text
mov di,offset dg: userdir + 1
dir_save_loop:
lodsb
stosb
or al,al
jnz dir_save_loop
curr_is_root:
push cs
pop ds
assume ds:dg
;----- Change directories ----------------------------------------------;
cmp [the_root],01h
mov dx,offset dg: [dirchar] ;assume the root
je sj1
mov dx,offset dg: [fname_buffer]
sj1:
mov ah,chdir ;change directory
int 21h
mov dx,offset dg: baddrv
jnc no_errors
jmp printerr
no_errors:
;----- Set Up int 24 intercept -----------------------------------------;
mov ax,(get_interrupt_vector shl 8) or 24h
int 21h
mov word ptr [hardch],bx
mov word ptr [hardch+2],es
mov ax,(set_interrupt_vector shl 8) or 23h
mov dx,offset dg: int_23
int 21h
mov ax,(set_interrupt_vector shl 8) or 24h
mov dx,offset dg: int_24
int 21h
push cs
pop es
;----- Parse filename to FCB -------------------------------------------;
pop si
mov di,fcb
mov ax,(parse_file_descriptor shl 8) or 1
int 21h
push ax
;-----------------------------------------------------------------------;
same_dir:
pop ax
mov bx,fcb
cmp byte ptr [bx+1],' ' ;must specify file name
jnz drvok
cmp byte ptr [bx],0 ;or drive specifier
jnz drvok
noname: mov dx,offset dg: drverr
call print
jmp int_23
drvok: push ds
mov dl,drive
inc dl
mov ah,GET_DPB
int bdos
mov ax,word ptr [bx+2] ;get physical sector size
mov cl,byte ptr [bx+4] ;get sectors/cluster - 1
xor ch,ch
inc cx
mov cs:secall,cx ;save sectors per cluster
mul cx ;ax = bytes per cluster
mov bp,word ptr [bx+11] ;get record of first sector
mov dx,word ptr [bx+16] ;get record of first directory entry
mov si,word ptr [bx+6] ;get record of first fat
mov cl,byte ptr [bx+15] ;get size of fat
mov di,word ptr [bx+13] ;get number of clusters
mov ch,byte ptr [bx+8] ;get number of fats on drive
mov bx,word ptr [bx+9] ;get max number of dir entries
pop ds
mov maxent,bx
mov firfat,si
mov firrec,bp
mov firdir,dx
mov byte ptr fatsiz,cl
mov lastfat,di ;number of fat entries
mov byte ptr fatnum,ch ;save number of fats on disk
mov secsiz,ax
mov di,table ;di points into constructed directory
mov ax,0e5e5h ;deleted file magic number
shl bx,1 ;16 words in a dir entry
shl bx,1
shl bx,1
shl bx,1
mov cx,bx
rep stosw
call readft
mov bx,fcb
cmp byte ptr [bx+1],' '
jz recdsk
jmp recfil
recdsk: mov di,table
mov fatptr,2
mov ax,fatptr
step1: call getfat
cmp bx,0fffh
jz step1a
jmp step6
step1a: mov filsiz,0
mov word ptr filsiz+2,0
mov dx,lastfat
mov target,ax
step2: mov ax,2
add filsiz,cx
adc word ptr filsiz+2,0
step3: call getfat
cmp bx,target
jne step4
mov target,ax
jmp step2
step4: inc ax
cmp ax,dx
jle step3
;
; at this point target = head of list, filsiz = file size
;
inc filcnt ;increment file count
mov ax,maxent
cmp filcnt,ax ;compare with max number of entries
ja direrr
mov si,(offset dg: dirent)+7
nam0: inc byte ptr [si] ;increment file name
cmp byte ptr [si],'9'
jle nam1
mov byte ptr [si],'0'
dec si
jmp nam0
nam1: mov ah,GET_DATE
int bdos ;set the date
sub cx,1980
add dh,dh
add dh,dh
add dh,dh
add dh,dh
add dh,dh
rcl cl,1
or dh,dl
mov byte ptr dirent+24,dh
mov byte ptr dirent+25,cl
mov ah,GET_TIME
int bdos ;set the time
shr dh,1
add cl,cl
add cl,cl
add cl,cl
rcl ch,1
add cl,cl
rcl ch,1
add cl,cl
rcl ch,1
or dh,cl
mov byte ptr dirent+22,dh
mov byte ptr dirent+23,ch
mov ax,filsiz ;set file size
mov word ptr dirent+28,ax
mov ax,word ptr filsiz+2
mov word ptr dirent+30,ax
mov ax,target ;set first cluster location
mov word ptr dirent+26,ax
mov si,offset dg: dirent ;copy in new dir entry
mov cx,32
rep movsb
step6: inc fatptr ;keep looking for eof's
mov ax,fatptr
cmp ax,lastfat
jg step7
jmp step1
direrr: dec filcnt
mov dx,offset dg: dirmsg
call print
step7:
mov al,drive
mov dx,firdir ;write out constructed directory
mov cx,firrec
sub cx,dx
mov bx,table
call dskwrt
call pcrlf
mov dx,offset dg: recmsg_pre
call print
mov bx,offset dg: recmsg_post
mov si,filcnt
xor di,di ;output number of files created
call convert
jmp rexit
recfil: mov dx,fcb
mov ah,FCB_OPEN
int bdos
inc al
jnz recfil0
mov dx,offset dg: opnerr
call print
jmp rexit
recfil0:mov lastfat,1 ;indicate location of list head
mov di,fcb
mov ax,[di+16] ;get file size
mov filsiz,ax
mov siztmp,ax
mov ax,[di+18]
mov filsiz+2,ax
mov siztmp+2,ax
mov ax,[di+25] ;get list head
or ax,ax
mov fatptr,ax
jnz recfil1
recvec: jmp recfil6
recfil1:cmp fatptr,0fffh
jz recvec ;terminate loop at e-o-f
mov cx,secall
mov ax,fatptr
dec ax
dec ax
mul cx
add ax,firrec
mov dx,ax
mov bx,table
mov al,drive
int aread
pop di ;restore stack pointer
mov di,fcb ;restore pointer to fcb
jnc recfil4 ;if no error continue reading
mov ax,fatptr
call getfat
cmp lastfat,1
jnz recfil2
cmp bx,0fffh
jnz noteof
xor bx,bx
noteof: mov word ptr [di+25],bx
jmp recfil3
recfil2:mov dx,bx ;jump around bad sector
mov ax,lastfat
call setfat
recfil3:mov ax,fatptr ;mark sector bad
mov dx,0ff7h
call setfat
mov ax,secsiz ;prepare to dec filsiz by secsiz
cmp siztmp+2,0
jnz recfilx
cmp siztmp,ax
ja recfilx
mov ax,siztmp
recfilx:sub word ptr [di+16],ax
sbb word ptr [di+18],0
sub siztmp,ax
sbb siztmp,0
and byte ptr [di+24],10111111b ;mark file dirty
mov ax,lastfat ;point to next sector to check
jmp recfil5
recfil4:
mov ax,secsiz ;set bytes remaining to be read
sub siztmp,ax
sbb siztmp+2,0
jnc recok
xor ax,ax ;if < 0, then set to zero
mov siztmp,ax
mov siztmp+2,ax
recok: mov ax,fatptr ;get next sector to test
mov lastfat,ax
recfil5:call getfat
mov fatptr,bx
jmp recfil1
recfil6: ;all done
mov dx,fcb
mov ah,FCB_CLOSE
int bdos ;close the file
call pcrlf
call report
;
rexit: mov ah,DISK_RESET
int bdos
call wrtfat ;save the fat
int_23: call rest_dir
rabort: int boot ;home, james...
;----- Restore INT 24 vector and old current directory -----------------;
rest_dir:
cmp [fudge],0
je no_fudge
mov ax,(set_interrupt_vector shl 8) or 24h
lds dx,[hardch]
int 21h
push cs
pop ds
mov dx,offset dg: userdir ;restore directory
mov ah,chdir
int 21h
mov dl,[user_drive] ;restore old current drive
mov ah,set_default_drive
int 21h
no_fudge:
ret
;----- INT 24 Processing -----------------------------------------------;
int_24_retaddr dw int_24_back
int_24 proc far
assume ds:nothing,es:nothing,ss:nothing
pushf
push cs
push [int_24_retaddr]
push word ptr [hardch+2]
push word ptr [hardch]
ret
int_24 endp
int_24_back:
cmp al,2 ;abort?
jnz ireti
push cs
pop ds
assume ds:dg
call rest_dir
int 20h
ireti:
iret
IF KANJI
TESTKANJ:
CMP AL,81H
JB NOTLEAD
CMP AL,9FH
JBE ISLEAD
CMP AL,0E0H
JB NOTLEAD
CMP AL,0FCH
JBE ISLEAD
NOTLEAD:
PUSH AX
XOR AX,AX ;Set zero
POP AX
RET
ISLEAD:
PUSH AX
XOR AX,AX ;Set zero
INC AX ;Reset zero
POP AX
RET
ENDIF
code ends
const segment public byte
EXTRN BADVER:BYTE,askmsg:BYTE,drvlet:BYTE,dirmsg:BYTE
EXTRN recmsg_pre:BYTE,DRVLET1:BYTE,recmsg_post:BYTE
EXTRN crlf:BYTE,drverr:BYTE,baddrv:BYTE,opnerr:BYTE
const ends
data segment byte
PUBLIC filsiz
dirent db 'FILE0000REC'
db 21 dup (00)
fndfat dw 0000 ;sector of first good fat
filcnt dw 0000
fatcnt db 00
fatnum db 00
fatsiz dw 0000
firfat dw 0000
fatptr dw 0000
secall dw 0000 ;sectors per cluster
target dw 0000
maxent dw 0000
firrec dw 0000
firdir dw 0000
secsiz dw 0000
siztmp dw 0000
dw 0000
filsiz dw 0000
dw 0000
lastfat dw 0000
;
table dw offset dg:fattbl + 6 * 1024
fattbl db 0
data ends
end recover

+530
View File
@@ -0,0 +1,530 @@
;
; Disk utilities of MSDOS
;
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.XLIST
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
TITLE ROM - miscellaneous routines
NAME ROM
i_need CLUSNUM,WORD
i_need NEXTADD,WORD
i_need LASTPOS,WORD
i_need SECCLUSPOS,BYTE
i_need FATBYT,WORD
i_need RECPOS,4
i_need THISFCB,DWORD
i_need TRANS,BYTE
i_need BYTCNT1,WORD
i_need CURBUF,DWORD
i_need BYTSECPOS,WORD
i_need DMAADD,WORD
i_need SECPOS,WORD
i_need VALSEC,WORD
procedure GET_random_record,NEAR
entry GETRRPOS1
MOV CX,1
entry GetRRPos
MOV DI,DX
CMP BYTE PTR [DI],-1
JNZ NORMFCB1
ADD DI,7
NORMFCB1:
MOV AX,WORD PTR [DI.fcb_RR]
MOV DX,WORD PTR [DI.fcb_RR+2]
return
GET_random_record ENDP
SUBTTL FNDCLUS -- Skip over allocation units
PAGE
procedure FNDCLUS,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; CX = No. of clusters to skip
; ES:BP = Base of drive parameters
; [THISFCB] point to FCB
; Outputs:
; BX = Last cluster skipped to
; CX = No. of clusters remaining (0 unless EOF)
; DX = Position of last cluster
; DI destroyed. No other registers affected.
PUSH ES
LES DI,[THISFCB]
MOV BX,ES:[DI.fcb_LSTCLUS] ; fcb_lstclus is packed with dir clus
AND BX,0FFFh ; get rid of dir nibble
MOV DX,ES:[DI.fcb_CLUSPOS]
OR BX,BX
JZ NOCLUS
SUB CX,DX
JNB FINDIT
ADD CX,DX
XOR DX,DX
MOV BX,ES:[DI.fcb_FIRCLUS]
FINDIT:
POP ES
JCXZ RET10
entry SKPCLP
invoke UNPACK
CMP DI,0FF8H
JAE RET10
XCHG BX,DI
INC DX
LOOP SKPCLP
RET10: return
NOCLUS:
POP ES
INC CX
DEC DX
return
FNDCLUS ENDP
SUBTTL BUFSEC -- BUFFER A SECTOR AND SET UP A TRANSFER
PAGE
procedure BUFSEC,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; AH = priority of buffer
; AL = 0 if buffer must be read, 1 if no pre-read needed
; ES:BP = Base of drive parameters
; [CLUSNUM] = Physical cluster number
; [SECCLUSPOS] = Sector position of transfer within cluster
; [BYTCNT1] = Size of transfer
; Function:
; Insure specified sector is in buffer, flushing buffer before
; read if necessary.
; Outputs:
; ES:DI = Pointer to buffer
; SI = Pointer to transfer address
; CX = Number of bytes
; [NEXTADD] updated
; [TRANS] set to indicate a transfer will occur
MOV DX,[CLUSNUM]
MOV BL,[SECCLUSPOS]
CALL FIGREC
invoke GETBUFFR
MOV BYTE PTR [TRANS],1 ; A transfer is taking place
MOV SI,[NEXTADD]
MOV DI,SI
MOV CX,[BYTCNT1]
ADD DI,CX
MOV [NEXTADD],DI
LES DI,[CURBUF]
ADD DI,BUFINSIZ ; Point to buffer
ADD DI,[BYTSECPOS]
return
BUFSEC ENDP
SUBTTL BUFRD, BUFWRT -- PERFORM BUFFERED READ AND WRITE
PAGE
procedure BUFRD,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Do a partial sector read via one of the system buffers
; ES:BP Points to DPB
PUSH ES
MOV AX,LBRPRI SHL 8 ; Assume last byte read
CALL BUFSEC
MOV BX,ES
MOV ES,[DMAADD+2]
MOV DS,BX
ASSUME DS:NOTHING
XCHG DI,SI
SHR CX,1
JNC EVENRD
MOVSB
EVENRD:
REP MOVSW
POP ES
LDS DI,[CURBUF]
LEA BX,[DI.BufInSiz]
SUB SI,BX ; Position in buffer
invoke PLACEBUF
CMP SI,ES:[BP.dpb_sector_size]
JB RBUFPLACED
invoke PLACEHEAD
RBUFPLACED:
PUSH SS
POP DS
return
BUFRD ENDP
procedure BUFWRT,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Do a partial sector write via one of the system buffers
; ES:BP Points to DPB
MOV AX,[SECPOS]
INC AX ; Set for next sector
MOV [SECPOS],AX
CMP AX,[VALSEC] ; Has sector been written before?
MOV AL,1
JA NOREAD ; Skip preread if SECPOS>VALSEC
XOR AL,AL
NOREAD:
PUSH ES
CALL BUFSEC
MOV DS,[DMAADD+2]
ASSUME DS:NOTHING
SHR CX,1
JNC EVENWRT
MOVSB
EVENWRT:
REP MOVSW
POP ES
LDS BX,[CURBUF]
MOV BYTE PTR [BX.BUFDIRTY],1
LEA SI,[BX.BufInSiz]
SUB DI,SI ; Position in buffer
MOV SI,DI
MOV DI,BX
invoke PLACEBUF
CMP SI,ES:[BP.dpb_sector_size]
JB WBUFPLACED
invoke PLACEHEAD
WBUFPLACED:
PUSH SS
POP DS
return
BUFWRT ENDP
SUBTTL NEXTSEC -- Compute next sector to read or write
PAGE
procedure NEXTSEC,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Compute the next sector to read or write
; ES:BP Points to DPB
TEST BYTE PTR [TRANS],-1
JZ CLRET
MOV AL,[SECCLUSPOS]
INC AL
CMP AL,ES:[BP.dpb_cluster_mask]
JBE SAVPOS
MOV BX,[CLUSNUM]
CMP BX,0FF8H
JAE NONEXT
invoke UNPACK
MOV [CLUSNUM],DI
INC [LASTPOS]
MOV AL,0
SAVPOS:
MOV [SECCLUSPOS],AL
CLRET:
CLC
return
NONEXT:
STC
return
NEXTSEC ENDP
SUBTTL OPTIMIZE -- DO A USER DISK REQUEST WELL
PAGE
procedure OPTIMIZE,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; BX = Physical cluster
; CX = No. of records
; DL = sector within cluster
; ES:BP = Base of drives parameters
; [NEXTADD] = transfer address
; Outputs:
; AX = No. of records remaining
; BX = Transfer address
; CX = No. or records to be transferred
; DX = Physical sector address
; DI = Next cluster
; [CLUSNUM] = Last cluster accessed
; [NEXTADD] updated
; ES:BP unchanged. Note that segment of transfer not set.
PUSH DX
PUSH BX
MOV AL,ES:[BP.dpb_cluster_mask]
INC AL ; Number of sectors per cluster
MOV AH,AL
SUB AL,DL ; AL = Number of sectors left in first cluster
MOV DX,CX
MOV CX,0
OPTCLUS:
; AL has number of sectors available in current cluster
; AH has number of sectors available in next cluster
; BX has current physical cluster
; CX has number of sequential sectors found so far
; DX has number of sectors left to transfer
; ES:BP Points to DPB
; ES:SI has FAT pointer
invoke UNPACK
ADD CL,AL
ADC CH,0
CMP CX,DX
JAE BLKDON
MOV AL,AH
INC BX
CMP DI,BX
JZ OPTCLUS
DEC BX
FINCLUS:
MOV [CLUSNUM],BX ; Last cluster accessed
SUB DX,CX ; Number of sectors still needed
PUSH DX
MOV AX,CX
MUL ES:[BP.dpb_sector_size] ; Number of sectors times sector size
MOV SI,[NEXTADD]
ADD AX,SI ; Adjust by size of transfer
MOV [NEXTADD],AX
POP AX ; Number of sectors still needed
POP DX ; Starting cluster
SUB BX,DX ; Number of new clusters accessed
ADD [LASTPOS],BX
POP BX ; BL = sector postion within cluster
invoke FIGREC
MOV BX,SI
return
BLKDON:
SUB CX,DX ; Number of sectors in cluster we don't want
SUB AH,CL ; Number of sectors in cluster we accepted
DEC AH ; Adjust to mean position within cluster
MOV [SECCLUSPOS],AH
MOV CX,DX ; Anyway, make the total equal to the request
JMP SHORT FINCLUS
OPTIMIZE ENDP
SUBTTL FIGREC -- Figure sector in allocation unit
PAGE
procedure FIGREC,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DX = Physical cluster number
; BL = Sector postion within cluster
; ES:BP = Base of drive parameters
; Outputs:
; DX = physical sector number
; No other registers affected.
PUSH CX
MOV CL,ES:[BP.dpb_cluster_shift]
DEC DX
DEC DX
SHL DX,CL
OR DL,BL
ADD DX,ES:[BP.dpb_first_sector]
POP CX
return
FIGREC ENDP
SUBTTL GETREC -- Figure record in file from fcb
PAGE
procedure GETREC,NEAR
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX point to FCB
; Outputs:
; CX = 1
; DX:AX = Record number determined by fcb_EXTENT and fcb_NR fields
; DS:DI point to FCB
; No other registers affected.
MOV DI,DX
CMP BYTE PTR [DI],-1 ; Check for extended FCB
JNZ NORMFCB2
ADD DI,7
NORMFCB2:
MOV CX,1
MOV AL,[DI.fcb_NR]
MOV DX,[DI.fcb_EXTENT]
SHL AL,1
SHR DX,1
RCR AL,1
MOV AH,DL
MOV DL,DH
MOV DH,0
return
GETREC ENDP
SUBTTL ALLOCATE -- Assign disk space
PAGE
procedure ALLOCATE,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; BX = Last cluster of file (0 if null file)
; CX = No. of clusters to allocate
; DX = Position of cluster BX
; ES:BP = Base of drive parameters
; [THISFCB] = Points to FCB
; Outputs:
; IF insufficient space
; THEN
; Carry set
; CX = max. no. of records that could be added to file
; ELSE
; Carry clear
; BX = First cluster allocated
; FAT is fully updated including dirty bit
; fcb_FIRCLUS field of FCB set if file was null
; SI,BP unchanged. All other registers destroyed.
PUSH BX ; save the fat byte
XOR BX,BX
invoke UNPACK
MOV [FATBYT],DI
POP BX
PUSH DX
PUSH CX
PUSH BX
MOV AX,BX
CLUSALLOC:
MOV DX,BX
FINDFRE:
INC BX
CMP BX,ES:[BP.dpb_max_cluster]
JLE TRYOUT
CMP AX,1
JG TRYIN
POP BX
MOV DX,0FFFH
invoke RELBLKS
POP AX ; No. of clusters requested
SUB AX,CX ; AX=No. of clusters allocated
POP DX
invoke RESTFATBYT
INC DX ; Position of first cluster allocated
ADD AX,DX ; AX=max no. of cluster in file
MOV DL,ES:[BP.dpb_cluster_mask]
MOV DH,0
INC DX ; DX=records/cluster
MUL DX ; AX=max no. of records in file
MOV CX,AX
SUB CX,WORD PTR [RECPOS] ; CX=max no. of records that could be written
JA MAXREC
XOR CX,CX ; If CX was negative, zero it
MAXREC:
STC
return
TRYOUT:
invoke UNPACK
JZ HAVFRE
TRYIN:
DEC AX
JLE FINDFRE
XCHG AX,BX
invoke UNPACK
JZ HAVFRE
XCHG AX,BX
JMP SHORT FINDFRE
HAVFRE:
XCHG BX,DX
MOV AX,DX
invoke PACK
MOV BX,AX
LOOP CLUSALLOC
MOV DX,0FFFH
invoke PACK
POP BX
POP CX ; Don't need this stuff since we're successful
POP DX
invoke UNPACK
invoke RESTFATBYT
XCHG BX,DI
OR DI,DI
retnz
PUSH ES
LES DI,[THISFCB]
AND BX,0FFFh
MOV ES:[DI.fcb_FIRCLUS],BX
AND ES:[DI.fcb_LSTCLUS],0F000h ; clear out old lstclus
OR ES:[DI.fcb_LSTCLUS],BX ; or the new guy in...
POP ES
return
ALLOCATE ENDP
procedure RESTFATBYT,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
PUSH BX
PUSH DX
PUSH DI
XOR BX,BX
MOV DX,[FATBYT]
invoke PACK
POP DI
POP DX
POP BX
return
RESTFATBYT ENDP
SUBTTL RELEASE -- DEASSIGN DISK SPACE
PAGE
procedure RELEASE,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; BX = Cluster in file
; ES:BP = Base of drive parameters
; Function:
; Frees cluster chain starting with [BX]
; AX,BX,DX,DI all destroyed. Other registers unchanged.
XOR DX,DX
entry RELBLKS
; Enter here with DX=0FFFH to put an end-of-file mark
; in the first cluster and free the rest in the chain.
invoke UNPACK
retz
MOV AX,DI
invoke PACK
CMP AX,0FF8H
MOV BX,AX
JB RELEASE
RET12: return
RELEASE ENDP
SUBTTL GETEOF -- Find the end of a file
PAGE
procedure GETEOF,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
; Inputs:
; ES:BP Points to DPB
; BX = Cluster in a file
; DS = CS
; Outputs:
; BX = Last cluster in the file
; DI destroyed. No other registers affected.
invoke UNPACK
CMP DI,0FF8H
JAE RET12
MOV BX,DI
JMP SHORT GETEOF
GETEOF ENDP
do_ext
CODE ENDS
END
BIN
View File
Binary file not shown.
+420
View File
@@ -0,0 +1,420 @@
TITLE SORT FILTER FOR MS-DOS
;
; Sort /R /+n
; /R -> reverse sort
; /+n -> sort on column n
;
; Written by: Chris Peters
;
; Modification History:
; 3-18-83 MZ Fix CR-LF at end of buffer
; Fix small file sorting
; Fix CR-LF line termination bug
; Comment the Damn source
;
FALSE EQU 0
TRUE EQU NOT FALSE
;NOTE: "internat" must be false if KANJI version
internat equ true
;NOTE: see above
.xlist
.xcref
INCLUDE DOSSYM.ASM
.cref
.list
sys MACRO name ; system call macro
MOV AH,name
INT 21h
ENDM
save MACRO reglist ; push those registers
IRP reg,<reglist>
PUSH reg
ENDM
ENDM
restore MACRO reglist ; pop those registers
IRP reg,<reglist>
POP reg
ENDM
ENDM
MAXREC EQU 256 ; MAXIMUM NUL RECORD SIZE
SPACE EQU 0 ; Offset zero in the allocated block
BUFFER EQU MAXREC ; Offset MAXREC in the allocated block
SUBTTL Segments used in load order
CODE SEGMENT
CODE ENDS
CONST SEGMENT PUBLIC BYTE
CONST ENDS
CSTACK SEGMENT STACK
DB 128 DUP (0) ; initial stack to be clear
CSTACK ENDS
DG GROUP CODE,CONST,CSTACK
CODE SEGMENT
ASSUME CS:DG,DS:NOTHING,ES:NOTHING,SS:CSTACK
COLUMN DW 0 ; COLUMN TO USE FOR KEY + 1
SWITCH DB '/'
SORT:
;
; check for proper version number of system
;
sys GET_VERSION
XCHG AH,AL ; Turn it around to AH.AL
CMP AX,200H ; Version 2.00 only
JAE OKDOS ; Success
MOV DX,OFFSET DG:BADVER ; Get error message
PUSH CS ; Get DS addressability
POP DS
sys STD_CON_STRING_OUTPUT ; Send to STDOUT
PUSH ES ; long segment
PUSH COLUMN ; offset zero
LONG_RET PROC FAR
RET ; long return to OS
LONG_RET ENDP
;
; get proper switch character
;
OKDOS:
MOV AL,0 ; Get current switch character
sys CHAR_OPER
MOV SWITCH,DL
;
; parse command line
;
MOV SI,80H ; pointer to command line
CLD ; go left to right
XOR CX,CX
LODSB
MOV CL,AL ; CX = length of command line
SWITCH_LOOP:
CALL GET_CHAR ; get a character
CMP AL,SWITCH ; beginning of switch?
JNZ SWITCH_LOOP ; No, get next character
CALL GET_CHAR ; get 1st char of switch
CMP AL,'+' ; Column to sort?
JZ SWITCH_NUMBER ; Yes, parse a number
OR AL,20h ; convert to lower case
CMP AL,'r' ; Reverse sort?
JNZ SWITCH_LOOP ; No, get next switch
MOV CS:CODE_PATCH,72h ; sleaze JAE into JB
JMP SWITCH_LOOP ; get next switch
SWITCH_NUMBER:
MOV COLUMN,0 ; start off at 0
SWITCH_NEXT_NUMBER:
CALL GET_CHAR ; get supposed digit
SUB AL,'0' ; convert to number
JB SWITCH_LOOP ; less than '0'
CMP AL,9 ; is it a valid digit?
JA SWITCH_LOOP ; nope, get next switch
CBW ; make it a full word
MOV BX,AX ; save byte away
MOV AX,10 ; decimal number system
MUL COLUMN ; take previous result
ADD AX,BX ; add in low order digit
MOV COLUMN,AX ; save away value
JMP SWITCH_NEXT_NUMBER ; get next character
GET_CHAR:
JCXZ END_GET ; End of line
DEC CX ; dec char count
LODSB ; get the character
RET ; return
END_GET:
POP AX ; nuke return on stack
;
; set up column for proper sort offset
;
END_SWITCH:
ADD COLUMN,2
CMP COLUMN,2
JZ GOT_COL
DEC COLUMN
;
; Get sorting area, no more than 64K
;
GOT_COL:
MOV BX,1000H ; 64K worth of paragraphs
GET_MEM:
sys ALLOC ; allocate them from somewhere
JNC GOT_MEM ; if error, BX has amount free, try to get it
OR BX,BX ; but, is BX = 0?
JNZ GET_MEM ; nope, try to allocate it
JMP SIZERR ; complain
GOT_MEM:
MOV DS,AX ; Point DS to buffer
MOV ES,AX ; and point ES to buffer
MOV CL,4 ; 2^4 bytes per paragraph
SHL BX,CL ; Find out how many bytes we have
;
; clear out temporary record area
;
MOV CX,MAXREC/2 ; Size of temporary buffer (words)
MOV AX,' ' ; Character to fill with
MOV DI,SPACE ; Beginning of temp buffer
REP STOSW ; Blam.
;
; read in file from standard input
;
MOV DX,BUFFER + 2 ; DX = place to begin reading
MOV CX,BX ; CX is the max number to read
SUB CX,MAXREC + 2 ; remember offset of temp buffer
SORTL:
XOR BX,BX ; Standard input
sys READ ; Read it in
ADD DX,AX ; Bump pointer by count read
SUB CX,AX ; subtract from remaining the count read
JZ SIZERR ; if buffer is full then error
OR AX,AX ; no chars read -> end of file
JNZ SORTL ; there were chars read. go read again
JMP SHORT SIZOK ; trim last ^Z terminated record
SIZERR:
MOV SI,OFFSET DG:ERRMSG ; not enough memory error
ERROR_EXIT:
PUSH CS ; DS addressability
POP DS
LODSW ; get length
MOV CX,AX ; put into appropriate register
MOV DX,SI ; get output destination
MOV BX,2 ; output to standard error
sys WRITE ; and write it out
MOV AL,1 ; return an error code
sys EXIT
;
; Look for a ^Z. Terminate buffer at 1st ^Z.
;
SIZOK:
MOV BX,DX ; save end pointer
MOV CX,DX ; get pointer to end of text
SUB CX,BUFFER+2 ; dif in pointers is count
MOV AL,1AH ; char is ^Z
MOV DI,BUFFER+2 ; point to beginning of text
REPNZ SCASB ; find one
JNZ NoBack ; nope, try to find CRLF
DEC BX ; pretend that we didn't see ^Z
NoBack:
SUB BX,CX ; sub from endpointer the number left
SUB BX,2 ; Hope for a CR LF at end
CMP WORD PTR [BX],0A0Dh ; Was there one there?
JZ GOTEND ; yep, here is the end
ADD BX,2 ; nope, bump back to SCASB spot
CMP BYTE PTR [BX],AL ; Was there ^Z there?
JZ GOTEND ; yep, chop it
INC BX ; Nope, skip last char
GOTEND:
MOV BP,BX ; BP = filesize-2(CRLF)+temp buffer+2
MOV WORD PTR DS:[BP],0 ; 0 at end of the file
;
; We now turn the entire buffer into a linked list of chains by
; replacing CRLFs with the length of the following line (with 2 for CRLF)
;
MOV BX,BUFFER ; pointer to line head (length)
MOV DI,BUFFER+2 ; pointer to line text
REPLACE_LOOP:
MOV AL,13 ; char to look for is CR
MOV CX,BP ; count = end pointer
SUB CX,DI ; chop off start point to get length
INC CX ; add 1???
REPLACE_SCAN:
REPNZ SCASB ; look for CR
JNZ REPLACE_SKIP ; count exhausted
CMP BYTE PTR [DI],10 ; LF there?
JNZ REPLACE_SCAN ; nope, continue scanning
REPLACE_SKIP:
MOV AX,DI ; AX to point after CR
DEC AX ; AX to point to CR
save <AX> ; save pointer
SUB AX,BX ; AX is length of line found
MOV [BX],AX ; stuff it in previous link
restore <BX> ; get pointer to next
INC DI ; skip LF???
JCXZ END_REPLACE_LOOP ; no more to scan -> go sort
JMP REPLACE_LOOP ; look for next
END_REPLACE_LOOP:
MOV WORD PTR [BX],0 ; terminate file with nul
LEA BP,[BX+2] ; remember the null line at end
MOV DI,BUFFER ; DI is start of unsorted section
;
; begin sort. Outer loop steps over all unsorted lines
;
OUTER_SORT_LOOP:
MOV BX,DI ; BX is start of unsorted section
MOV SI,BX ; SI is scanning place link
CMP WORD PTR [BX],0 ; are we at the end of the buffer?
JNZ INNER_SORT_LOOP ; No, do inner process
JMP END_OUTER_SORT_LOOP ; yes, go dump out
;
; BX points to best guy found so far. We scan through the sorted section
; to find an appropriate insertion point
;
INNER_SORT_LOOP:
ADD SI,[SI] ; link to next fellow
MOV AX,[SI] ; get length of comparison guy
OR AX,AX ; test for end of buffer
JZ END_INNER_SORT_LOOP ; if zero then figure out insertion
save <SI,DI> ; save SI,DI
MOV DI,BX ; DI = pointer to tester link
SUB AX,COLUMN ; adjust length for column
JA AXOK ; more chars in tester than column?
MOV SI,SPACE ; point SI to blank area
MOV AX,MAXREC ; make AX be max length
AXOK:
MOV DX,[DI] ; get length of best guy
SUB DX,COLUMN ; adjust length for column
JA DXOK ; there are more chars after column
MOV DI,SPACE ; point air to a space
MOV DX,MAXREC ; really big record
DXOK:
MOV CX,AX ; AX is shortest record
CMP AX,DX ; perhaps DX is shorter
JB SMALL ; nope, leace CX alone
MOV CX,DX ; DX is shorter, put length in CX
SMALL:
ADD DI,COLUMN ; offset into record
ADD SI,COLUMN ; offset into other record
if not internat
REPZ CMPSB ; compare every one
endif
if internat
push bx
push ax
mov bx,offset dg:table
tloop: lodsb
xlat byte ptr cs:[bx]
mov ah,al
mov al,es:[di]
inc di
xlat byte ptr cs:[bx]
cmp ah,al
loopz tloop
pop ax
pop bx
endif
restore <DI,SI> ; get head pointers back
JNZ TESTED_NOT_EQUAL ; didn't exhaust counter, conditions set
CMP AX,DX ; check string lengths
TESTED_NOT_EQUAL:
;
; note! jae is patched to a jbe if file is to be sorted in reverse!
;
CODE_PATCH LABEL BYTE
JAE INNER_SORT_LOOP ; if this one wasn't better then go again
MOV BX,SI ; it was better, save header
JMP INNER_SORT_LOOP ; and scan again
END_INNER_SORT_LOOP:
MOV SI,BX ; SI is now the best person
CMP SI,DI ; check best for current
JZ END_INSERT ; best equals current, all done
;
; SI points to best line found so far
; DI points to a place to insert this line
; DI is guaranteed to be < SI
; make room for line at destination
;
MOV DX,[SI] ; get length of line
save <SI,DI> ; save positions of people
STD ; go right to left
MOV CX,BP ; get end of file pointer
SUB CX,DI ; get length from destination to end
MOV SI,BP ; start from end
DEC SI ; SI points to end of file
MOV DI,SI ; destination is end of file
ADD DI,DX ; DI points to new end of file
REP MOVSB ; blam. Move every one up
CLD ; back left to right
restore <DI,SI> ; get old source and destination
;
; MOVE NEW LINE INTO PLACE
;
save <DI> ; save destination
ADD SI,DX ; adjust for previous movement
save <SI> ; save this value
MOV CX,DX ; get number to move
REP MOVSB ; blam. move the new line in
restore <SI,DI> ; get back destination and new source
;
; DELETE LINE FROM OLD PLACE
;
save <DI> ; save destination
MOV CX,BP ; pointer to end
ADD CX,DX ; remember bump
SUB CX,SI ; get count of bytes to move
INC CX ; turn it into a word
SHR CX,1 ; or a count of words
MOV DI,SI ; new destination of move
ADD SI,DX ; offset of block
REP MOVSW ; blam, squeeze out the space
restore <DI> ; get back original destination
MOV WORD PTR DS:[BP-2],0 ; remake the end of file mark
END_INSERT:
ADD DI,[DI] ; link to next guy
JMP OUTER_SORT_LOOP ; and continue
;
; PUT BACK IN THE CR-LF
;
END_OUTER_SORT_LOOP:
MOV DI,BUFFER ; start at beginning (where else)
MOV CX,[DI] ; count of butes
INSERT_LOOP:
ADD DI,CX ; point to next length
MOV CX,[DI] ; get length
MOV WORD PTR [DI],0A0DH ; replace length with CRLF
CMP CX,0 ; check for end of file
JNZ INSERT_LOOP ; nope, try again
WRITE_FILE:
MOV DX,BUFFER+2 ; get starting point
MOV CX,BP ; pointer to end of buffer
SUB CX,DX ; dif in pointers is number of bytes
MOV BX,1 ; to standard output
sys WRITE ; write 'em out
JC BADWRT ; some bizarre error -> flag it
CMP AX,CX ; did we write what was expected?
JZ WRTOK ; yes, say bye bye
BADWRT:
MOV SI,OFFSET dg:ERRMSG2 ; strange write error
JMP ERROR_EXIT ; bye bye
WRTOK:
XOR AL,AL ; perfect return (by convention)
sys EXIT ; bye!
CODE ENDS
CONST SEGMENT PUBLIC BYTE
EXTRN BADVER:BYTE,ERRMSG:BYTE,ERRMSG2:BYTE
if internat
extrn table:byte
endif
CONST ENDS
SUBTTL Initialized Data
PAGE
CSTACK SEGMENT STACK
DB 96 dup (0)
CSTACK ENDS
END SORT

BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+16
View File
@@ -0,0 +1,16 @@
;
; Standard FCB calls for MSDOS (first 12 function calls)
;
.xlist
.xcref
INCLUDE STDSW.ASM
.cref
.list
TITLE STDFCB - FCB calls for MSDOS
NAME STDFCB
INCLUDE FCB.ASM

+17
View File
@@ -0,0 +1,17 @@
;
; Standard device IO for MSDOS (first 12 function calls)
;
.xlist
.xcref
INCLUDE STDSW.ASM
INCLUDE DOSSEG.ASM
.cref
.list
TITLE STDIO - device IO for MSDOS
NAME STDIO
INCLUDE IO.ASM

+16
View File
@@ -0,0 +1,16 @@
;
; Pseudo EXEC system call for MSDOS
;
.xlist
.xcref
INCLUDE STDSW.ASM
.cref
.list
TITLE STDPROC - process maintenance for MSDOS
NAME STDPROC
INCLUDE PROC.ASM

+34
View File
@@ -0,0 +1,34 @@
TRUE EQU 0FFFFH
FALSE EQU NOT TRUE
; Use the switches below to produce the standard Microsoft version or the IBM
; version of the operating system
MSVER EQU false
IBM EQU true
WANG EQU FALSE
ALTVECT EQU FALSE
; Set this switch to cause DOS to move itself to the end of memory
HIGHMEM EQU FALSE
IF IBM
ESCCH EQU 0 ; character to begin escape seq.
CANCEL EQU 27
TOGLINS EQU TRUE ;One key toggles insert mode
TOGLPRN EQU TRUE ;One key toggles printer echo
ZEROEXT EQU TRUE
ELSE
IF WANG ;Are we assembling for WANG?
ESCCH EQU 1FH ;Yes. Use 1FH for escape character
ELSE
ESCCH EQU 1BH
ENDIF
CANCEL EQU "X"-"@" ;Cancel with Ctrl-X
TOGLINS EQU WANG ;Separate keys for insert mode on
;and off if not WANG
TOGLPRN EQU FALSE ;Separate keys for printer echo on
;and off
ZEROEXT EQU TRUE
ENDIF

+292
View File
@@ -0,0 +1,292 @@
procedure $STD_CON_STRING_INPUT,NEAR ;System call 10
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Point to an input buffer
; Function:
; Fill buffer from console input until CR
; Returns:
; None
MOV AX,SS
MOV ES,AX
MOV SI,DX
XOR CH,CH
LODSW
OR AL,AL
retz ;Buffer is 0 length!!?
MOV BL,AH ;Init template counter
MOV BH,CH ;Init template counter
CMP AL,BL
JBE NOEDIT ;If length of buffer inconsistent with contents
CMP BYTE PTR [BX+SI],c_CR
JZ EDITON ;If CR correctly placed EDIT is OK
NOEDIT:
MOV BL,CH ;Reset buffer
EDITON:
MOV DL,AL
DEC DX ;DL is # of bytes we can put in the buffer
NEWLIN:
MOV AL,[CARPOS]
MOV [STARTPOS],AL ;Remember position in raw buffer
PUSH SI
MOV DI,OFFSET DOSGROUP:INBUF ;Build the new line here
MOV [INSMODE],CH ;Insert mode off
MOV BH,CH ;No chars from template yet
MOV DH,CH ;No chars to new line yet
invoke $STD_CON_INPUT_NO_ECHO ;Get first char
CMP AL,c_LF ;Linefeed
JNZ GOTCH ;Filter out LF so < works
entry GETCH
invoke $STD_CON_INPUT_NO_ECHO
GOTCH:
CMP AL,"F"-"@" ;Ignore ^F
JZ GETCH
CMP AL,[ESCCHAR]
JZ ESC
CMP AL,c_DEL
JZ BACKSPJ
CMP AL,c_BS
JZ BACKSPJ
CMP AL,c_CR
JZ ENDLIN
CMP AL,c_LF
JZ PHYCRLF
CMP AL,CANCEL
JZ KILNEW
SAVCH:
CMP DH,DL
JAE BUFFUL ;No room
STOSB
INC DH ;Got a char
invoke BUFOUT ;Print control chars nicely
CMP BYTE PTR [INSMODE],0
JNZ GETCH ;In insert mode, get more chars
CMP BH,BL
JAE GETCH ;We are out of chars in template
INC SI ;Skip to next char in template
INC BH
JMP SHORT GETCH
BACKSPJ: JMP SHORT BACKSP
BUFFUL:
MOV AL,7 ;Bell
invoke OUT
JMP SHORT GETCH
ESC:
transfer OEMFunctionKey
ENDLIN:
STOSB ;Put the CR in the buffer
invoke OUT ;Echo it
POP DI ;Get start of buffer
MOV [DI-1],DH ;Tell user how many bytes
INC DH ;DH is length including CR
COPYNEW:
MOV BP,ES ;XCHG ES,DS
MOV BX,DS
MOV ES,BX
MOV DS,BP
MOV SI,OFFSET DOSGROUP:INBUF
MOV CL,DH
REP MOVSB ;Copy final line to user buffer
return ;All done
;Output a CRLF
entry CRLF
MOV AL,c_CR
invoke OUT
MOV AL,c_LF
JMP OUT
;Output a CRLF which is not terminate buffer
PHYCRLF:
invoke CRLF
JMP GETCH
;Zap the line without zapping the template
entry KILNEW
MOV AL,"\"
invoke OUT ;Print the CANCEL indicator
POP SI ;Remember start of edit buffer
PUTNEW:
invoke CRLF ;Go to next line on screen
MOV AL,[STARTPOS]
invoke TAB ;Tab over
JMP NEWLIN ;Start over again
;Back up one char
entry BACKSP
OR DH,DH
JZ OLDBAK ;No chars in line, do nothing to line
CALL BACKUP ;Do the backup
MOV AL,ES:[DI] ;Get the deleted char
CMP AL," "
JAE OLDBAK ;Was a normal char
CMP AL,c_HT
JZ BAKTAB ;Was a tab, fix up users display
CALL BACKMES ;Was a control char, zap the '^'
OLDBAK:
CMP BYTE PTR [INSMODE],0
JNZ GETCH1 ;In insert mode, get more chars
OR BH,BH
JZ GETCH1 ;Not advanced in template, stay where we are
DEC BH ;Go back in template
DEC SI
GETCH1:
JMP GETCH
BAKTAB:
PUSH DI
DEC DI ;Back up one char
STD ;Go backward
MOV CL,DH ;Number of chars currently in line
MOV AL," "
PUSH BX
MOV BL,7 ;Max
JCXZ FIGTAB ;At start, do nothing
FNDPOS:
SCASB ;Look back
JNA CHKCNT
CMP BYTE PTR ES:[DI+1],9
JZ HAVTAB ;Found a tab
DEC BL ;Back one char if non tab control char
CHKCNT:
LOOP FNDPOS
FIGTAB:
SUB BL,[STARTPOS]
HAVTAB:
SUB BL,DH
ADD CL,BL
AND CL,7 ;CX has correct number to erase
CLD ;Back to normal
POP BX
POP DI
JZ OLDBAK ;Nothing to erase
TABBAK:
invoke BACKMES
LOOP TABBAK ;Erase correct number of chars
JMP SHORT OLDBAK
BACKUP:
DEC DH ;Back up in line
DEC DI
BACKMES:
MOV AL,c_BS ;Backspace
invoke OUT
MOV AL," " ;Erase
invoke OUT
MOV AL,c_BS ;Backspace
JMP OUT ;Done
;User really wants an ESC character in his line
entry TwoEsc
MOV AL,[ESCCHAR]
JMP SAVCH
;Copy the rest of the template
entry COPYLIN
MOV CL,BL ;Total size of template
SUB CL,BH ;Minus position in template, is number to move
JMP SHORT COPYEACH
entry CopyStr
invoke FINDOLD ;Find the char
JMP SHORT COPYEACH ;Copy up to it
;Copy one char from template to line
entry COPYONE
MOV CL,1
;Copy CX chars from template to line
COPYEACH:
MOV BYTE PTR [INSMODE],0 ;All copies turn off insert mode
CMP DH,DL
JZ GETCH2 ;At end of line, can't do anything
CMP BH,BL
JZ GETCH2 ;At end of template, can't do anything
LODSB
STOSB
invoke BUFOUT
INC BH ;Ahead in template
INC DH ;Ahead in line
LOOP COPYEACH
GETCH2:
JMP GETCH
;Skip one char in template
entry SKIPONE
CMP BH,BL
JZ GETCH2 ;At end of template
INC BH ;Ahead in template
INC SI
JMP GETCH
entry SKIPSTR
invoke FINDOLD ;Find out how far to go
ADD SI,CX ;Go there
ADD BH,CL
JMP GETCH
;Get the next user char, and look ahead in template for a match
;CX indicates how many chars to skip to get there on output
;NOTE: WARNING: If the operation cannot be done, the return
; address is popped off and a jump to GETCH is taken.
; Make sure nothing extra on stack when this routine
; is called!!! (no PUSHes before calling it).
FINDOLD:
invoke $STD_CON_INPUT_NO_ECHO
CMP AL,[ESCCHAR] ; did he type a function key?
JNZ FindSetup ; no, set up for scan
invoke $STD_CON_INPUT_NO_ECHO ; eat next char
JMP NotFnd ; go try again
FindSetup:
MOV CL,BL
SUB CL,BH ;CX is number of chars to end of template
JZ NOTFND ;At end of template
DEC CX ;Cannot point past end, limit search
JZ NOTFND ;If only one char in template, forget it
PUSH ES
PUSH DS
POP ES
PUSH DI
MOV DI,SI ;Template to ES:DI
INC DI
REPNE SCASB ;Look
POP DI
POP ES
JNZ NOTFND ;Didn't find the char
NOT CL ;Turn how far to go into how far we went
ADD CL,BL ;Add size of template
SUB CL,BH ;Subtract current pos, result distance to skip
return
NOTFND:
POP BP ;Chuck return address
JMP GETCH
entry REEDIT
MOV AL,"@" ;Output re-edit character
invoke OUT
POP DI
PUSH DI
PUSH ES
PUSH DS
invoke COPYNEW ;Copy current line into template
POP DS
POP ES
POP SI
MOV BL,DH ;Size of line is new size template
JMP PUTNEW ;Start over again
entry EXITINS
entry ENTERINS
NOT BYTE PTR [INSMODE]
JMP GETCH
;Put a real live ^Z in the buffer (embedded)
entry CTRLZ
MOV AL,"Z"-"@"
JMP SAVCH
$STD_CON_STRING_INPUT ENDP
+587
View File
@@ -0,0 +1,587 @@
TITLE MS-DOS SYS Program
; SYS - Copies system programs IBMBIO.COM/IO.SYS and IBMDOS.COM/MSDOS.SYS
; 1.6 05/21/82 Added rev number message
; 1.61 06/04/82 Allow SYS to blank disk TimP at SCP
; 1.70 06/30/82 NON contiguous DOS allowed on 2.00 IBM. Allows SYS to
; 1.0 1.1 disks.
; 1.71 07/02/82 Put in CHDIRs to make sure everything done in root dir.
; 1.80 04/26/83 MZ make sys work in small machines; use full 2.0 system
; calls
; 1.81 07/22/83 ARR Added check in IBM version for valid FAT ID on
; destination because of IBM problem with SYSing to
; unformatted disks which are really formatted.
; Prints NoDest message for ridic IBM reasons, should
; have a better message.
FALSE EQU 0
TRUE EQU NOT FALSE
IBMJAPVER EQU FALSE
IBMVER EQU FALSE
MSVER EQU TRUE
.xlist
.xcref
INCLUDE DOSSYM.ASM
.cref
.list
DOSVER_LOW EQU 0136H ; Lowest acceptable DOS version number
DOSVER_HIGH EQU 020BH ; Highest acceptable DOS version
CODE SEGMENT WORD PUBLIC
CODE ENDS
CONST SEGMENT BYTE PUBLIC
CONST ENDS
DATA SEGMENT BYTE PUBLIC
DATA ENDS
DG GROUP CODE,DATA,CONST
DATA SEGMENT PUBLIC BYTE
EXTRN BADDRV:BYTE, BADDRVLen:WORD
EXTRN BADPARM:BYTE, BADPARMLen:WORD
EXTRN GETSYS:BYTE, GETSYSLen:WORD
EXTRN SYSDRV:BYTE
EXTRN NODEST:BYTE, NODESTLen:WORD
EXTRN BADSIZ:BYTE, BADSIZLen:WORD
EXTRN DONE:BYTE, DONELen:WORD
EXTRN BADVER:BYTE
IF IBMJAPVER
EXTRN BADDISK:BYTE, BADDISKLen:WORD
ENDIF
DEFALT DB 0
IF MSVER
BIOSName DB "A:\IO.SYS",0
DOSName DB "A:\MSDOS.SYS",0
ENDIF
IF IBMVER OR IBMJAPVER
BIOSName DB "A:\IBMBIO.COM",0
DOSName DB "A:\IBMDOS.COM",0
ENDIF
BIOSInFH DW ? ; file handle of source BIOS
BIOSLenLow DW 2 DUP (?) ; 32-bit length of BIOS
BIOSLenHigh DW 2 DUP (?) ; 32-bit length of BIOS
BIOSTime DW 2 DUP (?) ; place to store time of BIOS write
BIOSOutFH DW ? ; fh of BIOS destination
DOSInFH DW ? ; file handle of source DOS
DOSLenLow DW 2 DUP (?) ; 32-bit length of DOS
DOSLenHigh DW 2 DUP (?) ; 32-bit length of DOS
DOSTime DW 2 DUP (?) ; place to store time of DOS write
DOSOutFH DW ? ; fh of DOS destination
AllName DB "A:\*.*",0
cbBuf DW ? ; number of bytes in buffer
pDOS DW ? ; offset of beginning of DOS in buffer
pDOSEnd DW ? ; offset of end of DOS in buffer
IF IBMVER OR IBMJAPVER
BOOT DW 256 DUP (0)
IF IBMJAPVER
LLISTBUF DW 256 DUP (0)
ENDIF
ENDIF
IF IBMJAPVER
RELOC DW 1 DUP(?)
STARTSECTOR DW 1 DUP(?)
ENDIF
BUF LABEL BYTE ; beginning of area for file reads
DATA ENDS
CODE SEGMENT PUBLIC
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
ORG 100H
Start:
JMP SHORT CheckVersion
IF IBMVER
DW OFFSET DG:BOOT
ENDIF
HEADER DB "Vers 1.81"
CheckVersion:
PUSH AX ; save drive letter validity
MOV AH,GET_VERSION
INT 21H ; get dos version
XCHG AH,AL ; Turn it around to AH.AL
CMP AX,DOSVER_LOW ; is it too low?
JB GOTBADDOS ; yes, error
CMP AX,DOSVER_HIGH ; too high?
JBE OKDOS ; yes, go check drive letter
GOTBADDOS:
MOV DX,OFFSET DG:BADVER ; message to dump
MOV AH,STD_CON_STRING_OUTPUT ; standard output device
INT 21H
INT 20H ; old style exit for compatability
OKDOS: POP AX ; get drive validity
JMP SHORT SYS ; go process
ERR0: MOV DX,OFFSET DG:BADPARM ; no drive letter
MOV CX,BadParmLen
JMP DisplayError
ERR1: MOV DX,OFFSET DG:BADDRV ; drive letter invalid
MOV CX,BadDrvLen
JMP DisplayError
ERR2: MOV AL,DEFALT ; get default drive number
ADD AL,'A'-1 ; turn into letter
MOV SYSDRV,AL ; place into middle of message
MOV DX,OFFSET DG:GETSYS
MOV CX,GETSYSLen ; length for output
MOV BX,stderr ; use stderr
MOV AH,Write ; Ask for system disk
INT 21H
CALL GetKeystroke ; wait for him to type simething
XOR AL,AL ; valid drive spec now...
SYS:
CMP DS:(BYTE PTR 5DH)," " ; Was file specified?
JNZ ERR0 ; yes, no files are allowed -> error
CMP AL,-1 ; Invalid drive spec?
JZ ERR1 ; yes, must have valid drive -> error
CMP DS:(BYTE PTR 5CH),0 ; No drive specified?
JZ ERR1 ; yes, cannot sys to default drive error
MOV AH,GET_DEFAULT_DRIVE ; Get default drive
INT 21H
INC AL ; turn from phys drive to logical drive
MOV DEFALT,AL ; save it for possible printing
CMP DS:(BYTE PTR 5CH),AL ; did he specify the default drive?
JZ ERR1 ; yes, default drive not allowed
IF IBMVER ; Check for "valid" destination
PUSH AX
MOV AL,BYTE PTR DS:[5Ch]
DEC AL
MOV BX,OFFSET DG:BUF ; Temp space
MOV DX,1 ; Sector 1 (first sec of FAT)
MOV CX,DX ; One sector
INT 25H ; Read Fat sector
POP AX ; Flags
POP AX ; Real AX
JC OKFAT ; Don't error here, let a CREATE or
; some other call to the dest
; generate a more useful INT 24H
; error
CMP BYTE PTR [BUF],0F8H
JAE OKFAT
JMP ERR3
OKFAT:
ENDIF
ADD AL,'A'-1 ; turn into letter
MOV BIOSName,AL ; twiddle source name
MOV DOSName,AL ; twiddle source name
CLD
MOV DX,OFFSET DG:BIOSName ; source name
MOV DI,OFFSET DG:BIOSInFH ; pointer to block of data
CALL OpenFile
JC Err2 ; not found, go and try again
MOV DX,OFFSET DG:DOSName ; source of DOS
MOV DI,OFFSET DG:DOSInFH ; pointer to block of data
CALL OpenFile ; Look for DOS
JC ERR2 ; not there, go ask for a system disk
MOV CX,SP ; get lowest available spot
SUB CX,0200h+(OFFSET DG:BUF); leave room for all sorts of things
MOV cbBuf,CX ; store length away
CALL FillMem ; load up memory with files
IF IBMJAPVER
CALL READ_BOOT ; need to copy boot sector too
ENDIF
MOV AL,DS:(BYTE PTR 5CH) ; get drive of destination
IF IBMJAPVER
CALL CHECK_TRAN ; check for bootable device
JZ DOSWRT ; ok to boot
MOV DX,OFFSET DG:BADDISK ; incorrect format to boot
MOV CX,BadDiskLen
JMP DisplayError ; go error and quit
DOSWRT:
ENDIF
ADD AL,'A'-1 ; convert to letter
MOV BIOSName,AL ; point names at destination drive
MOV DOSName,AL
MOV AllName,AL ; look for any files
MOV AH,Find_First ; look for files
MOV DX,OFFSET DG:AllName ; path of where to look
MOV CX,Attr_Hidden+Attr_System ; attributes to find
INT 21H
JC PutSys ; no files - go and copy
IF MSVER
MOV DL,DS:(BYTE PTR 5CH) ; get drive number
MOV AH,GET_DRIVE_FREESPACE ; get free space available
INT 21H
MUL CX ; Compute size of cluster (secsiz*secperclus)
XCHG CX,AX ; move it to correct spot
MOV DX,OFFSET DG:BIOSName ; who to open
MOV AX,BIOSLenLow+2 ; get low part of size
MOV BX,BIOSLenHigh+2 ; get high size
CALL CHKLEN ; open and snoop size
JNZ ERR4 ; Must fit exact so MSDOS is in right place
MOV DX,OFFSET DG:DOSName ; other guy to open
MOV AX,DOSLenLow+2 ; get low part of size
MOV BX,DOSLenHigh+2 ; get high size
CALL CHKLEN ; open and snoop second size
JA ERR4 ; Must be enough (or too much) space
ENDIF
IF IBMVER OR IBMJAPVER
MOV DX,OFFSET DG:BIOSName ; open BIOS
MOV CX,7 ; attributes
MOV AH,Find_First
INT 21H
JNC FindDos
Err3J: JMP Err3 ; not found, go and complain
FindDos:
MOV DX,OFFSET DG:DOSName ; open DOS
MOV AH,Find_First
INT 21H
JC Err3J ; Not found, go complain
ENDIF
PUTSYS:
MOV DX,OFFSET DG:BIOSName ; who to change mode
MOV CX,0 ; undo attributes
MOV AX,(ChMod SHL 8) + 1 ; set the attributes
INT 21h
MOV DX,OFFSET DG:DOSName ; who to change mode
MOV CX,0 ; undo attributes
MOV AX,(ChMod SHL 8) + 1 ; set the attributes
INT 21h
MOV DX,OFFSET DG:BIOSName ; destination of BIOS
MOV CX,7 ; fancy attributes
MOV AH,Creat ; make a new one
INT 21h
MOV BIOSOutFH,AX ; save handle
MOV DX,OFFSET DG:DOSName ; destination of DOS
MOV AH,Creat ; make a new one
INT 21h
MOV DOSOutFH,AX ; save handle
Copy:
CALL DumpMem ; flush out memory
MOV AX,DOSLenHigh ; more DOS?
OR AX,DOSLenLow ; more low dos
OR AX,BIOSLenHigh ; more high BIOS
OR AX,BIOSLenLow ; more low BIOS
JZ AllDone ; nope, all done
CALL FillMem ; reload world
JMP Copy
ERR4:
MOV DX,OFFSET DG:BADSIZ
MOV CX,BadSizLen
JMP DisplayError
AllDone:
MOV CX,BIOSTime ; get time and date
MOV DX,BIOSTime+2
MOV BX,BIOSOutFH ; where to stuff the time
MOV AX,(File_Times SHL 8) + 1
INT 21h
MOV AH,Close
INT 21h
MOV CX,DOSTime ; get time and date
MOV DX,DOSTime+2
MOV BX,DOSOutFH ; where to stuff the time
MOV AX,(File_Times SHL 8) + 1
INT 21h
MOV AH,Close
INT 21h
IF IBMVER OR IBMJAPVER
CALL PUTBOOT ; copy the boot sector also
ENDIF
MOV DX,OFFSET DG:DONE ; all finished message
MOV CX,DoneLen
XOR AL,AL ; ok error code
SERROR:
PUSH AX
MOV BX,stderr
MOV AH,Write ; convenient place to display message
INT 21H
POP AX
ErrorExit:
MOV AH,EXIT ; bye and return error code
INT 21h
DisplayError:
MOV AL,1
JMP SERROR
FillMem:
MOV CX,cbBuf ; get length of buffer
MOV BX,BIOSInFH ; get bios source handle
MOV DX,OFFSET DG:BUF ; point to beginning of buffer
PUSH CX ; save away total length
CMP BIOSLenHigh,0 ; > 64K to read?
JA UseCX ; use CX
CMP BIOSLenLow,CX ; more left to read?
JA UseCX ; use CX
MOV CX,BIOSLenLow ; move new
UseCX:
MOV AH,Read
INT 21h ; read in what we can
ADD DX,AX ; update pointer for DOS Read
MOV pDOS,DX ; point to beginning of DOS
SUB BIOSLenLow,AX ; decrement remaining
SBB BIOSLenHigh,0 ; do 32 bit
POP CX ; get original length
SUB CX,AX ; this much is left
MOV BX,DOSInFH ; get bios source handle
CMP DOSLenHigh,0 ; > 64K to read?
JA UseCXDOS ; use CX
CMP DOSLenLow,CX ; more left to read?
JA UseCXDOS ; use CX
MOV CX,DOSLenLow ; move new
UseCXDOS:
MOV AH,Read
INT 21h ; read in what we can
ADD DX,AX ; update pointer for DOS Read
MOV pDOSEnd,DX ; point to End of dos DOS
SUB DOSLenLow,AX ; decrement remaining
SBB DOSLenHigh,0 ; do 32 bit arithmetic
return
OpenFile:
MOV AX,(OPEN SHL 8) + 0 ; open for reading only
INT 21H ; Look for BIOS
retc ; not found, go and try again
STOSW ; stash away handle
MOV BX,AX ; get ready for seeks
MOV AX,(LSeek SHL 8) + 2 ; seek relative to eof
XOR CX,CX ; zero offset
XOR DX,DX ; zero offset
INT 21h ; get offsets
STOSW ; save low part of size
STOSW ; save low part of size
MOV AX,DX
STOSW ; save high part of size
STOSW ; save high part of size
XOR DX,DX ; zero offset
MOV AX,(LSeek SHL 8) + 0 ; seek relative to beginning
INT 21h
MOV AX,(File_Times SHL 8) + 0
INT 21h ; get last write times
MOV AX,CX
STOSW ; save time
MOV AX,DX
STOSW ; save date
return
ERR3:
MOV DX,OFFSET DG:NODEST
MOV CX,NoDestLen
JMP DisplayError
DumpMem:
MOV DX,OFFSET DG:BUF ; get offset of bios start
MOV CX,pDOS ; beginning of next guy
SUB CX,DX ; difference is length
JZ DumpDos ; no bios to move
MOV BX,BIOSOutFH ; where to output
MOV AH,Write
INT 21h ; wham
DumpDos:
MOV DX,pDOS ; beginning of dos
MOV CX,pDOSEnd ; end of dos
SUB CX,DX ; difference is length
retz ; if zero no write
MOV BX,DOSOutFH ; where to output
MOV AH,Write
INT 21h ; wham
ret
IF MSVER
CHKLEN:
; CX has size of cluster, DX has pointer to file name
; Returns with flags set on (size of file) - (size of hole)
PUSH AX ; old size low
PUSH BX ; old size high
PUSH CX ; old cluster size
MOV AH,Find_First
MOV CX,7 ; attributes to search for
INT 21H
JC ERR3 ; cannot find file, error
POP CX ; get cluster size back
MOV DX,DS:[80h+find_buf_size_h] ; get destination size high
MOV AX,DS:[80h+find_buf_size_l] ; get size low
ADD AX,CX ; add cluster size
ADC DX,0 ; 32 bit add
SUB AX,1 ; adding CLUSSIZE-1
SBB DX,0 ; 32 bit dec
DIV CX ; compute new cluster size
POP DX ; get old high
POP BX ; get old low
PUSH AX ; save away dividend
MOV AX,BX ; put into correct register
ADD AX,CX ; do the same as above (+CLUSSIZE-1)/CLUSSIZE
ADC DX,0 ; 32 bit add
SUB AX,1 ; adding CLUSSIZE-1
SBB DX,0 ; 32 bit dec
DIV CX ; compute old cluster size
POP DX ; get new size
CMP AX,DX ; is old >= new?
return
ENDIF
IF IBMJAPVER
PUTBOOT:
CALL READ_LLIST ; Get the list sector and set new boot sector
MOV AL,DS:(BYTE PTR 5CH)
DEC AL ; A=0
MOV CX,1
XOR DX,DX
MOV BX,OFFSET DG:BOOT
INT 26H ; Write out new boot sector
POPF
CALL WRITE_LLIST ; Make and write out new list sector
RET
ENDIF
IF IBMVER
PUTBOOT:
MOV AH,GET_DPB
MOV DL,BYTE PTR DS:[5Ch] ; Target drive
INT 21H
ASSUME DS:NOTHING
MOV AL,[BX+16H] ; Media byte
PUSH CS
POP DS
ASSUME DS:DG
CMP AL,0FEH
JB RET1
TEST AL,1
JZ GOTBOOT
MOV BX,OFFSET DG:BOOT
MOV WORD PTR [BX+17],112 ; Set number of dir entries
MOV WORD PTR [BX+19],2*8*40 ; Set number of sectors
INC BYTE PTR [BX+21] ; Media = ff
INC WORD PTR [BX+26] ; Number of heads = 2
GOTBOOT:
MOV AL,BYTE PTR DS:[5Ch]
DEC AL
MOV BX,OFFSET DG:BOOT ; Boot sector
XOR DX,DX ; Sector 0
MOV CX,DX
INC CX ; One sector
INT 26H ; Write out 8 sector boot sector
POP AX ; Flags
RET1: RET
ENDIF
IF IBMJAPVER
READ_BOOT:
MOV AL,[DEFALT]
DEC AL ; A=0
MOV CX,1
XOR DX,DX
MOV BX,OFFSET DG:BOOT
INT 25H
POPF
MOV AX,[BOOT+108H] ; Get old first sector of data
MOV [RELOC],AX
RET
READ_LLIST:
MOV AL,DS:(BYTE PTR 5CH)
DEC AL ; A=0
MOV CX,1
MOV DX,[STARTSECTOR]
MOV BX,OFFSET DG:LLISTBUF
INT 25H
POPF
RET
WRITE_LLIST:
MOV AX,[STARTSECTOR]
MOV DX,AX
SUB AX,[RELOC] ; True reloc factor
MOV CL,BYTE PTR [LLISTBUF+0CH] ; Number of entries needing reloc
XOR CH,CH
JCXZ NO_RELOCS
MOV BX,OFFSET DG:LLISTBUF + 10H
RELLOOP:
ADD WORD PTR [BX+2],AX
ADD BX,10H
LOOP RELLOOP
NO_RELOCS:
MOV AL,DS:(BYTE PTR 5CH)
DEC AL ; A=0
MOV CX,1
MOV BX,OFFSET DG:LLISTBUF
INT 26H
POPF
RET
CHECK_TRAN:
; All registers preserved. Returns zero if SYS OK, NZ if SYS FAIL
; AL is drive (1=A,...) AL=0 is not valid
PUSH BX
PUSH AX
PUSH DS
MOV DL,AL
MOV AH,GET_DPB
INT 21H
MOV AX,[BX.dpb_first_sector] ; Get new first sector of data
MOV BH,[BX.dpb_media]
POP DS
MOV [STARTSECTOR],AX
MOV [BOOT+108H],AX ; Set new start of data in boot
POP AX
PUSH AX
MOV BL,AL
INT 11H ; IBM EQUIP CALL
ROL AL,1
ROL AL,1
AND AL,3
JNZ NOT_SINGLE
INC AL
NOT_SINGLE:
INC AL ; AL is now MAX floppy #
CMP BL,AL
POP AX
JBE CHECK_FLOP ; Is a floppy
XOR BL,BL ; Is Hard file
POP BX
RET
CHECK_FLOP:
CMP BH,0FBH ; Only floppy that boots
POP BX
RET
ENDIF
GetKeystroke:
MOV AX,(Std_CON_Input_Flush SHL 8) + Std_CON_Input_No_Echo
INT 21H
MOV AX,(Std_CON_Input_Flush SHL 8) + 0
INT 21H
return
CODE ENDS
END START

+749
View File
@@ -0,0 +1,749 @@
;
; system call entry points MSDOS
;
INCLUDE DOSSEG.ASM
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
i_need YEAR,WORD
i_need DAY,BYTE
i_need WeekDay,BYTE
i_need TimeBuf,6
i_need BCLOCK,DWORD
i_need DskErr,BYTE
i_need Attrib,BYTE
i_need Name1,BYTE
i_need Name2,BYTE
i_need Name3,BYTE
i_need DelAll,BYTE
i_need ThisDPB,DWORD
i_need CurBuf,DWORD
i_need LastEnt,WORD
i_need ThisDrv,BYTE
i_need DirStart,WORD
i_need DevPt,DWORD
i_need Creating,BYTE
i_need VolID,BYTE
i_need FoundDel,BYTE
SUBTTL DATE AND TIME - SYSTEM CALLS 42,43,44,45; S/G DATE,TIME
PAGE
procedure $GET_DATE,NEAR ;System call 42
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Return current date
; Returns:
; Date in CX:DX
PUSH SS
POP DS
ASSUME DS:DOSGROUP
invoke READTIME ;Check for rollover to next day
MOV AX,[YEAR]
MOV BX,WORD PTR [DAY]
invoke get_user_stack ;Get pointer to user registers
ASSUME DS:NOTHING
MOV [SI.user_DX],BX ;DH=month, DL=day
ADD AX,1980 ;Put bias back
MOV [SI.user_CX],AX ;CX=year
MOV AL,BYTE PTR [WEEKDAY]
RET
$GET_DATE ENDP
procedure $SET_DATE,NEAR ;System call 43
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; CX:DX valid date
; Function:
; Set current date
; Returns:
; AL = -1 date bad, = 0 OK
MOV AL,-1 ;Be ready to flag error
SUB CX,1980 ;Fix bias in year
JC RET24 ;Error if not big enough
CMP CX,119 ;Year must be less than 2100
JA RET24
OR DH,DH
JZ RET24
OR DL,DL
JZ RET24 ;Error if either month or day is 0
CMP DH,12 ;Check against max. month
JA RET24
PUSH SS
POP DS
ASSUME DS:DOSGROUP
invoke DODATE
RET24: RET
$SET_DATE ENDP
procedure $GET_TIME,NEAR ;System call 44
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; None
; Function:
; Get current time
; Returns:
; Time in CX:DX
PUSH SS
POP DS
ASSUME DS:DOSGROUP
invoke READTIME
invoke get_user_stack ;Get pointer to user registers
MOV [SI.user_DX],DX
MOV [SI.user_CX],CX
XOR AL,AL
RET26: RET
$GET_TIME ENDP
procedure $SET_TIME,NEAR ;System call 45
;Time is in CX:DX in hours, minutes, seconds, 1/100 sec.
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; CX:DX = Time
; Function:
; Set time
; Returns:
; AL = -1 time bad, = 0 OK
MOV AL,-1 ;Flag in case of error
CMP CH,24 ;Check hours
JAE RET26
CMP CL,60 ;Check minutes
JAE RET26
CMP DH,60 ;Check seconds
JAE RET26
CMP DL,100 ;Check 1/100's
JAE RET26
PUSH CX
PUSH DX
PUSH SS
POP DS
ASSUME DS:DOSGROUP
MOV BX,OFFSET DOSGROUP:TIMEBUF
MOV CX,6
XOR DX,DX
MOV AX,DX
PUSH BX
invoke SETREAD
ASSUME ES:DOSGROUP
PUSH DS
LDS SI,[BCLOCK]
ASSUME DS:NOTHING
invoke DEVIOCALL2 ;Get correct day count
POP DS
ASSUME DS:DOSGROUP
POP BX
invoke SETWRITE
POP WORD PTR [TIMEBUF+4]
POP WORD PTR [TIMEBUF+2]
LDS SI,[BCLOCK]
ASSUME DS:NOTHING
invoke DEVIOCALL2 ;Set the time
XOR AL,AL
RET
$SET_TIME ENDP
SUBTTL DISK R/W ROUTINES
PAGE
procedure $FCB_SEQ_READ,NEAR ; System call 20
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to openned FCB
; Function:
; Read next record from file to disk transfer address
; Returns:
; AL = 1 EOF record is empty
; AL = 3 EOF record is partial zero filled
; AL = 2 No room at disk transfer address
; AL = 0 All OK
invoke GETREC
invoke LOAD
JMP SHORT FINSEQ
entry $FCB_SEQ_WRITE ; System call 21
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to openned FCB
; Function:
; Write next record to file from disk transfer address
; Returns:
; AL = 1 Disk full
; AL = 2 No room in disk transfer segment
; AL = 0 All OK
invoke GETREC
invoke STORE
FINSEQ:
JCXZ SETNREX
ADD AX,1
ADC DX,0
JMP SHORT SETNREX
entry $FCB_RANDOM_READ ; System call 33
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to openned FCB
; Function:
; Read record addressed by random record field from file to
; disk transfer address
; Returns:
; AL = 1 EOF record is empty
; AL = 3 EOF record is partial zero filled
; AL = 2 No room at disk transfer address
; AL = 0 All OK
invoke GETRRPOS1
invoke LOAD
JMP SHORT FINRND
entry $FCB_RANDOM_WRITE ; System call 34
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to openned FCB
; Function:
; Write record addressed by random record field to file from
; disk transfer address
; Returns:
; AL = 1 Disk full
; AL = 2 No room in disk transfer segment
; AL = 0 All OK
invoke GETRRPOS1
invoke STORE
JMP SHORT FINRND
entry $FCB_RANDOM_READ_BLOCK ; System call 39
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to openned FCB
; CX = Record count
; Function:
; Read CX records starting at random record field from file
; to disk transfer address
; Returns:
; AL = 1 EOF record is empty
; AL = 3 EOF record is partial zero filled
; AL = 2 No room at disk transfer address
; AL = 0 All OK
; CX = Actual number of records read
invoke GETRRPOS
invoke LOAD
JMP SHORT FINBLK
entry $FCB_RANDOM_WRITE_BLOCK ; System call 40
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX Points to openned FCB
; CX = Record count
; Function:
; Write CX records starting at random record field to file
; from disk transfer address
; If CX = 0 File is set to length determined from random record field
; Returns:
; AL = 1 Disk full
; AL = 2 No room in disk transfer segment
; AL = 0 All OK
; CX = Actual number of records written
invoke GETRRPOS
invoke STORE
FINBLK:
invoke get_user_stack
MOV [SI.user_CX],CX
entry FINNOSAV
JCXZ FINRND
ADD AX,1
ADC DX,0
FINRND:
MOV WORD PTR ES:[DI.fcb_RR],AX
MOV ES:[DI.fcb_RR+2],DL
OR DH,DH
JZ SETNREX
MOV ES:[DI.fcb_RR+3],DH ; Save 4 byte of RECPOS only if significant
SETNREX:
MOV CX,AX
AND AL,7FH
MOV ES:[DI.fcb_NR],AL
AND CL,80H
SHL CX,1
RCL DX,1
MOV AL,CH
MOV AH,DL
MOV ES:[DI.fcb_EXTENT],AX
MOV AL,BYTE PTR [DSKERR]
RET4:
RET
$FCB_SEQ_READ ENDP
SUBTTL $FCB_DELETE -- SYSTEM CALL 19
PAGE
procedure $FCB_DELETE,NEAR ; System call 19
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX point to unopened FCB
; Function:
; Delete all matching entries
; Returns:
; AL = -1 if no entries matched, otherwise 0
invoke MOVNAME
ASSUME ES:DOSGROUP
MOV AL,-1
MOV BYTE PTR [FoundDel],AL
JC RET4
MOV AL,BYTE PTR [ATTRIB]
AND AL,attr_hidden+attr_system+attr_directory+attr_volume_id+attr_read_only
; Look only at hidden bits
CMP AL,attr_hidden+attr_system+attr_directory+attr_volume_id+attr_read_only
; All must be set
JNZ NOTALL
MOV CX,11
MOV AL,"?"
MOV DI,OFFSET DOSGROUP:NAME1
REPE SCASB ; See if name is *.*
JNZ NOTALL
MOV BYTE PTR [DELALL],0 ; DEL *.* - flag deleting all
NOTALL:
invoke FINDNAME
ASSUME DS:DOSGROUP
MOV AL,-1
JC RET4
OR AH,AH ; Check if device name
JS RET4 ; Can't delete I/O devices
DELFILE:
LES BP,[THISDPB]
MOV AH,BYTE PTR [DELALL]
PUSH DS
LDS DI,[CURBUF]
ASSUME DS:NOTHING
TEST [Attrib],attr_read_only ; are we deleting RO files too?
JNZ DoDelete ; yes
TEST DS:[BX.dir_attr],attr_read_only
JZ DoDelete ; not read only
POP DS
JMP SHORT DelNxt
DoDelete:
MOV BYTE PTR [FoundDel],0
MOV [DI.BUFDIRTY],1
MOV BYTE PTR [BX],AH
MOV BX,[SI]
POP DS
ASSUME DS:DOSGROUP
OR BX,BX
JZ DELNXT
CMP BX,ES:[BP.dpb_max_cluster]
JA DELNXT
invoke RELEASE
DELNXT:
invoke GETENTRY ; Registers need to be reset
invoke NEXTENT
JNC DELFILE
CALL FLUSHRET1
MOV AL,BYTE PTR [FoundDel]
RET
$FCB_DELETE ENDP
SUBTTL $FCB_RENAME -- SYSTEM CALL 23; RENAME FILES
PAGE
ERRETJ: JMP ERRET
procedure $FCB_RENAME,NEAR ; System call 23
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX point to a modified FCB (DS:DX+11H points to destination
; name)
; Function:
; Rename all matching entries to indicated name
; Returns:
; AL = -1 if no entries matched, otherwise 0
invoke MOVNAME
ASSUME ES:DOSGROUP
JC ERRETJ
ADD SI,5
MOV DI,OFFSET DOSGROUP:NAME2
invoke LODNAME
JC ERRETJ ; Report error if second name invalid
invoke FINDNAME
ASSUME DS:DOSGROUP
JC ERRETJ
OR AH,AH ; Check if I/O device name
JS ERRETJ ; If so, can't rename it
MOV SI,OFFSET DOSGROUP:NAME1
MOV DI,OFFSET DOSGROUP:NAME3
MOV CX,13
REP MOVSB ; Copy name to search for --include attribute byte
RENFIL:
MOV DI,OFFSET DOSGROUP:NAME1
MOV SI,OFFSET DOSGROUP:NAME2
MOV CX,11
NEWNAM:
LODSB
CMP AL,"?"
JNZ NOCHG
PUSH DS
MOV DS,WORD PTR [CURBUF+2]
MOV AL,[BX]
POP DS
NOCHG:
STOSB
INC BX
LOOP NEWNAM
INC DI
MOV BYTE PTR [DI],attr_all ;Sets ATTRIB
; Stop duplicates with any attributes
invoke DEVNAME ; Check if giving it a device name
JNC RENERR
XOR AX,AX
PUSH [LASTENT]
invoke FINDENTRY ; See if new name already exists
POP AX
JNC RENERR ; Error if found
LES BP,[THISDPB]
invoke GETENT ; Re-read matching entry
MOV DI,BX ; Leave BX,DX until call to NEXTENT
MOV ES,WORD PTR [CURBUF+2]
MOV SI,OFFSET DOSGROUP:NAME1
MOV CX,11
REP MOVSB ; Replace old name with new one
MOV DI,WORD PTR [CURBUF]
MOV ES:[DI.BUFDIRTY],1 ; Directory changed
PUSH SS
POP ES
MOV SI,OFFSET DOSGROUP:NAME3
MOV DI,OFFSET DOSGROUP:NAME1
MOV CX,13 ; Include attribute byte
REP MOVSB ; Copy name back into search buffer
invoke NEXTENT
JNC RENFIL
JMP FLUSHRET1
RENERR:
CALL FLUSHRET1
ERRET:
MOV AL,-1
RET
$FCB_RENAME ENDP
SUBTTL $FCB_OPEN -- SYSTEM CALL 15; OPEN A FILE
PAGE
procedure $FCB_OPEN,NEAR ; System call 15
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX point to an unopened FCB
; Function:
; Open indicated file and fill in FCB
; Returns:
; AL = -1 if no entries matched, otherwise 0
; FOR INTERNAL USE
; [CURBUF+2]:SI and [CURBUF+2]:BX Preserved
invoke GETFILE
ASSUME DS:DOSGROUP,ES:NOTHING
entry DOOPEN
; Enter here to perform $FCB_OPEN on file already found
; in directory. AH=device ID number, DS=CS, BX points to directory
; entry in [CURBUF], SI points to First Cluster field, and
; ES:DI point to the FCB to be opened. This entry point
; is used by $FCB_CREATE.
JC ERRET
PUSH SI
PUSH AX ; Save I/O driver number
XOR AL,AL
OR AH,AH
JS OPENDEV
MOV AL,[THISDRV]
MOV DS,WORD PTR [CURBUF+2]
ASSUME DS:NOTHING
INC AX
OPENDEV:
STOSB
XOR AX,AX
IF ZEROEXT
ADD DI,11
STOSW ; Zero low byte of extent field if ZERPEXT only
ELSE
ADD DI,12 ; Point to high half of CURRENT BLOCK field
STOSB ; Set it to zero (CP/M programs set low byte)
ENDIF
MOV AL,128 ; Default record size
STOSW ; Set record size
LODSW ; Get starting cluster
MOV DX,AX ; Save it for the moment
MOVSW ; Transfer size to FCB
MOVSW
MOV AX,[SI-8] ; Get date
STOSW ; Save date in FCB
MOV AX,[SI-10] ; Get time
STOSW ; Save it in FCB
POP AX ; Restore I/O driver number
POP SI
MOV AL,AH
OR AL,40H ; Not dirty
STOSB
JS SAVDEVPT ; If device, go save pointer to it
MOV AX,DX ; Restore starting cluster
STOSW ; first cluster
PUSH AX ; save cluster
XOR AX,AX
STOSW ; clus pos
POP AX ; last cluster
STOSB
MOV AL,AH
MOV AH,BYTE PTR [DIRSTART]
PUSH CX
MOV CL,4
SHL AH,CL
OR AL,AH
STOSB
MOV AX,[DIRSTART]
MOV CL,4
SHL AX,CL
POP CX
MOV AL,AH
STOSB
OPEN_RET:
XOR AX,AX
RET
SAVDEVPT:
ASSUME DS:DOSGROUP
LDS AX,[DEVPT]
ASSUME DS:NOTHING
STOSW
MOV ES:[DI],DS
JMP SHORT OPEN_RET
$FCB_OPEN ENDP
SUBTTL $FCB_CLOSE -- SYSTEM CALL 16; CLOSE FILE
PAGE
procedure $FCB_CLOSE,NEAR ; System call 16
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX point to an opened FCB
; Function:
; Close the indicated file
; Returns:
; AL = -1 if disk has been changed, otherwise 0
MOV DI,DX
CMP BYTE PTR [DI],-1 ; Check for extended FCB
JNZ NORMFCB3
ADD DI,7
NORMFCB3:
TEST [DI.fcb_DEVID],devid_file_clean+devid_device
; Allow only dirty files
JNZ OKRET1 ; can't close I/O device or not written
invoke MOVNAMENOSET
JC BADCLOSE ; Bad file name
entry FCB_CLOSE_INNER
PUSH DX
PUSH DS
MOV SI,DX
MOV BX,[SI.fcb_LSTCLUS+1]
MOV CL,4
SHR BX,CL
PUSH BX
PUSH SS
POP DS
ASSUME DS:DOSGROUP
invoke FATREAD
POP BX
invoke SETDIRSRCH
invoke FINDENTRY
POP ES
POP DI
JC BADCLOSE
LDS BX,[CURBUF]
ASSUME DS:NOTHING
; note that SI points to dir_first...
OR BYTE PTR [SI-dir_first+dir_attr],attr_archive
MOV CX,ES:[DI.fcb_FIRCLUS]
MOV [SI-dir_first+dir_first],CX
MOV DX,ES:WORD PTR [DI.fcb_FILSIZ]
MOV [SI-dir_first+dir_size_l],DX
MOV DX,ES:WORD PTR [DI.fcb_FILSIZ+2]
MOV [SI-dir_first+dir_size_h],DX
MOV DX,ES:[DI.fcb_FDATE]
MOV [SI-dir_first+dir_date],DX
MOV DX,ES:[DI.fcb_FTIME]
MOV [SI-dir_first+dir_time],DX
MOV [BX.BUFDIRTY],1
PUSH SS
POP DS
ASSUME DS:DOSGROUP
FLUSHRET1:
LES BP,[THISDPB]
MOV AL,ES:[BP.dpb_drive]
invoke FLUSHBUF
OKRET1:
XOR AL,AL
RET
BADCLOSE:
MOV AL,-1
RET
$FCB_CLOSE ENDP
SUBTTL $FCB_CREATE -- SYSTEM CALL 22; MAKE AND OPEN A NEW FILE
PAGE
procedure $FCB_CREATE,NEAR ; System call 22
ASSUME DS:NOTHING,ES:NOTHING
; Inputs:
; DS:DX point to an unopened FCB
; Function:
; If file does not exist, create it and open it
; If file exists, free up its contents and open the file
; Returns:
; AL = -1 if file cannot be created, otherwise 0
invoke MOVNAME
ASSUME ES:DOSGROUP
JC ERRET3
MOV DI,OFFSET DOSGROUP:NAME1
MOV CX,11
MOV AL,"?"
REPNE SCASB
JZ ERRET3
MOV BYTE PTR [CREATING],-1
PUSH DX
PUSH DS
invoke FINDNAME
ASSUME DS:DOSGROUP
NWENTY:
LES BP,[THISDPB]
ASSUME ES:NOTHING
JNC EXISTENT
invoke BUILDDIR
JC ERRPOP
invoke GETENT ; Point at that free entry
JMP SHORT FREESPOT
ERRPOP:
POP DS
POP DX
ASSUME DS:NOTHING
ERRET3:
JMP SHORT BADCLOSE
entry NEWENTRY
POP DX ; Return address
POP ES ; ES
POP CX ; DI
PUSH DX
PUSH CX
PUSH ES
JMP NWENTY
EXISTENT:
ASSUME DS:DOSGROUP
JNZ ERRPOP ; Error if attributes don't match
OR AH,AH ; Check if file is I/O device
JS OPENJMP ; If so, no action
PUSH DS
LDS DI,[CURBUF]
ASSUME DS:NOTHING
MOV CX,[SI] ; Get pointer to clusters
MOV SI,[DI.BUFSECNO]
POP DS
ASSUME DS:DOSGROUP
JCXZ FREESPOT
CMP CX,ES:[BP.dpb_max_cluster]
JA FREESPOT
SUB BX,DI
PUSH BX
PUSH SI ; Save sector number
MOV BX,CX
invoke RELEASE ; Free any data already allocated
POP DX
XOR AL,AL
invoke GETBUFFR
POP BX
ADD BX,WORD PTR [CURBUF]
FREESPOT:
TEST BYTE PTR [ATTRIB],attr_volume_id
JZ NOTVOLID
CMP BYTE PTR [VOLID],0
JNZ ERRPOP ; Can't create a second volume ID
NOTVOLID:
MOV ES,WORD PTR [CURBUF+2]
MOV DI,BX
MOV SI,OFFSET DOSGROUP:NAME1
MOV CX,5
MOVSB
REP MOVSW
MOV AL,[ATTRIB]
STOSB
MOV CL,5
XOR AX,AX
REP STOSW
invoke DATE16
XCHG AX,DX
STOSW
XCHG AX,DX
STOSW
XOR AX,AX
PUSH DI
STOSW
STOSW
STOSW
MOV SI,WORD PTR [CURBUF]
MOV ES:[SI.BUFDIRTY],1
LES BP,[THISDPB]
MOV AL,ES:[BP.dpb_drive]
PUSH AX
PUSH BX
invoke FLUSHBUF
POP BX
POP AX
POP SI
MOV AH,AL ; Get I/O driver number back
OPENJMP:
CLC ; Clear carry so OPEN won't fail
POP ES
POP DI
ASSUME ES:NOTHING
JMP DOOPEN
$FCB_CREATE ENDP
do_ext
CODE ENDS
END

BIN
View File
Binary file not shown.
+1424
View File
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
TITLE Message file for MS-DOS SYS Program
FALSE EQU 0
TRUE EQU NOT FALSE
INCLUDE DOSSYM.ASM
Message MACRO label,text
PUBLIC label,label&Len
label DB text
label&Len DW $-label
ENDM
IBMJAPVER EQU FALSE
CONST SEGMENT PUBLIC BYTE
; only this message must be terminated with a $
PUBLIC BadVer
BADVER DB "Incorrect DOS version",13,10,"$"
IF IBMJAPVER
Message BadDisk,<"Destination disk cannot be booted">
ENDIF
Message BadDrv,<"Invalid drive specification">
Message BadParm,<"Invalid parameter">
Message NoDest,<"No room for system on destination disk">
Message BadSiz,<"Incompatible system size">
Message Done,<"System transferred">
PUBLIC GetSys,SysDrv,GetSysLen
GETSYS DB "Insert system disk in drive "
SYSDRV DB "A",13,10
DB "and strike any key when ready",13,10
GetSysLen DW GetSysLen-GetSys
CONST ENDS
DATA SEGMENT BYTE PUBLIC
DATA ENDS
CODE SEGMENT
DG GROUP CODE,CONST,DATA
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
CODE ENDS
END

+1088
View File
File diff suppressed because it is too large Load Diff
+522
View File
@@ -0,0 +1,522 @@
TITLE PART2 - COMMAND Transient routines.
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
CODERES SEGMENT PUBLIC
EXTRN LODCOM1:NEAR
CODERES ENDS
DATARES SEGMENT PUBLIC
EXTRN PARENT:WORD,IO_SAVE:WORD,PERMCOM:BYTE
EXTRN PIPEFLAG:BYTE,ENVIRSEG:WORD
if ibmver
EXTRN SYS_CALL:DWORD
endif
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN PATH_TEXT:BYTE,PROMPT_TEXT:BYTE
EXTRN BADDEV:BYTE,SYNTMES:BYTE,ENVERR:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN CURDRV:BYTE,DIRCHAR:BYTE,PWDBUF:BYTE
EXTRN INTERNATVARS:BYTE,RESSEG:WORD,TPA:WORD
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN CERROR:NEAR,ZPRINT:NEAR
EXTRN CRLF2:NEAR,SCANOFF:NEAR,FREE_TPA:NEAR,ALLOC_TPA:NEAR
EXTRN OUT:NEAR,DRVBAD:NEAR,SETPATH:NEAR,PRINT:NEAR
EXTRN FCB_TO_ASCZ:NEAR
PUBLIC PRINT_DRIVE,$EXIT,MOVE_NAME
PUBLIC UPCONV,ADD_PROMPT,CTTY,PRINT_DEFAULT_DIRECTORY
PUBLIC ADD_NAME_TO_ENVIRONMENT,PWD,SCAN_DOUBLE_NULL
PUBLIC FIND_NAME_IN_ENVIRONMENT,STORE_CHAR
PUBLIC FIND_PATH,DELETE_PATH,FIND_PROMPT
PUBLIC SCASB2
IF KANJI
PUBLIC TESTKANJ
ENDIF
BREAK <Environment utilities>
ASSUME DS:TRANGROUP
ADD_PROMPT:
CALL DELETE_PROMPT ; DELETE ANY EXISTING PROMPT
CALL SCAN_DOUBLE_NULL
ADD_PROMPT2:
PUSH SI
CALL GETARG
POP SI
retz ; PRE SCAN FOR ARGUMENTS
CALL MOVE_NAME ; MOVE IN NAME
CALL GETARG
JMP SHORT ADD_NAME
;
; Input: DS:SI points to a CR terminated string
; Output: carry flag is set if no room
; otherwise name is added to environment
;
ADD_NAME_TO_ENVIRONMENT:
CALL GETARG
JZ DISP_ENV
;
; check if line contains exactly one equals sign
;
XOR BX,BX ;= COUNT IS 0
PUSH SI ;SAVE POINTER TO BEGINNING OF LINE
EQLP:
LODSB ;GET A CHAR
CMP AL,13 ;IF CR WE'RE ALL DONE
JZ QUEQ
CMP AL,"=" ;LOOK FOR = SIGN
JNZ EQLP ;NOT THERE, GET NEXT CHAR
INC BL ;OTHERWISE INCREMENT EQ COUNT
CMP BYTE PTR [SI],13 ;LOOK FOR CR FOLLOWING = SIGN
JNZ EQLP
INC BH ;SET BH=1 MEANS NO PARAMETERS
JMP EQLP ;AND LOOK FOR MORE
QUEQ:
POP SI ;RESTORE BEGINNING OF LINE
DEC BL ;ZERO FLAG MEANS ONLY ONE EQ
JZ ONEQ ;GOOD LINE
MOV DX,OFFSET TRANGROUP:SYNTMES
JMP CERROR
ONEQ:
PUSH BX
CALL DELETE_NAME_IN_ENVIRONMENT
POP BX
DEC BH
retz
CALL SCAN_DOUBLE_NULL
CALL MOVE_NAME
ADD_NAME:
LODSB
CMP AL,13
retz
CALL STORE_CHAR
JMP ADD_NAME
DISP_ENV:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV DS,[ENVIRSEG]
ASSUME DS:NOTHING
XOR SI,SI
PENVLP:
CMP BYTE PTR [SI],0
retz
MOV DX,SI
CALL ZPRINT
CALL CRLF2
PENVLP2:
LODSB
OR AL,AL
JNZ PENVLP2
JMP PENVLP
ASSUME DS:TRANGROUP
DELETE_PATH:
MOV SI,OFFSET TRANGROUP:PATH_TEXT
JMP SHORT DELETE_NAME_IN_environment
DELETE_PROMPT:
MOV SI,OFFSET TRANGROUP:PROMPT_TEXT
DELETE_NAME_IN_environment:
;
; Input: DS:SI points to a "=" terminated string
; Output: carry flag is set if name not found
; otherwise name is deleted
;
PUSH SI
PUSH DS
CALL FIND ; ES:DI POINTS TO NAME
JC DEL1
MOV SI,DI ; SAVE IT
CALL SCASB2 ; SCAN FOR THE NUL
XCHG SI,DI
CALL GETENVSIZ
SUB CX,SI
PUSH ES
POP DS ; ES:DI POINTS TO NAME, DS:SI POINTS TO NEXT NAME
REP MOVSB ; DELETE THE NAME
DEL1:
POP DS
POP SI
return
FIND_PATH:
MOV SI,OFFSET TRANGROUP:PATH_TEXT
JMP SHORT FIND_NAME_IN_environment
FIND_PROMPT:
MOV SI,OFFSET TRANGROUP:PROMPT_TEXT
FIND_NAME_IN_environment:
;
; Input: DS:SI points to a "=" terminated string
; Output: ES:DI points to the arguments in the environment
; zero is set if name not found
; carry flag is set if name not valid format
;
CALL FIND ; FIND THE NAME
retc ; CARRY MEANS NOT FOUND
JMP SCASB1 ; SCAN FOR = SIGN
;
; On return of FIND1, ES:DI points to beginning of name
;
FIND:
CLD
CALL COUNT0 ; CX = LENGTH OF NAME
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV ES,[ENVIRSEG]
ASSUME ES:NOTHING
XOR DI,DI
FIND1:
PUSH CX
PUSH SI
PUSH DI
FIND11:
LODSB
IF KANJI
CALL TESTKANJ
JZ NOTKANJ3
DEC SI
LODSW
INC DI
INC DI
CMP AX,ES:[DI-2]
JNZ FIND12
DEC CX
LOOP FIND11
JMP SHORT FIND12
NOTKANJ3:
ENDIF
CALL UPCONV
INC DI
CMP AL,ES:[DI-1]
JNZ FIND12
LOOP FIND11
FIND12:
POP DI
POP SI
POP CX
retz
PUSH CX
CALL SCASB2 ; SCAN FOR A NUL
POP CX
CMP BYTE PTR ES:[DI],0
JNZ FIND1
STC ; INDICATE NOT FOUND
return
COUNT0:
PUSH DS
POP ES
MOV DI,SI
COUNT1:
PUSH DI ; COUNT NUMBER OF CHARS UNTIL "="
CALL SCASB1
JMP SHORT COUNTX
COUNT2:
PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL
CALL SCASB2
COUNTX:
POP CX
SUB DI,CX
XCHG DI,CX
return
MOVE_NAME:
CMP BYTE PTR DS:[SI],13
retz
LODSB
IF KANJI
CALL TESTKANJ
JZ NOTKANJ1
CALL STORE_CHAR
LODSB
CALL STORE_CHAR
JMP SHORT MOVE_NAME
NOTKANJ1:
ENDIF
CALL UPCONV
CALL STORE_CHAR
CMP AL,"="
JNZ MOVE_NAME
return
GETARG:
MOV SI,80H
LODSB
OR AL,AL
retz
CALL SCANOFF
CMP AL,13
return
SCAN_DOUBLE_NULL:
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV ES,[ENVIRSEG]
ASSUME ES:NOTHING
XOR DI,DI
SDN1:
CALL SCASB2
CMP BYTE PTR ES:[DI],0
JNZ SDN1
return
SCASB1:
MOV AL,"=" ; SCAN FOR AN =
JMP SHORT SCASBX
SCASB2:
XOR AL,AL ; SCAN FOR A NUL
SCASBX:
MOV CX,100H
REPNZ SCASB
return
IF KANJI
TESTKANJ:
CMP AL,81H
JB NOTLEAD
CMP AL,9FH
JBE ISLEAD
CMP AL,0E0H
JB NOTLEAD
CMP AL,0FCH
JBE ISLEAD
NOTLEAD:
PUSH AX
XOR AX,AX ;Set zero
POP AX
return
ISLEAD:
PUSH AX
XOR AX,AX ;Set zero
INC AX ;Reset zero
POP AX
return
ENDIF
UPCONV:
CMP AL,"a"
JB RET22C
CMP AL,"z"
JA RET22C
SUB AL,20H ; Lower-case changed to upper-case
RET22C:
CALL DWORD PTR CS:[INTERNATVARS.Map_call]
return
;
; STORE A CHAR IN environment, GROWING IT IF NECESSARY
;
STORE_CHAR:
PUSH CX
PUSH BX
CALL GETENVSIZ
MOV BX,CX
SUB BX,2 ; SAVE ROOM FOR DOUBLE NULL
CMP DI,BX
JB STORE1
PUSH AX
PUSH CX
PUSH BX ; Save Size of environment
CALL FREE_TPA
POP BX
ADD BX,2 ; Recover true environment size
MOV CL,4
SHR BX,CL ; Convert back to paragraphs
INC BX ; Try to grow environment by one para
MOV AH,SETBLOCK
INT int_command
PUSHF
PUSH ES
MOV ES,[RESSEG]
CALL ALLOC_TPA
POP ES
POPF
POP CX
POP AX
JNC STORE1
MOV DX,OFFSET TRANGROUP:ENVERR
JMP CERROR
STORE1:
STOSB
MOV WORD PTR ES:[DI],0 ; NULL IS AT END
POP BX
POP CX
return
GETENVSIZ:
;Get size of environment in bytes, rounded up to paragraph boundry
;ES has environment segment
;Size returned in CX, all other registers preserved
PUSH ES
PUSH AX
MOV AX,ES
DEC AX ;Point at arena
MOV ES,AX
MOV AX,ES:[arena_size]
MOV CL,4
SHL AX,CL ;Convert to bytes
MOV CX,AX
POP AX
POP ES
return
PRINT_DRIVE:
MOV AH,GET_DEFAULT_DRIVE
INT int_command
ADD AL,"A"
JMP OUT
ASSUME DS:TRANGROUP,ES:TRANGROUP
PWD:
CALL PRINT_DIRECTORY
CALL CRLF2
return
PRINT_DEFAULT_DIRECTORY:
MOV BYTE PTR DS:[FCB],0
PRINT_DIRECTORY:
MOV DL,DS:[FCB]
MOV AL,DL
ADD AL,'@'
CMP AL,'@'
JNZ GOTDRIVE
ADD AL,[CURDRV]
INC AL
GOTDRIVE:
PUSH AX
MOV SI,OFFSET TRANGROUP:PWDBUF+3
MOV AH,CURRENT_DIR
INT int_command
JNC DPBISOK
PUSH CS
POP DS
JMP DRVBAD
DPBISOK:
MOV DI,OFFSET TRANGROUP:PWDBUF
MOV DX,DI
POP AX
MOV AH,DRVCHAR
STOSW
MOV AL,[DIRCHAR]
STOSB
JMP ZPRINT
$EXIT:
PUSH ES
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV AX,[PARENT]
MOV WORD PTR ES:[PDB_Parent_PID],AX
IF IBM
CMP [PERMCOM],0
JNZ NORESETVEC ;Don't reset the vector if a PERMCOM
LDS DX,DWORD PTR ES:[SYS_CALL]
ASSUME DS:NOTHING
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) + INT_COMMAND
INT int_command
NORESETVEC:
ENDIF
POP ES
ASSUME ES:TRANGROUP
MOV ES,[TPA]
MOV AH,DEALLOC
INT int_command ; Now running in "free" space
MOV AX,(EXIT SHL 8)
INT int_command
CTTY:
CALL SETPATH ; Get spec
MOV AX,(OPEN SHL 8) OR 2 ; Read and write
INT int_command ; Open new device
JC ISBADDEV
MOV BX,AX
MOV AX,IOCTL SHL 8
INT int_command
TEST DL,80H
JNZ DEVISOK
MOV AH,CLOSE ; Close initial handle
INT int_command
ISBADDEV:
MOV DX,OFFSET TRANGROUP:BADDEV
CALL PRINT
JMP RESRET
DEVISOK:
XOR DH,DH
OR DL,3 ; Make sure has CON attributes
MOV AX,(IOCTL SHL 8) OR 1
INT int_command
PUSH BX ; Save handle
MOV CX,3
XOR BX,BX
ICLLOOP: ; Close basic handles
MOV AH,CLOSE
INT int_command
INC BX
LOOP ICLLOOP
POP BX ; Get handle
MOV AH,XDUP
INT int_command ; Dup it to 0
MOV AH,XDUP
INT int_command ; Dup to 1
MOV AH,XDUP
INT int_command ; Dup to 2
MOV AH,CLOSE ; Close initial handle
INT int_command
RESRET:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
PUSH DS
MOV AX,WORD PTR DS:[PDB_JFN_Table] ; Get new 0 and 1
MOV [IO_SAVE],AX
MOV AX,OFFSET RESGROUP:LODCOM1
PUSH AX
ZMMMM PROC FAR
RET ; Force header to be checked
ZMMMM ENDP
TRANCODE ENDS
END
+677
View File
@@ -0,0 +1,677 @@
TITLE PART3 - COMMAND Transient routines.
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
DATARES SEGMENT PUBLIC
EXTRN BATCH:WORD,BATLOC:DWORD
EXTRN RETCODE:WORD,ECHOFLAG:BYTE
EXTRN SINGLECOM:WORD,FORFLAG:BYTE,UFORDRV:BYTE
EXTRN FORSET:BYTE,FORCOM:BYTE,FORVAR:BYTE,FORPTR:WORD
EXTRN FORUFCB:BYTE,FORFCB:BYTE,RE_INSTR:BYTE,RE_OUT_APP:BYTE
EXTRN RE_OUTSTR:BYTE,PIPEFLAG:BYTE
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN BADLAB:BYTE,SYNTMES:BYTE,FORNESTMES:BYTE
EXTRN NOTFND:BYTE,FULDIR:BYTE,IFTAB:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN BATHAND:WORD,RESSEG:WORD,DIRBUF:BYTE,COMBUF:BYTE
EXTRN GOTOLEN:WORD,IFNOTFLAG:BYTE
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN SCANOFF:NEAR,DOCOM:NEAR,DOCOM1:NEAR,CERROR:NEAR
EXTRN PRINT:NEAR,TCOMMAND:NEAR,DELIM:NEAR,GETBATBYT:NEAR
EXTRN FCB_TO_ASCZ:NEAR
PUBLIC GOTO,$IF,IFERLEV,SHIFT,IFEXISTS
PUBLIC STRCOMP,MesTran,$FOR,IFNOT
PUBLIC FORPROC,BATOPEN,BATCLOSE
PUBLIC IOSET,TESTDOREIN,TESTDOREOUT
ASSUME DS:RESGROUP
FORTERM:
MOV [FORFLAG],0
CMP [SINGLECOM],0FF00H
JNZ NOFORP2
MOV [SINGLECOM],-1 ; Cause a terminate
NOFORP2:
JMP TCOMMAND
FORPROC:
ASSUME DS:RESGROUP
CMP [FORUFCB],-1
JZ NORMFOR
MOV DX,OFFSET TRANGROUP:DIRBUF
PUSH DS
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV AH,SET_DMA
INT int_command
POP DS
ASSUME DS:RESGROUP
MOV DX,OFFSET RESGROUP:FORFCB
MOV AH,DIR_SEARCH_NEXT
CMP [FORUFCB],0
JZ DOFORSRCH
MOV AH,DIR_SEARCH_FIRST
MOV [FORUFCB],0
DOFORSRCH:
INT int_command
OR AL,AL
JNZ FORTERM
PUSH DS
POP ES
ASSUME ES:RESGROUP
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV SI,OFFSET TRANGROUP:DIRBUF
MOV DI,OFFSET RESGROUP:FORSET
MOV [FORPTR],DI
LODSB ;Get drive spec
ADD AL,'@'
CMP AL,'@'
JZ NDRV8
CMP [UFORDRV],0
JZ NDRV8
MOV AH,':'
STOSW
NDRV8:
CALL FCB_TO_ASCZ
MOV BYTE PTR ES:[DI-1],0DH
PUSH ES
POP DS
ASSUME DS:RESGROUP
NORMFOR:
PUSH CS
POP ES
ASSUME ES:TRANGROUP
MOV BX,[FORPTR]
CMP BYTE PTR [BX],0
JZ FORTERM
MOV SI,BX
PARMSUB0:
LODSB
CMP AL,0DH
JNZ PARMSUB0
MOV DX,SI ; DX points to next parm
MOV SI,OFFSET RESGROUP:FORCOM
MOV DI,OFFSET TRANGROUP:COMBUF+2
XOR CX,CX
TFORCOM:
LODSB
CMP AL,'%'
JNZ NOFORPARM
MOV AH,[FORVAR]
CMP AH,[SI]
JNZ NOFORPARM
INC SI
PUSH SI
MOV SI,BX
PARMSUB:
LODSB
CMP AL,0DH
JZ PARMSUBDONE
INC CX
STOSB
JMP SHORT PARMSUB
PARMSUBDONE:
POP SI ; Get back command line pointer
JMP TFORCOM
NOFORPARM:
STOSB
INC CX
CMP AL,0DH
JNZ TFORCOM
DEC CX
MOV [COMBUF+1],CL
MOV [FORPTR],DX ; Point to next set element
TEST [ECHOFLAG],-1
PUSH CS
POP DS
ASSUME DS:TRANGROUP
JZ NOECHO3
MOV BYTE PTR ES:[DI-1],'$'
MOV DX,OFFSET TRANGROUP:COMBUF+2
CALL PRINT
MOV BYTE PTR ES:[DI-1],0DH
JMP DOCOM
NOECHO3:
JMP DOCOM1
ASSUME DS:TRANGROUP,ES:TRANGROUP
FORNESTERR:
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV DX,OFFSET TRANGROUP:FORNESTMES
CMP [SINGLECOM],0FF00H
JNZ NOFORP3
MOV [SINGLECOM],-1 ; Cause termination
NOFORP3:
POP DS
ASSUME DS:TRANGROUP
JMP CERROR
$FOR:
MOV SI,81H
XOR CX,CX
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV DI,OFFSET RESGROUP:FORSET
XOR AL,AL
MOV [UFORDRV],AL
XCHG AL,[FORFLAG]
OR AL,AL
JNZ FORNESTERR
MOV [FORPTR],DI
MOV [FORUFCB],-1
CALL SCANOFF
LODSW
CMP AL,'%'
JNZ FORERRORJ
MOV [FORVAR],AH
CALL SCANOFF
CMP AL,0DH
JZ FORERRORJ2
LODSW
CMP AX,('N' SHL 8) OR 'I'
JZ FOROK1
CMP AX,('n' SHL 8) OR 'i'
JNZ FORERRORJ
FOROK1:
CALL SCANOFF
LODSB
CMP AL,'('
JNZ FORERRORJ
CALL SCANOFF
CMP AL,')' ; Special check for null set
JNZ FORSETLP
MOV DS,[RESSEG]
JMP FORTERM
FORSETLP:
LODSB
CMP AL,0DH
FORERRORJ2:
JZ FORERRORJ3
CMP AL,')'
JZ FORSETEND
STOSB
CMP AL,'*'
JZ SETFORSCAN
CMP AL,'?'
JNZ NOFORSCAN
SETFORSCAN:
MOV [FORUFCB],1
NOFORSCAN:
CALL DELIM
JNZ FORSETLP
MOV BYTE PTR ES:[DI-1],0DH
CALL SCANOFF
JMP FORSETLP
FORSETEND:
MOV AX,000DH
CMP BYTE PTR ES:[DI-1],0DH
JNZ FORSETTERM
XOR AX,AX
FORSETTERM:
STOSW
CALL SCANOFF
LODSW
CMP AX,('O' SHL 8) OR 'D'
JZ FOROK2
CMP AX,('o' SHL 8) OR 'd'
FORERRORJ:
JNZ FORERROR
FOROK2:
CALL SCANOFF
CMP AL,0DH
FORERRORJ3:
JZ FORERROR
MOV DI,OFFSET RESGROUP:FORCOM
FORCOMLP:
LODSB
STOSB
CMP AL,0DH
JNZ FORCOMLP
INC [FORFLAG]
CMP [SINGLECOM],-1
JNZ NOFORP
MOV [SINGLECOM],0FF00H ; Flag single command for
NOFORP:
CMP [FORUFCB],1
retnz
PUSH ES
POP DS
ASSUME DS:RESGROUP
MOV DI,OFFSET RESGROUP:FORFCB
MOV SI,OFFSET RESGROUP:FORSET
CMP BYTE PTR [SI+1],':'
JNZ NOSETUDRV
INC [UFORDRV]
NOSETUDRV:
MOV AX,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
return
ASSUME DS:TRANGROUP,ES:TRANGROUP
IFERRORP:
POP AX
IFERROR:
FORERROR:
MOV DX,OFFSET TRANGROUP:SYNTMES
JMP CERROR
$IF:
MOV [IFNOTFLAG],0
MOV SI,81H
IFREENT:
CALL SCANOFF
CMP AL,0DH
JZ IFERROR
MOV BP,SI
MOV DI,OFFSET TRANGROUP:IFTAB ; Prepare to search if table
MOV CH,0
IFINDCOM:
MOV SI,BP
MOV CL,[DI]
INC DI
JCXZ IFSTRING
JMP SHORT FIRSTCOMP
IFCOMP:
JNZ IFDIF
FIRSTCOMP:
LODSB
MOV AH,ES:[DI]
INC DI
CMP AL,AH
JZ IFLP
OR AH,20H ; Try lower case
CMP AL,AH
IFLP:
LOOP IFCOMP
IFDIF:
LAHF
ADD DI,CX ; Bump to next position without affecting flags
MOV BX,[DI] ; Get handler address
INC DI
INC DI
SAHF
JNZ IFINDCOM
LODSB
CMP AL,0DH
IFERRORJ:
JZ IFERROR
CALL DELIM
JNZ IFINDCOM
CALL SCANOFF
JMP BX
IFNOT:
NOT [IFNOTFLAG]
JMP IFREENT
IFSTRING:
PUSH SI
XOR CX,CX
FIRST_STRING:
LODSB
CMP AL,0DH
JZ IFERRORP
CALL DELIM
JZ EQUAL_CHECK
INC CX
JMP SHORT FIRST_STRING
EQUAL_CHECK:
CMP AL,'='
JZ EQUAL_CHECK2
CMP AL,0DH
JZ IFERRORP
LODSB
JMP SHORT EQUAL_CHECK
EQUAL_CHECK2:
LODSB
CMP AL,'='
JNZ IFERRORP
CALL SCANOFF
CMP AL,0DH
JZ IFERRORP
POP DI
REPE CMPSB
JZ MATCH
CMP BYTE PTR [SI-1],0DH
JZ IFERRORJ
SKIPSTRINGEND:
LODSB
NOTMATCH:
CMP AL,0DH
IFERRORJ2:
JZ IFERRORJ
CALL DELIM
JNZ SKIPSTRINGEND
MOV AL,-1
JMP SHORT IFRET
MATCH:
LODSB
CALL DELIM
JNZ NOTMATCH
XOR AL,AL
JMP SHORT IFRET
IFEXISTS:
MOV DI,OFFSET TRANGROUP:DIRBUF
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H
INT int_command
MOV AH,FCB_OPEN
MOV DX,DI
INT int_command
IFRET:
TEST [IFNOTFLAG],-1
JZ REALTEST
NOT AL
REALTEST:
OR AL,AL
JZ IFTRUE
JMP TCOMMAND
IFTRUE:
CALL SCANOFF
MOV CX,SI
SUB CX,81H
SUB DS:[80H],CL
MOV CL,DS:[80H]
MOV [COMBUF+1],CL
MOV DI,OFFSET TRANGROUP:COMBUF+2
REP MOVSB
MOV AL,0DH
STOSB
JMP DOCOM1
IFERLEV:
MOV BH,10
XOR BL,BL
GETNUMLP:
LODSB
CMP AL,0DH
JZ IFERRORJ2
CALL DELIM
JZ GOTNUM
SUB AL,'0'
XCHG AL,BL
MUL BH
ADD AL,BL
XCHG AL,BL
JMP SHORT GETNUMLP
GOTNUM:
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV AH,BYTE PTR [RETCODE]
POP DS
ASSUME DS:TRANGROUP
XOR AL,AL
CMP AH,BL
JAE IFRET
DEC AL
JMP SHORT IFRET
ASSUME DS:TRANGROUP
SHIFT:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV AX,[BATCH]
TEST AX,-1
retz
MOV ES,AX
MOV DS,AX
ASSUME DS:NOTHING,ES:NOTHING
XOR CX,CX
MOV AX,CX
MOV DI,CX
DEC CX
REPNZ SCASB
MOV SI,DI
INC SI
INC SI
MOV CX,9
REP MOVSW ; Perform shift of existing parms
CMP WORD PTR [DI],-1
retz ; No new parm
MOV SI,[DI]
MOV WORD PTR [DI],-1 ; Assume no parm
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
SKIPCRLP:
LODSB
CMP AL,0DH
JNZ SKIPCRLP
CMP BYTE PTR [SI],0
retz ; End of parms
MOV ES:[DI],SI ; Pointer to next parm as %9
return
ASSUME DS:TRANGROUP,ES:TRANGROUP
GOTO:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
TEST [BATCH],-1
retz ; If not in batch mode, a nop
XOR DX,DX
MOV WORD PTR [BATLOC],DX ; Back to start
MOV WORD PTR [BATLOC+2],DX
CALL BATOPEN ; Find the batch file
MOV DI,FCB+1 ; Get the label
MOV CX,11
MOV AL,' '
REPNE SCASB
JNZ NOINC
INC CX
NOINC:
SUB CX,11
NEG CX
MOV [GOTOLEN],CX
CALL GETBATBYT
CMP AL,':'
JZ CHKLABEL
LABLKLP: ; Look for the label
CALL GETBATBYT
CMP AL,0AH
JNZ LABLKTST
CALL GETBATBYT
CMP AL,':'
JZ CHKLABEL
LABLKTST:
TEST [BATCH],-1
JNZ LABLKLP
CALL BATCLOSE
PUSH CS
POP DS
MOV DX,OFFSET TRANGROUP:BADLAB
JMP CERROR
CHKLABEL:
MOV DI,FCB+1
MOV CX,[GOTOLEN]
NEXTCHRLP:
PUSH CX
CALL GETBATBYT
POP CX
OR AL,20H
CMP AL,ES:[DI]
JNZ TRYUPPER
JMP SHORT NEXTLABCHR
TRYUPPER:
SUB AL,20H
CMP AL,ES:[DI]
JNZ LABLKTST
NEXTLABCHR:
INC DI
LOOP NEXTCHRLP
CALL GETBATBYT
CMP AL,' '
JA LABLKTST
CMP AL,0DH
JZ SKIPLFEED
TONEXTBATLIN:
CALL GETBATBYT
CMP AL,0DH
JNZ TONEXTBATLIN
SKIPLFEED:
CALL GETBATBYT
BATCLOSE:
MOV BX,CS:[BATHAND]
MOV AH,CLOSE
INT int_command
return
BATOPEN:
;Open the BATCH file, If open fails, AL is drive of batch file (A=1)
ASSUME DS:RESGROUP,ES:TRANGROUP
PUSH DS
MOV DS,[BATCH]
ASSUME DS:NOTHING
XOR DX,DX
MOV AX,OPEN SHL 8
INT int_command ; Open the batch file
JC SETERRDL
POP DS
ASSUME DS:RESGROUP
MOV [BATHAND],AX
MOV BX,AX
MOV DX,WORD PTR [BATLOC]
MOV CX,WORD PTR [BATLOC+2]
MOV AX,LSEEK SHL 8 ; Go to the right spot
INT int_command
return
SETERRDL:
MOV BX,DX
MOV AL,[BX] ; Get drive spec
SUB AL,'@' ; A = 1
POP DS
STC ; SUB mucked over carry
return
MESTRAN:
ASSUME DS:NOTHING,ES:NOTHING
LODSB
CMP AL,"$"
retz
STOSB
JMP MESTRAN
IOSET:
; ALL REGISTERS PRESERVED
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
PUSH DS
PUSH DX
PUSH AX
PUSH BX
PUSH CX
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
CMP [PIPEFLAG],0
JNZ NOREDIR ; Don't muck up the pipe
CALL TESTDOREIN
CALL TESTDOREOUT
NOREDIR:
POP CX
POP BX
POP AX
POP DX
POP DS
ASSUME DS:NOTHING
return
TESTDOREIN:
ASSUME DS:RESGROUP
CMP [RE_INSTR],0
retz
MOV DX,OFFSET RESGROUP:RE_INSTR
MOV AX,(OPEN SHL 8)
INT int_command
MOV DX,OFFSET TRANGROUP:NOTFND
JC REDIRERR
MOV BX,AX
MOV AL,0FFH
XCHG AL,[BX.PDB_JFN_Table]
MOV DS:[PDB_JFN_Table],AL
return
REDIRERR:
PUSH CS
POP DS
JMP CERROR
TESTDOREOUT:
ASSUME DS:RESGROUP
CMP [RE_OUTSTR],0
JZ NOREOUT
CMP [RE_OUT_APP],0
JZ REOUTCRT
MOV DX,OFFSET RESGROUP:RE_OUTSTR
MOV AX,(OPEN SHL 8) OR 1
INT int_command
JC REOUTCRT
XOR DX,DX
XOR CX,CX
MOV BX,AX
MOV AX,(LSEEK SHL 8) OR 2
INT int_command
JMP SHORT SET_REOUT
REOUTCRT:
MOV DX,OFFSET RESGROUP:RE_OUTSTR
XOR CX,CX
MOV AH,CREAT
INT int_command
MOV DX,OFFSET TRANGROUP:FULDIR
JC REDIRERR
MOV BX,AX
SET_REOUT:
MOV AL,0FFH
XCHG AL,[BX.PDB_JFN_Table]
MOV DS:[PDB_JFN_Table+1],AL
NOREOUT:
return
STRCOMP:
; Compare ASCIZ DS:SI with ES:DI.
; SI,DI destroyed.
CMPSB
retnz ; Strings not equal
cmp byte ptr [SI-1],0 ; Hit NUL terminator?
retz ; Yes, strings equal
jmp short STRCOMP ; Equal so far, keep going
TRANCODE ENDS
END
+1002
View File
File diff suppressed because it is too large Load Diff
+953
View File
@@ -0,0 +1,953 @@
TITLE PART5 - COMMAND Transient routines.
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
CODERES SEGMENT PUBLIC
IF IBMVER
EXTRN EXEC_WAIT:NEAR
ENDIF
CODERES ENDS
DATARES SEGMENT PUBLIC
EXTRN BATCH:WORD,BATLOC:DWORD,BATBYT:BYTE,ECHOFLAG:BYTE
EXTRN SINGLECOM:WORD,RE_OUTSTR:BYTE,PIPEFLAG:BYTE,PIPEPTR:WORD
EXTRN RE_INSTR:BYTE,RE_OUT_APP:BYTE,PARMBUF:BYTE,PIPESTR:BYTE
EXTRN LTPA:WORD,ENVIRSEG:WORD
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN PIPEEMES:BYTE,NULPATH:BYTE,NOSPACE:BYTE
EXTRN DBACK:BYTE,PROMPT_TABLE:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN PATHCNT:WORD,PATHPOS:WORD,PATHSW:WORD
EXTRN DESTISDIR:BYTE,DESTTAIL:WORD,DESTINFO:BYTE
EXTRN BATHAND:WORD,RESSEG:WORD,TPA:WORD,SWITCHAR:BYTE
EXTRN BYTCNT:WORD,COMBUF:BYTE,DIRBUF:BYTE,CHARBUF:BYTE
IF KANJI
EXTRN KPARSE:BYTE
ENDIF
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
IF KANJI
EXTRN TESTKANJ:NEAR
ENDIF
EXTRN CERROR:NEAR,UPCONV:NEAR,PIPEERRSYN:NEAR,SETREST1:NEAR
EXTRN SWITCH:NEAR,SETREST1:NEAR,BATCLOSE:NEAR,MOVE_NAME:NEAR
EXTRN FIND_PROMPT:NEAR,FIND_PATH:NEAR,DELETE_PATH:NEAR
EXTRN STORE_CHAR:NEAR,SCAN_DOUBLE_NULL:NEAR,SCASB2:NEAR
EXTRN PRINT_DRIVE:NEAR,SAVUDIR:NEAR,CRLF2:NEAR,PAUSE:NEAR
PUBLIC PRINT_B,PRINT_G,DISPSIZE,GETNUM,OUTBYTE
PUBLIC DELIM,OUT,OUT2,SETPATH,PATHCRUNCH
PUBLIC CRPRINT,SCANOFF,FCB_TO_ASCZ
PUBLIC PRINT_L,PATH,PATHCHRCMP,PRINT_ESC,PRINT_BACK
PUBLIC PRINT_EQ,PRINT,ZPRINT,PRINT_PROMPT
PUBLIC DISP32BITS,ERROR_PRINT,ERROR_OUTPUT
PUBLIC FREE_TPA,ALLOC_TPA,PRESCAN,GETBATBYT
FREE_TPA:
ASSUME DS:TRANGROUP,ES:NOTHING
PUSH ES
MOV ES,[TPA]
MOV AH,DEALLOC
INT int_command ; Make lots of free memory
POP ES
return
ALLOC_TPA:
ASSUME DS:TRANGROUP,ES:RESGROUP
MOV BX,0FFFFH ; Re-allocate the transient
MOV AH,ALLOC
INT int_command
MOV AH,ALLOC
INT int_command
MOV [LTPA],AX ; Re-compute evrything
MOV [TPA],AX
MOV BX,AX
MOV AX,CS
SUB AX,BX
MOV DX,16
MUL DX
OR DX,DX
JZ SAVSIZ2
MOV AX,-1
SAVSIZ2:
MOV [BYTCNT],AX
return
PRESCAN: ; Cook the input buffer
ASSUME DS:TRANGROUP,ES:TRANGROUP
XOR CX,CX
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV SI,OFFSET TRANGROUP:COMBUF+2
MOV DI,SI
CountQuotes:
LODSB ; get a byte
CMP AL,22h ; is it a quote?
JNZ CountEnd ; no, try for end of road
INC CH ; bump count
JMP CountQuotes ; go get next char
CountEnd:
CMP AL,13 ; end of road?
JNZ CountQuotes ; no, go back for next char
IF KANJI
PUSH CX ; save count
MOV SI,DI ; get back beginning of buffer
KanjiScan:
LODSB ; get a byte
CALL TestKanj ; is it a leadin byte
JZ KanjiQuote ; no, check for quotes
MOV AH,AL ; save leadin
LODSB ; get trailing byte
CMP AX,8140h ; is it Kanji space
JNZ KanjiScan ; no, go get next
MOV [SI-2],2020h ; replace with spaces
JMP KanjiScan ; go get next char
KanjiQuote:
CMP AL,22h ; beginning of quoted string
JNZ KanjiEnd ; no, check for end
DEC CH ; drop count
JZ KanjiScan ; if count is zero, no quoting
KanjiQuoteLoop:
LODSB ; get next byte
CMP AL,22h ; is it another quote
JNZ KanjiQuoteLoop ; no, get another
DEC CH ; yes, drop count
JMP KanjiScan ; go get next char
KanjiEnd:
CMP AL,13 ; end of line character?
JNZ KanjiScan ; go back to beginning
POP CX ; get back original count
ENDIF
MOV SI,DI ; restore pointer to begining
PRESCANLP:
LODSB
IF KANJI
CALL TESTKANJ
JZ NOTKANJ6
MOV [DI],AL
INC DI ; fake STOSB into DS
LODSB ; grab second byte
MOV [DI],AL ; fake stosb into DS
INC DI
INC CL
INC CL
JMP PRESCANLP
NOTKANJ6:
ENDIF
CMP AL,22H ; " character
JNZ TRYGREATER
DEC CH
JZ TRYGREATER
QLOOP:
MOV [DI],AL
INC DI
INC CL
LODSB
CMP AL,22H ; " character
JNZ QLOOP
DEC CH
TRYGREATER:
CMP AL,'>'
JNZ NOOUT
CMP BYTE PTR [SI],'>'
JNZ NOAPPND
LODSB
INC [RE_OUT_APP] ; Flag >>
NOAPPND:
CALL SCANOFF
CMP AL,0DH
JNZ GOTREOFIL
MOV WORD PTR [RE_OUTSTR],09H ; Cause an error later
JMP SHORT PRESCANEND
GOTREOFIL:
PUSH DI
MOV DI,OFFSET RESGROUP:RE_OUTSTR
SETREOUTSTR: ; Get the output redirection name
LODSB
CMP AL,0DH
JZ GOTRESTR
CALL DELIM
JZ GOTRESTR
CMP AL,[SWITCHAR]
JZ GOTRESTR
STOSB ; store it into resgroup
JMP SHORT SETREOUTSTR
NOOUT:
CMP AL,'<'
JNZ CHKPIPE
CALL SCANOFF
CMP AL,0DH
JNZ GOTREIFIL
MOV WORD PTR [RE_INSTR],09H ; Cause an error later
JMP SHORT PRESCANEND
GOTREIFIL:
PUSH DI
MOV DI,OFFSET RESGROUP:RE_INSTR
JMP SHORT SETREOUTSTR ; Get the input redirection name
CHKPIPE:
MOV AH,AL
CMP AH,'|'
JNZ CONTPRESCAN
INC [PIPEFLAG]
CALL SCANOFF
CMP AL,0DH
JZ PIPEERRSYNJ5
CMP AL,'|' ; Double '|'?
JNZ CONTPRESCAN
PIPEERRSYNJ5:
PUSH ES
POP DS ; DS->RESGROUP
JMP PIPEERRSYN
GOTRESTR:
XCHG AH,AL
CMP BYTE PTR ES:[DI-1],':' ; Trailing ':' OK on devices
JNZ NOTTRAILCOL
DEC DI ; Back up over trailing ':'
NOTTRAILCOL:
XOR AL,AL
STOSB ; NUL terminate the string
POP DI ; Remember the start
CONTPRESCAN:
MOV [DI],AH ; "delete" the redirection string
INC DI
CMP AH,0DH
JZ PRESCANEND
INC CL
JMP PRESCANLP
PRESCANEND:
CMP [PIPEFLAG],0
JZ ISNOPIPE
MOV DI,OFFSET RESGROUP:PIPESTR
MOV [PIPEPTR],DI
MOV SI,OFFSET TRANGROUP:COMBUF+2
CALL SCANOFF
PIPESETLP: ; Transfer the pipe into the resident pipe buffer
LODSB
STOSB
CMP AL,0DH
JNZ PIPESETLP
ISNOPIPE:
MOV [COMBUF+1],CL
CMP [PIPEFLAG],0
PUSH CS
POP ES
return
ASSUME DS:TRANGROUP,ES:TRANGROUP
PATHCHRCMP:
CMP [SWITCHAR],'/'
JZ NOSLASHT
CMP AL,'/'
retz
NOSLASHT:
CMP AL,'\'
return
PATHCRUNCH:
; Drive taken from FCB
; DI = Dirsave pointer
;
; Zero set if path dir, CHDIR to this dir, FCB filled with ?
; NZ set if path/file, CHDIR to file, FCB has file (parsed fill ' ')
; [DESTTAIL] points to parse point
; Carry set if no CHDIRs worked, FCB not altered.
; DESTISDIR set non zero if PATHCHRs in path (via SETPATH)
MOV DL,DS:[FCB]
CALL SAVUDIR
CALL SETPATH
TEST [DESTINFO],2
JNZ TRYPEEL ; If ? or * cannot be pure dir
MOV AH,CHDIR
INT int_command
JC TRYPEEL
CALL SETREST1
MOV AL,"?" ; *.* is default file spec if pure dir
MOV DI,5DH
MOV CX,11
REP STOSB
XOR AL,AL ; Set zero
return
TRYPEEL:
MOV SI,[PATHPOS]
DEC SI ; Point at NUL
MOV AL,[SI-1]
IF KANJI
CMP [KPARSE],0
JNZ DELSTRT ; Last char is second KANJI byte, might be '\'
ENDIF
CALL PATHCHRCMP
JZ PEELFAIL ; Trailing '/'
IF KANJI
DELSTRT:
MOV CX,SI
MOV SI,DX
PUSH DX
DELLOOP:
CMP SI,CX
JZ GOTDELE
LODSB
CALL TESTKANJ
JZ NOTKANJ8
INC SI
JMP DELLOOP
NOTKANJ8:
CALL PATHCHRCMP
JNZ DELLOOP
MOV DX,SI
DEC DX
JMP DELLOOP
GOTDELE:
MOV SI,DX
POP DX
CMP SI,DX
JZ BADRET
MOV CX,SI
MOV SI,DX
DELLOOP2: ; Set value of KPARSE
CMP SI,CX
JZ KSET
MOV [KPARSE],0
LODSB
CALL TESTKANJ
JZ DELLOOP2
INC SI
INC [KPARSE]
JMP DELLOOP2
KSET:
ELSE
DELLOOP:
CMP SI,DX
JZ BADRET
MOV AL,[SI]
CALL PATHCHRCMP
JZ TRYCD
DEC SI
JMP SHORT DELLOOP
ENDIF
TRYCD:
CMP BYTE PTR [SI+1],'.'
JZ PEELFAIL ; If . or .., pure cd should have worked
mov al,[si-1]
CMP al,DRVCHAR ; Special case dDRVCHAR,DIRCHARfile
JZ BADRET
IF KANJI
CMP [KPARSE],0
JNZ NOTDOUBLESL ; Last char is second KANJI byte, might be '\'
ENDIF
CALL PATHCHRCMP
JNZ NOTDOUBLESL
PEELFAIL:
STC ; //
return
NOTDOUBLESL:
MOV BYTE PTR [SI],0
MOV AH,CHDIR
INT int_command
JNC CDSUCC
return
BADRET:
MOV AL,[SI]
CALL PATHCHRCMP ; Special case 'DIRCHAR'file
STC
retnz
XOR BL,BL
XCHG BL,[SI+1]
MOV AH,CHDIR
INT int_command
retc
MOV [SI+1],BL
CDSUCC:
CALL SETREST1
INC SI ; Reset zero
MOV [DESTTAIL],SI
MOV DI,FCB
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 02H ; Parse with default drive
INT int_command
return
DISPSIZE:
MOV SI,WORD PTR[DIRBUF+29+7]
MOV DI,WORD PTR[DIRBUF+31+7]
DISP32BITS:
; Prints the 32-bit number DI:SI on the console in decimal. Uses a total
; of 9 digit positions with leading blanks.
XOR AX,AX
MOV BX,AX
MOV BP,AX
MOV CX,32
CONVLP:
SHL SI,1
RCL DI,1
XCHG AX,BP
CALL CONVWRD
XCHG AX,BP
XCHG AX,BX
CALL CONVWRD
XCHG AX,BX
ADC AL,0
LOOP CONVLP
; Conversion complete. Print 9-digit number.
MOV DI,OFFSET TRANGROUP:CHARBUF
MOV CX,1810H ; Allow leading zero blanking for 8 digits
XCHG DX,AX
CALL DIGIT
XCHG AX,BX
CALL OUTWORD
XCHG AX,BP
CALL OUTWORD
XOR AX,AX
STOSB
MOV DX,OFFSET TRANGROUP:CHARBUF
JMP ZPRINT
OUTWORD:
PUSH AX
MOV DL,AH
CALL OUTBYTE
POP DX
OUTBYTE:
MOV DH,DL
SHR DL,1
SHR DL,1
SHR DL,1
SHR DL,1
CALL DIGIT
MOV DL,DH
DIGIT:
AND DL,0FH
JZ BLANKZER
MOV CL,0
BLANKZER:
DEC CH
AND CL,CH
OR DL,30H
SUB DL,CL
MOV AL,DL
STOSB
return
CONVWRD:
ADC AL,AL
DAA
XCHG AL,AH
ADC AL,AL
DAA
XCHG AL,AH
return
GETBATBYT:
; Get one byte from the batch file and return it in AL. End-of-file
; returns <CR> and ends batch mode. DS must be set to resident segment.
; AH, CX, DX destroyed.
ASSUME DS:RESGROUP
ADD WORD PTR [BATLOC],1 ; Add one to file location
ADC WORD PTR [BATLOC+2],0
PUSH BX
MOV DX,OFFSET RESGROUP:BATBYT
MOV BX,[BATHAND]
MOV AH,READ
MOV CX,1
INT int_command ; Get one more byte from batch file
POP BX
MOV CX,AX
JC BATEOF
JCXZ BATEOF
MOV AL,[BATBYT]
CMP AL,1AH
retnz
BATEOF:
PUSH ES
MOV ES,[BATCH] ; Turn off batch
MOV AH,DEALLOC
INT int_command ; free up the batch piece
POP ES
MOV [BATCH],0 ; AFTER DEALLOC in case of ^C
CALL BATCLOSE
MOV AL,0DH ; If end-of-file, then end of line
CMP [SINGLECOM],0FFF0H ; See if we need to set SINGLECOM
JNZ NOSETSING2
MOV [SINGLECOM],-1 ; Cause termination
NOSETSING2:
MOV [ECHOFLAG],1
return
ASSUME DS:TRANGROUP
SCANOFF:
LODSB
CALL DELIM
JZ SCANOFF
DEC SI ; Point to first non-delimiter
return
DELIM:
CMP AL," "
retz
CMP AL,"="
retz
CMP AL,","
retz
CMP AL,";"
retz
CMP AL,9 ; Check for TAB character
return
PRINT_PROMPT:
PUSH DS
PUSH CS
POP DS ; MAKE SURE DS IS IN TRANGROUP
PUSH ES
CALL FIND_PROMPT ; LOOK FOR PROMPT STRING
JC PP0 ; CAN'T FIND ONE
CMP BYTE PTR ES:[DI],0
JNZ PP1
PP0:
CALL PRINT_DRIVE ; USE DEFAULT PROMPT
MOV AL,SYM
CALL OUT
JMP SHORT PP5
PP1:
MOV AL,ES:[DI] ; GET A CHAR
INC DI
OR AL,AL
JZ PP5 ; NUL TERMINATED
CMP AL,"$" ; META CHARACTER?
JZ PP2 ; NOPE
PPP1:
CALL OUT
JMP PP1
PP2:
MOV AL,ES:[DI]
INC DI
MOV BX,OFFSET TRANGROUP:PROMPT_TABLE-3
OR AL,AL
JZ PP5
PP3:
ADD BX,3
CALL UPCONV
CMP AL,[BX]
JZ PP4
CMP BYTE PTR [BX],0
JNZ PP3
JMP PP1
PP4:
PUSH ES
PUSH DI
PUSH CS
POP ES
CALL [BX+1]
POP DI
POP ES
JMP PP1
PP5:
POP ES ; RESTORE SEGMENTS
POP DS
return
PRINT_BACK:
MOV DX,OFFSET TRANGROUP:DBACK
JMP ZPRINT
PRINT_EQ:
MOV AL,"="
JMP SHORT OUTV
PRINT_ESC:
MOV AL,1BH
JMP SHORT OUTV
PRINT_G:
MOV AL,">"
JMP SHORT OUTV
PRINT_L:
MOV AL,"<"
JMP SHORT OUTV
PRINT_B:
MOV AL,"|"
OUTV:
JMP OUT
SETPATH:
; Get an ASCIZ argument from the unformatted parms
; DESTISDIR set if pathchars in string
; DESTINFO set if ? or * in string
MOV SI,80H
LODSB
XOR AH,AH
MOV [PATHCNT],AX
MOV [PATHPOS],SI
GETPATH:
MOV [DESTINFO],0
MOV [DESTISDIR],0
MOV SI,[PATHPOS]
MOV CX,[PATHCNT]
MOV DX,SI
JCXZ PATHDONE
PUSH CX
PUSH SI
CALL SWITCH
MOV [PATHSW],AX
POP BX
SUB BX,SI
POP CX
ADD CX,BX
MOV DX,SI
SKIPPATH:
IF KANJI
MOV [KPARSE],0
SKIPPATH2:
ENDIF
JCXZ PATHDONE
DEC CX
LODSB
IF KANJI
CALL TESTKANJ
JZ TESTPPSEP
DEC CX
INC SI
INC [KPARSE]
JMP SKIPPATH2
TESTPPSEP:
ENDIF
CALL PATHCHRCMP
JNZ TESTPMETA
INC [DESTISDIR]
TESTPMETA:
CMP AL,'?'
JNZ TESTPSTAR
OR [DESTINFO],2
TESTPSTAR:
CMP AL,'*'
JNZ TESTPDELIM
OR [DESTINFO],2
TESTPDELIM:
CALL DELIM
JZ PATHDONEDEC
CMP AL,[SWITCHAR]
JNZ SKIPPATH
PATHDONEDEC:
DEC SI
PATHDONE:
XOR AL,AL
XCHG AL,[SI]
INC SI
CMP AL,0DH
JNZ NOPSTORE
MOV [SI],AL ;Don't loose the CR
NOPSTORE:
MOV [PATHPOS],SI
MOV [PATHCNT],CX
return
PGETARG:
MOV SI,80H
LODSB
OR AL,AL
retz
CALL PSCANOFF
CMP AL,13
return
PSCANOFF:
LODSB
CALL DELIM
JNZ PSCANOFFD
CMP AL,';'
JNZ PSCANOFF ; ';' is not a delimiter
PSCANOFFD:
DEC SI ; Point to first non-delimiter
return
PATH:
CALL FIND_PATH
CALL PGETARG ; Pre scan for arguments
JZ DISPPATH ; Print the current path
CALL DELETE_PATH ; DELETE ANY OFFENDING NAME
CALL SCAN_DOUBLE_NULL
CALL MOVE_NAME ; MOVE IN PATH=
CALL PGETARG
CMP AL,';' ; NUL path argument?
JZ GOTPATHS
PATHSLP: ; Get the user specified path
LODSB
CMP AL,0DH
JZ GOTPATHS
IF KANJI
CALL TESTKANJ
JZ NOTKANJ2
CALL STORE_CHAR
LODSB
CALL STORE_CHAR
JMP SHORT PATHSLP
NOTKANJ2:
ENDIF
CALL UPCONV
CMP AL,';' ; ';' not a delimiter on PATH
JZ NOTDELIM
CALL DELIM
JZ GOTPATHS
NOTDELIM:
CALL STORE_CHAR
JMP SHORT PATHSLP
GOTPATHS:
XOR AX,AX
STOSW
return
DISPPATH:
CALL PRINT_PATH
CALL CRLF2
return
PRINT_PATH:
CMP BYTE PTR ES:[DI],0
JNZ PATH1
PATH0:
MOV DX,OFFSET TRANGROUP:NULPATH
PUSH CS
POP DS
JMP PRINT
PATH1:
PUSH ES
POP DS
SUB DI,5
MOV DX,DI
ASSUME DS:RESGROUP
CALL SCASB2 ; LOOK FOR NUL
CMP CX,0FFH
JZ PATH0
JMP ZPRINT
FCB_TO_ASCZ: ; Convert DS:SI to ASCIZ ES:DI
MOV CX,8
MAINNAME:
LODSB
CMP AL,' '
JZ SKIPSPC
STOSB
SKIPSPC:
LOOP MAINNAME
LODSB
CMP AL,' '
JZ GOTNAME
MOV AH,AL
MOV AL,'.'
STOSB
XCHG AL,AH
STOSB
MOV CL,2
EXTNAME:
LODSB
CMP AL,' '
JZ GOTNAME
STOSB
LOOP EXTNAME
GOTNAME:
XOR AL,AL
STOSB
return
GETNUM:
CALL INDIG
retc
MOV AH,AL ; Save first digit
CALL INDIG ; Another digit?
JC OKRET
AAD ; Convert unpacked BCD to decimal
MOV AH,AL
OKRET:
OR AL,1
return
INDIG:
MOV AL,BYTE PTR[SI]
SUB AL,"0"
retc
CMP AL,10
CMC
retc
INC SI
return
OUT2: ; Output binary number as two ASCII digits
AAM ; Convert binary to unpacked BCD
XCHG AL,AH
OR AX,3030H ; Add "0" bias to both digits
CMP AL,"0" ; Is MSD zero?
JNZ NOSUP
SUB AL,BH ; Suppress leading zero if enabled
NOSUP:
MOV BH,0 ; Disable zero suppression
STOSW
return
OUT:
; Print char in AL without affecting registers
XCHG AX,DX
PUSH AX
CALL OUT_CHAR
POP AX
XCHG AX,DX
return
OUT_CHAR:
PUSH DS
PUSH DX
PUSH CX
PUSH BX
PUSH AX
PUSH CS
POP DS
MOV BX,OFFSET TRANGROUP:CHARBUF
MOV [BX],DL
MOV DX,BX
MOV BX,1
MOV CX,BX
MOV AH,WRITE
INT int_command
POP AX
POP BX
POP CX
POP DX
POP DS
return
ERROR_PRINT:
PUSH AX
PUSH BX
MOV AL,"$"
MOV BX,2 ;STD ERROR
JMP SHORT STRING_OUT
CRPRINT:
PUSH AX
MOV AL,13
JMP SHORT Z$PRINT
PRINT: ;$ TERMINATED STRING
PUSH AX
MOV AL,"$"
JMP SHORT Z$PRINT
ZPRINT:
PUSH AX
XOR AX,AX ;NUL TERMINATED STRING
Z$PRINT:
PUSH BX
MOV BX,1 ;STD CON OUT
;
; output string terminated by AL to handle BX, DS:DX points to string
;
STRING_OUT:
PUSH CX
PUSH DI
MOV DI,DX
MOV CX,-1
PUSH ES
PUSH DS
POP ES
REPNZ SCASB ; LOOK FOR TERMINATOR
POP ES
NEG CX
DEC CX
DEC CX
;
; WRITE CHARS AT DS:DX TO HANDLE IN BX, COUNT IN CX
;
MOV AH,WRITE
INT int_command
JC ERROR_OUTPUT
CMP AX,CX
JNZ ERROR_OUTPUT
POP DI
POP CX
POP BX
POP AX
return
ERROR_OUTPUT:
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV DX,OFFSET TRANGROUP:NOSPACE
CMP [PIPEFLAG],0
JZ GO_TO_ERROR
MOV [PIPEFLAG],0
MOV DX,OFFSET TRANGROUP:PIPEEMES
GO_TO_ERROR:
JMP CERROR
TRANCODE ENDS
END
+243
View File
@@ -0,0 +1,243 @@
TITLE COMMAND Transient Initialized DATA
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE IFEQU.ASM
TRANCODE SEGMENT PUBLIC
EXTRN PRINT_DATE:NEAR,PRINT_TIME:NEAR,PRINT_DEFAULT_DIRECTORY:NEAR
EXTRN PRINT_DRIVE:NEAR,PRINT_VERSION:NEAR,PRINT_G:NEAR
EXTRN PRINT_L:NEAR,PRINT_B:NEAR,CRLF2:NEAR,OUT:NEAR,PRINT_ESC:NEAR
EXTRN PRINT_BACK:NEAR,PRINT_EQ:NEAR
EXTRN IFNOT:NEAR,IFERLEV:NEAR,IFEXISTS:NEAR
EXTRN CATALOG:NEAR,CRENAME:NEAR,ERASE:NEAR,TYPEFIL:NEAR
EXTRN TCOMMAND:NEAR,COPY:NEAR,PAUSE:NEAR,DATE:NEAR,CTIME:NEAR
EXTRN VERSION:NEAR,VOLUME:NEAR,$CHDIR:NEAR,$MKDIR:NEAR,$RMDIR:NEAR
EXTRN CNTRLC:NEAR,VERIFY:NEAR,ADD_NAME_TO_ENVIRONMENT:NEAR
EXTRN ADD_PROMPT:NEAR,PATH:NEAR,$EXIT:NEAR,CTTY:NEAR,ECHO:NEAR
EXTRN GOTO:NEAR,SHIFT:NEAR,$IF:NEAR,$FOR:NEAR,CLS:NEAR
TRANCODE ENDS
; Data for transient portion
TRANDATA SEGMENT PUBLIC BYTE
PUBLIC BADBAT,NEEDBAT,BADNAM,RENERR,NOTFND,NOSPACE,ENVERR,FULDIR
PUBLIC OVERWR,LOSTERR,DIRMES_PRE,DIRMES_POST,BADDRV,PAUSEMES,BADSWT
PUBLIC COPIED_PRE,COPIED_POST,BYTMES_PRE,BYTMES_POST
PUBLIC WEEKTAB,BADDAT,NEWDAT,BADTIM,NEWTIM,SUREMES,CURDAT_MID
PUBLIC CURDAT_PRE,CURDAT_POST,CURTIM_PRE,CURTIM_POST,VERMES_POST
PUBLIC DMES,VERMES_PRE,VOLMES,GOTVOL,NOVOL,BADCD,BADMKD,BADRMD
PUBLIC BAD_ON_OFF,NULPATH,PATH_TEXT,PROMPT_TEXT,BADPMES
PUBLIC BADDEV,BADLAB,SYNTMES,FORNESTMES,PIPEEMES,INBDEV,OFFMES
PUBLIC ONMES,CTRLCMES,VERIMES,ECHOMES,BADCPMES,BADARGS,DEVWMES
PUBLIC ACRLF,DBACK,CLSSTRING,PROMPT_TABLE,IFTAB,COMTAB
PUBLIC TRANDATAEND,DIRHEAD_PRE,DIRHEAD_POST
ORG 0
ZERO = $
BADBAT DB 13,10,"Batch file missing",13,10,"$"
NEEDBAT DB 13,10,"Insert disk with batch file"
DB 13,10,"and press any key when ready",13,10,"$"
BADNAM DB "Bad command or file name",13,10,"$"
RENERR DB "Duplicate file name or "
NOTFND DB "File not found",13,10,"$"
NOSPACE DB "Insufficient disk space",13,10,"$"
ENVERR DB "Out of environment space",13,10,"$"
FULDIR DB "File creation error",13,10,"$"
OVERWR DB "File cannot be copied onto itself",13,10,"$"
LOSTERR DB "Content of destination lost before copy",13,10,"$"
;"COPIED_PRE<# files copied>COPIED_POST"
COPIED_POST DB " File(s) copied",13,10 ŠCOPIED_PRE DB "$"
;"DIRMES_PRE<# files in dir>DIRMES_POST"
DIRMES_POST DB " File(s) "
DIRMES_PRE DB "$"
;"BYTMES_PRE<# free bytes>BYTMES_POST"
BYTMES_POST DB " bytes free",13,10
BYTMES_PRE DB "$"
BADDRV DB "Invalid drive specification",13,10,"$"
PAUSEMES DB "Strike a key when ready . . . $"
BADSWT DB "Invalid parameter",13,10,"$"
WEEKTAB DB "SunMonTueWedThuFriSat"
BADDAT DB 13,10,"Invalid date$"
;"CURDAT_PRE<day of week>CURDAT_MID<MO,DAY,YR>CURDAT_POST"
;Note: CURDAT_MID also appears in the date printed via PROMPT command
CURDAT_PRE DB "Current date is "
CURDAT_MID LABEL BYTE
CURDAT_POST DB "$"
NEWDAT DB 13,10,"Enter new date: $"
BADTIM DB 13,10,"Invalid time$"
;"CURTIM_PRE<HR,MIN,SEC,HSEC>CURTIM_POST"
CURTIM_PRE DB "Current time is "
CURTIM_POST DB "$"
NEWTIM DB 13,10,"Enter new time: $"
SUREMES DB "Are you sure (Y/N)? $"
DMES DB " <DIR> $"
;"VERMES_PRE<version #>VERMES_POST"
IF IBMVER
VERMES_PRE DB "TeleVideo Personal Computer DOS Version "
ENDIF
IF MSVER
VERMES_PRE DB "MS-DOS Version "
ENDIF
VERMES_POST DB "$"
VOLMES DB " Volume in drive $"
GOTVOL DB " is $"
NOVOL DB " has no label$"
BADCD DB "Invalid directory",13,10,"$"
BADMKD DB "Unable to create directory",13,10,"$"
BADRMD DB "Invalid path, not directory,",13,10
DB "or directory not empty",13,10,"$"
BAD_ON_OFF DB "Must specify ON or OFF" ;Note Run over to next message
;"DIRHEAD_PRE<path of dir>DIRHEAD_POST"
DIRHEAD_POST DB 13,10,"$"
DIRHEAD_PRE DB " Directory of $" Š
NULPATH DB "No Path $"
PATH_TEXT DB "PATH="
PROMPT_TEXT DB "PROMPT="
BADPMES DB "Invalid drive in search path",13,10,"$"
BADDEV DB "Invalid device",13,10,"$"
BADLAB DB "Label not found",13,10,"$"
SYNTMES DB "Syntax error",13,10,"$"
FORNESTMES DB 13,"FOR cannot be nested",13,10,"$"
PIPEEMES DB "Intermediate file error during pipe",13,10,"$"
INBDEV DB "Cannot do binary reads from a device",13,10,"$"
OFFMES DB "off",13,10,"$"
ONMES DB "on",13,10,"$"
CTRLCMES DB "BREAK is $"
VERIMES DB "VERIFY is $"
ECHOMES DB "ECHO is $"
BADCPMES DB "Invalid path or file name",13,10,"$"
BADARGS DB "Invalid number of parameters",13,10,"$"
DEVWMES DB "Error writing to device"
ACRLF DB 13,10,"$"
DBACK DB 8," ",8,0 ; DESTRUCTIVE BACK SPACE
CLSSTRING DB 4,01BH,"[2J" ; ANSI Clear screen
PROMPT_TABLE LABEL BYTE
DB "D"
DW OFFSET TRANGROUP:PRINT_DATE
DB "T"
DW OFFSET TRANGROUP:PRINT_TIME
DB "P"
DW OFFSET TRANGROUP:PRINT_DEFAULT_DIRECTORY
DB "N"
DW OFFSET TRANGROUP:PRINT_DRIVE
DB "V"
DW OFFSET TRANGROUP:PRINT_VERSION
DB "G"
DW OFFSET TRANGROUP:PRINT_G
DB "L"
DW OFFSET TRANGROUP:PRINT_L
DB "B"
DW OFFSET TRANGROUP:PRINT_B
DB "_"
DW OFFSET TRANGROUP:CRLF2
DB "$"
DW OFFSET TRANGROUP:OUT
DB "E"
DW OFFSET TRANGROUP:PRINT_ESC
DB "H"
DW OFFSET TRANGROUP:PRINT_BACK
DB "Q"
DW OFFSET TRANGROUP:PRINT_EQ
DB 0 ; NUL TERMINATED
IFTAB LABEL BYTE ; Table of IF conditionals
DB 3,"NOT" ; First byte is count Š DW OFFSET TRANGROUP:IFNOT
DB 10,"ERRORLEVEL"
DW OFFSET TRANGROUP:IFERLEV
DB 5,"EXIST"
DW OFFSET TRANGROUP:IFEXISTS
DB 0
COMTAB DB 4,"DIR",1 ; Table for internal command names
DW OFFSET TRANGROUP:CATALOG
DB 7,"RENAME",1
DW OFFSET TRANGROUP:CRENAME
DB 4,"REN",1
DW OFFSET TRANGROUP:CRENAME
DB 6,"ERASE",1
DW OFFSET TRANGROUP:ERASE
DB 4,"DEL",1
DW OFFSET TRANGROUP:ERASE
DB 5,"TYPE",1
DW OFFSET TRANGROUP:TYPEFIL
DB 4,"REM",0
DW OFFSET TRANGROUP:TCOMMAND
DB 5,"COPY",1
DW OFFSET TRANGROUP:COPY
DB 6,"PAUSE",0
DW OFFSET TRANGROUP:PAUSE
DB 5,"DATE",0
DW OFFSET TRANGROUP:DATE
DB 5,"TIME",0
DW OFFSET TRANGROUP:CTIME
DB 4,"VER",0
DW OFFSET TRANGROUP:VERSION
DB 4,"VOL",1
DW OFFSET TRANGROUP:VOLUME
DB 3,"CD",1
DW OFFSET TRANGROUP:$CHDIR
DB 6,"CHDIR",1
DW OFFSET TRANGROUP:$CHDIR
DB 3,"MD",1
DW OFFSET TRANGROUP:$MKDIR
DB 6,"MKDIR",1
DW OFFSET TRANGROUP:$MKDIR
DB 3,"RD",1
DW OFFSET TRANGROUP:$RMDIR
DB 6,"RMDIR",1
DW OFFSET TRANGROUP:$RMDIR
DB 6,"BREAK",0
DW OFFSET TRANGROUP:CNTRLC
DB 7,"VERIFY",0
DW OFFSET TRANGROUP:VERIFY
DB 4,"SET",0
DW OFFSET TRANGROUP:ADD_NAME_TO_ENVIRONMENT
DB 7,"PROMPT",0
DW OFFSET TRANGROUP:ADD_PROMPT
DB 5,"PATH",0
DW OFFSET TRANGROUP:PATH Š DB 5,"EXIT",0
DW OFFSET TRANGROUP:$EXIT
DB 5,"CTTY",1
DW OFFSET TRANGROUP:CTTY
DB 5,"ECHO",0
DW OFFSET TRANGROUP:ECHO
DB 5,"GOTO",0
DW OFFSET TRANGROUP:GOTO
DB 6,"SHIFT",0
DW OFFSET TRANGROUP:SHIFT
DB 3,"IF",0
DW OFFSET TRANGROUP:$IF
DB 4,"FOR",0
DW OFFSET TRANGROUP:$FOR
DB 4,"CLS",0
DW OFFSET TRANGROUP:CLS
DB 0 ; Terminate command table
TRANDATAEND LABEL BYTE
TRANDATA ENDS
END

BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+907
View File
@@ -0,0 +1,907 @@
;
; xenix file calls for MSDOS
;
INCLUDE DOSSEG.ASM
IFNDEF KANJI
KANJI EQU 0 ;FALSE
ENDIF
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
TITLE XENIX - IO system to mimic UNIX
NAME XENIX
i_need NoSetDir,BYTE
i_need CURDRV,BYTE
i_need IOCALL,BYTE
i_need IOMED,BYTE
i_need IOSCNT,WORD
i_need IOXAD,DWORD
i_need DIRSTART,WORD
i_need ATTRIB,BYTE
i_need THISFCB,DWORD
i_need AuxStack,BYTE
i_need Creating,BYTE
i_need ThisDRV,BYTE
i_need NAME1,BYTE
i_need LastEnt,WORD
i_need ThisDPB,DWORD
i_need EntLast,WORD
i_need CurrentPDB,WORD
i_need sft_addr,DWORD ; pointer to head of table
i_need CURBUF,DWORD ; pointer to current buffer
i_need DMAADD,DWORD ; pointer to current dma address
BREAK <Local data>
CODE ENDS
DATA SEGMENT BYTE PUBLIC 'DATA'
open_name DW ?
DW ?
open_access DB ?
open_jfn DW ? ; accessed as DD
open_jfn_b DW ? ; accessed as DD with above
open_sfn DW ?
open_sfoff DW ? ; accessed as DD
open_sfn_b DW ? ; accessed as DD with above
open_devid DB ?
Cr_read_only DB ?
rename_source DD ?
rename_dest DD ?
DATA ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
BREAK <Validate_path - check to see if there are meta characters in path>
;
; Input: DS:DX is an ASCIZ path
; Output: Carry set if meta-characters present or path malformed and
; Zero is set if the only problem is that meta-characters
; are present in the last element of the path
procedure Validate_path,near
ASSUME DS:NOTHING,ES:NOTHING
PUSH AX
PUSH CX
PUSH SI
MOV SI,DX
MOV CX,0FFH ;No path seps yet
MOV AX,[SI] ; Get first two bytes
OR AL,AL
JZ validate_malformed ; NUL path
CMP AH,':'
JNZ validate_loop ; OK so far
CMP BYTE PTR [SI+2],0
JZ validate_malformed ; NUL path (just d:)
validate_loop:
LODSB
validate_loop1:
IF KANJI
invoke TESTKANJ
JZ NOTKANJ6
INC SI
JMP validate_loop
NOTKANJ6:
ENDIF
OR AL,AL
JZ validate_end
CMP AL,"?"
JZ validate_error
CMP AL,"*"
JZ validate_error
invoke PathChrCmp
JNZ validate_loop
JCXZ validate_malformed ;If path sep, cannot have meta yet
LODSB ;Look ahead one char
OR AL,AL
JZ validate_checktslsh ;Trailing path sep
invoke PathChrCmp
JNZ validate_loop1 ;Double path sep?
validate_malformed:
INC CX
OR CX,CX ;Reset zero
JMP SHORT validate_set_carry
validate_error:
XOR CX,CX ;Flag metas found
JMP validate_loop
validate_checktslsh:
;A bizarre case, "/" is OK, "d:/" is OK, anything else is an error
SUB SI,DX
CMP SI,2
JZ validate_end ;Two chars, the '/' and the NUL
CMP SI,4
JNZ validate_malformed ;Four chars, "D:/<NUL>"
MOV SI,DX
CMP BYTE PTR [SI+1],':'
JNZ validate_malformed ;Second char must be a ':'
validate_end:
OR CX,CX ;Clears carry
JNZ validate_ok ;No metas found, leave carry clear
validate_set_carry:
STC
validate_ok:
POP SI
POP CX
POP AX
return
validate_path ENDP
BREAK <Access_path - determine if file found>
;
; Input: DS:DX point to a path
; Output: Carry reset - outputs of GetPath
; carry set - AL has error code
;
procedure Access_path,NEAR
ASSUME DS:NOTHING,ES:NOTHING
CALL Validate_path
JC access_no_path
MOV SI,DX
invoke GetPath
retnc
MOV AL,error_file_not_found
OR CL,CL
JNZ access_ret
access_no_path:
MOV AL,error_path_not_found
access_ret:
STC
return
access_path ENDP
BREAK <Find_free_jfn - return a free jfn in users PDB>
;
; system file table data
;
;
; The system file table is two linear tables. The first table is the
; DOS initialization table containing a default number of FCBs. The
; first word in the table is a link to the second table, which
; SYSINIT sets up, the second word is the number of FCBs in the table.
;
;
; find_free_jfn
; input: none
; output: JNC <found>
; ES:DI is pointer to free JFN
; JC <no free jfns>
; ES,DI indeterminate
;
procedure Find_free_jfn,NEAR
ASSUME DS:NOTHING,ES:NOTHING
PUSH AX
PUSH CX
MOV AL,0FFh
MOV ES,[CurrentPDB]
MOV DI,PDB_JFN_Table
MOV CX,FilPerProc
REPNE SCASB
STC
JNZ Find_jfn_ret
DEC DI
CLC
Find_jfn_ret:
POP CX
POP AX
return
Find_free_jfn ENDP
BREAK <find_free_sfn - return a free sfn and sf pointer>
;
; find_free_sfn
; input: none
; output: JNC <found>
; ES:DI is free sf entry
; SI is sfn
; JC <not found>
; ES,DI,SI indeterminate
;
; sft_addr --> (link) count (fcbs)
; links = -1 means end of list
;
procedure Find_free_sfn,NEAR
ASSUME DS:NOTHING,ES:NOTHING
PUSH BX
PUSH CX
LES BX,sft_addr ; head of chain of tables
XOR SI,SI ; count of sfn
; ES:BX points to table... search through table
Find_sfn_in_table:
CMP BX,-1 ; end of chain
JZ Find_no_free_sfns
MOV DI,sft_table ; offset to sf entry
MOV CX,ES:[BX].sft_count ; count of fcbs in table
Find_sfn:
CMP ES:BYTE PTR [BX+DI].sf_ref_count,0h
JZ Find_got_sfn ; ref count is 0 -> free entry
ADD DI,SIZE sf_entry ; look to next entry
INC SI ; bump sfn
LOOP Find_sfn
LES BX,ES:[BX].sft_link ; link to next
JMP SHORT Find_sfn_in_table ; look for more
Find_no_free_sfns:
STC
JMP SHORT find_ret
Find_got_sfn:
ADD DI,BX
CLC
Find_ret:
POP CX
POP BX
RET
Find_free_sfn ENDP
BREAK <$Open - open a file handle>
;
; Assembler usage:
; LDS DX, Name
; MOV AH, Open
; MOV AL, access
; INT int_command
;
; ACCESS Function
; ------ --------
; open_for_read file is opened for reading
; open_for_write file is opened for writing
; open_for_both file is opened for both reading and writing.
;
; Error returns:
; AX = error_invalid_access
; = error_file_not_found
; = error_access_denied
; = error_too_many_open_files
;
procedure $Open,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV [Cr_read_only],0
Open_create:
CMP AL,open_for_both ; validate access
JBE OPEN_get_jfn
error error_invalid_access
OPEN_get_jfn:
MOV [open_name+2],DS
context DS
MOV open_name,DX
MOV open_access,AL
invoke Find_free_jfn ; scan through user's area
; ES:DI is the jfn entry
JNC OPEN_get_sfn
OPEN_too_many:
error error_too_many_open_files
OPEN_get_sfn:
MOV OPEN_jfn_b,ES
MOV OPEN_jfn,DI
invoke Find_free_sfn ; get a free sft entry
; ES:DI is the SFT entry that's free, SI is the sfn
JC OPEN_too_many
OPEN_file:
MOV OPEN_sfn,SI
MOV OPEN_sfoff,DI
MOV OPEN_sfn_b,ES
;
; open the file
;
PUSH DS
LDS DX,DWORD PTR [open_name]
ASSUME DS:NOTHING
CALL access_path
POP DS
ASSUME DS:DOSGROUP
JNC open_check_access ; carry set -> error
transfer SYS_RET_ERR
open_check_access:
MOV ES,WORD PTR [CURBUF+2] ; get buffer location
MOV open_devid,AH
TEST AH,080h
JNZ open_set_FCB_dev ;is a device
MOV AL,ES:[BX].dir_attr
TEST AL,attr_directory ; can't open directories
JZ open_try_volid
open_bad_access:
error error_access_denied
open_try_volid:
TEST AL,attr_volume_id ; can't open volume ids
JNZ open_bad_access
TEST AL,attr_read_only ; check write on read only
JZ open_set_FCB
CMP [Cr_read_only],0
JNZ open_set_FCB ; ok if creating read only file
CMP open_access, open_for_read
JNZ open_bad_access ; writing on a read only file
JMP SHORT open_set_FCB
open_set_FCB_dev:
PUSH SS
POP ES ;Device opens are DOSGROUP relative
open_set_FCB:
MOV CX,11 ; copy name into FCB...
PUSH SI ; ES:BX is source, must change
MOV SI,BX ; ES:SI is source
MOV DI,open_sfoff ; ??:DI is dest
PUSH DS
PUSH ES
MOV ES,open_sfn_b ; ES:DI is dest
POP DS ; DS:SI is source
ASSUME DS:NOTHING
;
; need to save attribute for the close operation
;
MOV AH,DS:[BX.dir_attr] ; save attribute for close
MOV ES:[DI.sf_attr],AH
ADD DI,sf_fcb+1 ; point to name
IF KANJI
MOVSB
CMP BYTE PTR ES:[DI-1],5
JNZ NOTKTRAN
MOV BYTE PTR ES:[DI-1],0E5H
NOTKTRAN:
DEC CX
ENDIF
REP MOVSB ; move in parsed name
POP DS
ASSUME DS:DOSGROUP
POP SI
LES DI,DWORD PTR [open_sfoff]
ADD DI,sf_fcb ; offset on fcb in sf entry
MOV AH,open_devid
invoke DOOPEN ; let open code fill in blanks
context DS
LES DI,DWORD PTR [open_sfoff]
INC ES:[DI].sf_ref_count ; reference this FCB
MOV AL,open_access ; stash the access
MOV ES:BYTE PTR [DI].sf_mode,AL
XOR AX,AX
MOV ES:WORD PTR [DI.sf_FCB.fcb_RR],AX ; beginning of file
MOV ES:WORD PTR [DI.sf_FCB.fcb_RR+2],AX
INC AX
MOV ES:WORD PTR [DI.sf_FCB.fcb_RECSIZ],AX ; byte io only
LES DI,DWORD PTR [open_jfn]
MOV AX,open_sfn
MOV ES:BYTE PTR [DI],AL ; stash sfn in PDB
SUB DI,PDB_jfn_table ; get jfn for user
MOV AX,DI
transfer SYS_RET_OK
$Open ENDP
BREAK <$UNLINK - delete a file entry>
;
; Assembler usage:
; LDS DX, name
; MOV AH, Unlink
; INT 21h
;
; Error returns:
; AX = error_file_not_found
; = error_access_denied
;
procedure $UNLINK,NEAR
ASSUME DS:NOTHING,ES:NOTHING
CALL access_path
JNC unlink_check_attr
transfer SYS_RET_ERR
unlink_check_attr:
JZ unlink_dir
LDS DI,DWORD PTR [CURBUF] ; get directory entry
TEST DS:[BX.dir_attr],attr_read_only
JZ unlink_doit
unlink_dir:
error error_access_denied
unlink_doit:
MOV BYTE PTR DS:[BX.dir_name],0E5h ; delete dir entry
MOV BYTE PTR DS:[DI.BUFDIRTY],1 ; dirty the buffer
LODSW
MOV BX,AX
AND BX,0FFFh
context DS
JZ unlink_flush
invoke RELEASE
unlink_flush:
MOV AL,BYTE PTR ES:[BP.DPB_drive]
invoke FLUSHBUF
transfer SYS_RET_OK
$UNLINK ENDP
BREAK <$CREAT - creat a new file and open him for input>
;
; Assembler usage:
; LDS DX, name
; MOV AH, Creat
; MOV CX, access
; INT 21h
; ; AX now has the handle
;
; Error returns:
; AX = error_access_denied
; = error_path_not_found
; = error_too_many_open_files
;
procedure $CREAT,NEAR
ASSUME DS:NOTHING,ES:NOTHING
CALL Validate_path
JNC unlink_do_make
error error_path_not_found
unlink_do_make:
PUSH DX
PUSH DS
context DS
MOV WORD PTR [CREATING],0E5FFh
MOV WORD PTR [ThisFCB+2],SS
MOV WORD PTR [ThisFCB],OFFSET DOSGROUP:AUXSTACK-40
MOV SI,DX
MOV AL,CL
AND CL,attr_read_only
MOV [Cr_read_only],CL
POP DS
PUSH DS
ASSUME DS:NOTHING
invoke MakeNode
POP DS
POP DX
OR AL,AL
JZ creat_open
CMP AL,3
JZ creat_open
creat_no_access:
error error_access_denied
creat_open:
MOV AL,open_for_both
JMP Open_create
$CREAT ENDP
BREAK <$DUP - duplicate a jfn>
;
; Assembler usage:
; MOV BX, fh
; MOV AH, Dup
; INT int_command
; AX has the returned handle
; Errors:
; AX = dup_invalid_handle
; = dup_too_many_open_files
procedure $DUP,NEAR
ASSUME DS:NOTHING,ES:NOTHING
context DS
invoke Find_free_jfn
JC dup_no_free_handles
dup_force:
PUSH ES
PUSH DI
invoke Get_sf_from_jfn
POP SI
POP DS
JC dup_bad_handle
; ES:DI is pointer to sf entry
; DS:DI is pointer to jfn
INC ES:[DI].sf_ref_count ; another jfn reference...
MOV AL,[BX].PDB_JFN_table ; get old sfn
MOV [SI],AL ; store in new place
SUB SI,PDB_JFN_table ; get jfn
MOV AX,SI
transfer SYS_RET_OK
dup_no_free_handles:
error error_too_many_open_files
dup_bad_handle:
error error_invalid_handle
$DUP ENDP
BREAK <$DUP2 - force a dup on a particular jfn>
;
; Assembler usage:
; MOV BX, fh
; MOV CX, newfh
; MOV AH, Dup2
; INT int_command
; Error returns:
; AX = error_invalid_handle
;
procedure $DUP2,NEAR
ASSUME DS:NOTHING,ES:NOTHING
XCHG BX,CX ; BX < destination jfn
PUSH BX
PUSH CX
invoke $CLOSE ; close BX
context DS
POP CX
POP BX
invoke Get_jfn_pointer
XCHG BX,CX
JNC dup_force
lseek_bad_handle:
error error_invalid_handle
$DUP2 ENDP
BREAK <$CHMOD - change file attributes>
;
; Assembler usage:
; LDS DX, name
; MOV CX, attributes
; INT 21h
; Error returns:
; AX = error_path_not_found
; AX = error_access_denied
;
procedure $CHMOD,NEAR
ASSUME DS:NOTHING,ES:NOTHING
CMP AL,1
JBE chmod_save
error error_invalid_function
chmod_save:
JB chmod_try_file
MOV BX,CX
AND BX,NOT attr_changeable
JZ chmod_try_file
chmod_bad:
error error_access_denied
chmod_bye:
transfer SYS_RET_ERR
chmod_try_file:
PUSH CX
PUSH AX
CALL access_path
POP DX
POP CX
JC chmod_bye
LES DI,[CURBUF]
context DS
OR DL,DL
JZ chmod_fetch
AND BYTE PTR ES:[BX].dir_attr,NOT attr_changeable
OR BYTE PTR ES:[BX].dir_attr,CL
MOV ES:[DI.BUFDIRTY],1
MOV AL,-1
invoke FlushBuf
transfer SYS_RET_OK
chmod_fetch:
XOR CX,CX
MOV CL,BYTE PTR ES:[BX].dir_attr
invoke Get_user_stack
MOV [SI.user_CX],CX
transfer SYS_RET_OK
$chmod ENDP
BREAK <$CURRENT_DIR - dump the current directory into user space>
;
; Assembler usage:
; LDS SI,area
; MOV DL,drive
; INT 21h
; ; DS:SI is a pointer to 64 byte area that contains drive
; ; current directory.
; Error returns:
; AX = error_invalid_drive
;
procedure $CURRENT_DIR,NEAR
ASSUME DS:NOTHING,ES:NOTHING
PUSH DS
PUSH BX
PUSH SI
invoke $get_DPB
;
; ES:BP points to DPB. DS:SI points to user stack, unless error
;
CMP AL,0FFh
JNZ current_copy
POP AX ; Clean Stack
POP AX
POP AX
error error_invalid_drive
current_copy:
POP DI ; where to move to
POP [SI.user_BX] ; restore old BX
POP BX
MOV [SI.user_DS],BX ; and restore old DS
;
; ES:BP is pointer to DPB. BX:DI is pointer to destination
;
CMP ES:[BP.dpb_current_dir],-1
JNZ current_ok
PUSH BX
PUSH DI
MOV [ATTRIB],attr_all
invoke GETCURRDIR
POP DI
POP BX
current_ok:
MOV SI,BP ; ES:SI is source
PUSH ES
POP DS ; DS:SI is source
MOV ES,BX ; ES:DI is destination
CMP [SI.dpb_current_dir],0
JNZ current_move
MOV BYTE PTR [SI.dpb_dir_text],0
current_move:
ADD SI,dpb_dir_text
MOV CX,DIRSTRLEN
current_loop:
LODSB
STOSB
OR AL,AL
LOOPNZ current_loop
transfer SYS_RET_OK
$CURRENT_DIR ENDP
BREAK <$RENAME - move directory entries around>
;
; Assembler usage:
; LDS DX, source
; LES DI, dest
; MOV AH, Rename
; INT 21h
;
; Error returns:
; AX = error_file_not_found
; = error_not_same_device
; = error_access_denied
procedure $RENAME,near
MOV WORD PTR [rename_source],DX
MOV WORD PTR [rename_source+2],DS
MOV WORD PTR [rename_dest],DI
MOV WORD PTR [rename_dest+2],ES
CALL Access_path
JNC rename_check_dir
transfer SYS_RET_ERR
rename_check_dir:
JZ rename_no_access
MOV DS,WORD PTR [CurBuf+2]
PUSH [BX.dir_date]
PUSH [BX.dir_first]
PUSH [BX.dir_size_h]
PUSH [BX.dir_size_l]
PUSH [BX.dir_time]
PUSH WORD PTR [BX.dir_attr]
PUSH WORD PTR [ThisDrv]
LDS SI,[rename_dest]
invoke GetPath
POP AX
JC rename_check_drives
rename_bad_access:
ADD SP,12
rename_no_access:
error error_access_denied
rename_check_drives:
CMP AL,[ThisDrv]
JZ rename_create
ADD SP,12
error error_not_same_device
rename_create:
LDS SI,[rename_dest]
POP AX
PUSH AX
MOV WORD PTR [Creating],0E5FFh
MOV WORD PTR [ThisFCB+2],SS
MOV WORD PTR [ThisFCB],OFFSET DOSGROUP:AUXStack-40
invoke MakeNode
JC rename_bad_access
LDS SI,[CurBuf]
POP AX
MOV [BX.dir_attr],AL
POP [BX.dir_time]
POP [BX.dir_size_l]
POP [BX.dir_size_h]
POP [BX.dir_first]
POP [BX.dir_date]
MOV [SI.BUFDIRTY],1
LDS SI,[rename_source]
invoke GetPath
LDS SI,[CurBuf]
MOV BYTE PTR [BX],0E5h
MOV [SI.BUFDIRTY],1
context DS
MOV AL,0FFh
invoke FlushBuf
transfer SYS_RET_OK
$RENAME ENDP
BREAK <$FIND_FIRST - find first matching xenix filename>
;
; Assembler usage:
; MOV AH, FindFirst
; LDS DX, name
; MOV CX, attr
; INT 21h
; ; DMA address has datablock
;
; Error Returns:
; AX = error_file_not_found
; = error_no_more_files
;
procedure $FIND_FIRST,near
ASSUME DS:NOTHING,ES:NOTHING
CALL Validate_path
JNC find_get
JZ find_get
error error_file_not_found
find_get:
MOV SI,DX
PUSH CX
INC BYTE PTR [NoSetDir] ; if we find a dir, don't change to it
MOV WORD PTR [Creating],0E500h
CALL GetPath
POP CX
MOV [Attrib],CL
find_check:
JNC find_check_attr
find_no_more:
error error_no_more_files
find_check_attr:
MOV DS,WORD PTR [CURBUF+2]
MOV CH,[BX.dir_attr]
invoke MatchAttributes
JZ found_it
PUSH [LastEnt]
MOV BX,[DirStart]
JMP find_it_next
found_it:
LES DI,[DMAADD]
MOV AL,[Attrib]
STOSB ; find_buf 0 = attribute in search
MOV AL,[ThisDrv]
STOSB ; find_buf 1 = drive
MOV CX,11
PUSH BX
MOV SI,OFFSET DOSGROUP:NAME1; find_buf 2 = formatted name
PUSH DS
PUSH SS
POP DS
IF KANJI
MOVSB
CMP BYTE PTR ES:[DI-1],5
JNZ NOTKANJB
MOV BYTE PTR ES:[DI-1],0E5H
NOTKANJB:
DEC CX
ENDIF
REP MOVSB
POP DS
MOV AX,[LastEnt]
STOSW ; find_buf 13 = LastEnt
MOV AX,WORD PTR [ThisDPB]
STOSW ; find_buf 15 = ThisDPB
MOV AX,WORD PTR [ThisDPB+2]
STOSW
MOV AX,[DirStart]
STOSW ; find_buf 19 = DirStart
MOV AL,[BX].dir_attr
STOSB ; find_buf 21 = attribute found
MOV AX,[BX].dir_time
STOSW ; find_buf 22 = time
MOV AX,[BX].dir_date
STOSW ; find_buf 24 = date
MOV AX,[BX].dir_size_l
STOSW ; find_buf 26 = low(size)
MOV AX,[BX].dir_size_h
STOSW ; find_buf 28 = high(size)
POP SI
MOV CX,8 ; find_buf 30 = packed name
find_loop_name:
LODSB
STOSB
CMP AL," "
LOOPNZ find_loop_name
JNZ find_check_dot
DEC DI
find_check_dot:
ADD SI,CX
CMP BYTE PTR [SI]," "
JZ find_done
MOV AL,"."
STOSB
MOV CX,3
find_loop_ext:
LODSB
STOSB
CMP AL," "
LOOPNZ find_loop_ext
JNZ find_done
DEC DI
find_done:
XOR AL,AL
STOSB
transfer SYS_RET_OK
$FIND_FIRST ENDP
BREAK <$FIND_NEXT - scan for match in directory>
;
; Assembler usage:
; ; dma points at area returned by find_first
; MOV AH, findnext
; INT 21h
; ; next entry is at dma
;
; Error Returns:
; AX = error_no_more_files
;
procedure $FIND_NEXT,near
ASSUME DS:NOTHING,ES:NOTHING
LDS SI,[DMAADD]
MOV DX,SI
INC DX
PUSH SI
invoke MOVNAMENOSET
POP SI
JNC find_load
findnext_no_more:
error error_no_more_files
find_load:
MOV AX,[SI.find_buf_LastEnt]
LES BP,[SI.find_buf_ThisDPB]
OR AX,AX
JS findnext_no_more
MOV BX,[SI.find_buf_DirStart]
MOV DL,[SI.find_buf_sattr]
MOV [Attrib],DL
PUSH AX
MOV WORD PTR [ThisDPB],BP
MOV WORD PTR [ThisDPB+2],ES
find_it_next:
invoke SetDirSrch
ASSUME DS:DOSGROUP
POP AX
MOV [ENTLAST],-1
invoke GetEnt
invoke NextEnt
JMP find_check
$find_next ENDP
do_ext
CODE ENDS
END
+626
View File
@@ -0,0 +1,626 @@
;
; xenix file calls for MSDOS
;
INCLUDE DOSSEG.ASM
IFNDEF KANJI
KANJI EQU 0 ;FALSE
ENDIF
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME SS:DOSGROUP,CS:DOSGROUP
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list
TITLE XENIX - IO system to mimic UNIX
NAME XENIX
i_need NoSetDir,BYTE
i_need CURDRV,BYTE
i_need IOCALL,BYTE
i_need IOMED,BYTE
i_need IOSCNT,WORD
i_need IOXAD,DWORD
i_need DIRSTART,WORD
i_need ATTRIB,BYTE
i_need THISFCB,DWORD
i_need AuxStack,BYTE
i_need Creating,BYTE
i_need ThisDRV,BYTE
i_need NAME1,BYTE
i_need LastEnt,WORD
i_need ThisDPB,DWORD
i_need EntLast,WORD
i_need CurrentPDB,WORD
i_need sft_addr,DWORD ; pointer to head of table
i_need CURBUF,DWORD ; pointer to current buffer
i_need DMAADD,DWORD ; pointer to current dma address
BREAK <Local data>
CODE ENDS
DATA SEGMENT BYTE PUBLIC 'DATA'
PushSave DW ?
PushES DW ?
PushBX DW ?
xenix_count DW ?
DATA ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
BREAK <get_sf_from_sfn - translate a sfn into sf pointer>
;
; get_sf_from_sfn
; input: AX has sfn (0 based)
; DS is DOSGROUP
; output: JNC <found>
; ES:DI is sf entry
; JC <error>
; ES,DI indeterminate
;
procedure get_sf_from_sfn,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
PUSH AX ; we trash AX in process
LES DI,[sft_addr]
get_sfn_loop:
CMP DI,-1 ; end of chain of tables?
JZ get_sf_invalid ; I guess so...
SUB AX,ES:[DI].sft_count ; chop number of entries in this table
JL get_sf_gotten ; sfn is in this table
LES DI,ES:[DI].sft_link ; step to next table
JMP get_sfn_loop
get_sf_gotten:
ADD AX,ES:[DI].sft_count ; reset to index in this table
PUSH BX
MOV BX,SIZE sf_entry
MUL BL ; number of bytes offset into table
POP BX
ADD AX,sft_table ; offset into sf table structure
ADD DI,AX ; offset into memory
CLC
JMP SHORT get_sf_ret
get_sf_jfn_invalid:
get_sf_invalid:
STC
get_sf_jfn_ret:
get_sf_ret:
POP AX ; remember him?
RET
get_sf_from_sfn ENDP
BREAK <get_sf_from_jfn - translate a jfn into sf pointer>
;
; get_sf_from_jfn
; input: BX is jfn 0 based
; DS is DOSGROUP
; output: JNC <found>
; ES:DI is sf entry
; JC <error>
; ES,DI is indeterminate
;
procedure get_sf_from_jfn,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
PUSH AX ; save him
invoke get_jfn_pointer
JC get_sf_jfn_invalid
MOV AL,ES:[DI] ; get sfn
CMP AL,0FFh ; is it free?
JZ get_sf_jfn_invalid ; yep... error
XOR AH,AH
invoke get_sf_from_sfn ; check this sfn out...
JMP SHORT get_sf_jfn_ret ; condition codes are properly set
get_sf_from_jfn ENDP
BREAK <get_jfn_pointer - map a jfn into a pointer to jfn>
;
; get_jfn_pointer
; input: BX is jfn
; DS is DOSGROUP
; output: JNC <found>
; ES:DI is pointer to jfn
; JC <bad jfn>
;
procedure Get_jfn_pointer,NEAR
ASSUME DS:DOSGROUP,ES:NOTHING
CMP BX,FilPerProc
JAE get_jfn_bad
MOV ES,[CurrentPDB]
MOV DI,BX
ADD DI,PDB_JFN_Table
CLC
RET
get_jfn_bad:
STC
RET
get_jfn_pointer ENDP
BREAK <$Close - release a handle>
;
; Assembler usage:
; MOV BX, handle
; MOV AH, Close
; INT int_command
;
; Error return:
; AX = error_invalid_handle
;
procedure $Close,NEAR
ASSUME DS:NOTHING,ES:NOTHING
context DS
invoke get_jfn_pointer ; get jfn loc
JNC close_jfn
close_bad_handle:
error error_invalid_handle
close_jfn:
MOV AL,BYTE PTR ES:[DI]
CMP AL,0FFh
JE close_bad_handle
MOV BYTE PTR ES:[DI],0FFh;
XOR AH,AH
invoke get_sf_from_sfn
JC close_bad_handle
PUSH ES
POP DS
ASSUME DS:NOTHING
DEC [DI].sf_ref_count ; no more reference
LEA DX,[DI].sf_fcb
;
; need to restuff Attrib if we are closing a protected file
;
TEST [DI.sf_fcb.fcb_DevID],devid_file_clean+devid_device
JNZ close_ok
PUSH WORD PTR [DI].sf_attr
invoke MOVNAMENOSET
POP BX
MOV [Attrib],BL
invoke FCB_CLOSE_INNER
CMP AL,0FFh ; file not found error?
JNZ close_ok
error error_file_not_found
close_ok:
transfer SYS_RET_OK
$Close ENDP
BREAK <PushDMA, PopDMA, ptr_normalize - set up local dma and save old>
; PushDMA
; input: DS:DX is DMA
; output: DS:DX is normalized , ES:BX destroyed
; [DMAADD] is now set up to DS:DX
; old DMA is pushed
procedure PushDMA,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV PushES,ES
MOV PushBX,BX
POP PushSave
LES BX,DWORD PTR [DMAADD] ; get old dma
PUSH ES
PUSH BX
PUSH PushSave
invoke ptr_normalize ; get new dma
MOV WORD PTR [DMAADD],DX ; save IT!
MOV WORD PTR [DMAADD+2],DS
MOV ES,PushES
MOV BX,PushBX
RET
PushDMA ENDP
; PopDMA
; input: old DMA under ret address on stack
; output: [DMAADD] set to old version and stack popped
procedure PopDMA,NEAR
ASSUME DS:NOTHING,ES:NOTHING
POP PushSave
POP WORD PTR [DMAADD]
POP WORD PTR [DMAADD+2]
PUSH PushSave
RET
PopDMA ENDP
; ptr_normalize
; input: DS:DX is a pointer
; output: DS:DX is normalized (DX < 10h)
procedure ptr_normalize,NEAR
PUSH CX ; T1 = CX
PUSH DX ; T2 = DX
MOV CL,4
SHR DX,CL ; DX = (DX >> 4) (using CX)
MOV CX,DS
ADD CX,DX
MOV DS,CX ; DS = DS + DX (using CX)
POP DX
AND DX,0Fh ; DX = T2 & 0Fh
POP CX ; CX = T1
; PUSH AX
; PUSH DX
; MOV AX,DS
; PUSH CX
; MOV CL,4
; SHR DX,CL ; get upper part of dx
; POP CX
; ADD AX,DX ; add into seg address
; MOV DS,AX
; POP DX
; AND DX,0Fh ; save low part
; POP AX
RET
ptr_normalize ENDP
BREAK <$Read - Do file/device I/O>
;
; Assembler usage:
; LDS DX, buf
; MOV CX, count
; MOV BX, handle
; MOV AH, Read
; INT int_command
; AX has number of bytes read
; Errors:
; AX = read_invalid_handle
; = read_access_denied
;
procedure $Read,NEAR
ASSUME DS:NOTHING,ES:NOTHING
invoke PushDMA
CALL IO_setup
JC IO_err
CMP ES:[DI].sf_mode,open_for_write
JNE read_setup
IO_bad_mode:
MOV AL,read_access_denied
IO_err:
invoke PopDMA
transfer SYS_RET_ERR
read_setup:
invoke $FCB_RANDOM_READ_BLOCK ; do read
IO_done:
invoke get_user_stack ; get old frame
MOV AX,[SI].user_CX ; get returned CX
MOV CX,xenix_count
MOV [SI].user_CX,CX ; stash our CX
invoke PopDMA ; get old DMA
transfer SYS_RET_OK
$Read ENDP
BREAK <$Write - Do file/device I/O>
;
; Assembler usage:
; LDS DX, buf
; MOV CX, count
; MOV BX, handle
; MOV AH, Write
; INT int_command
; AX has number of bytes written
; Errors:
; AX = write_invalid_handle
; = write_access_denied
;
procedure $Write,NEAR
ASSUME DS:NOTHING,ES:NOTHING
invoke PushDMA
CALL IO_setup
JC IO_err
CMP ES:[DI].sf_mode,open_for_read
JE IO_bad_mode
invoke $FCB_RANDOM_WRITE_BLOCK ; do write
JMP IO_done
$write ENDP
IO_setup:
ASSUME DS:NOTHING,ES:NOTHING
context DS
MOV xenix_count,CX
invoke Get_sf_from_jfn
; ES:DI is sf pointer
MOV AL,read_invalid_handle ;Assume an error
MOV CX,xenix_count
LEA DX,[DI].sf_fcb
PUSH ES
POP DS
ASSUME DS:NOTHING
RET
BREAK <$LSEEK - set random record field>
;
; Assembler usage:
; MOV DX, offsetlow
; MOV CX, offsethigh
; MOV BX, handle
; MOV AL, method
; MOV AH, LSeek
; INT int_command
; DX:AX has the new location of the pointer
; Error returns:
; AX = error_invalid_handle
; = error_invalid_function
procedure $LSEEK,NEAR
ASSUME DS:NOTHING,ES:NOTHING
CMP AL,3
JB lseek_get_sf
error error_invalid_function
lseek_get_sf:
context DS
invoke get_sf_from_jfn
PUSH ES
POP DS
ASSUME DS:NOTHING
JC lseek_bad
;
; don't seek device
;
TEST [DI.sf_fcb+fcb_devid],devid_device
JZ lseek_dispatch
XOR AX,AX
XOR DX,DX
JMP SHORT lseek_ret
lseek_dispatch:
DEC AL
JL lseek_beginning
DEC AL
JL lseek_current
; move from end of file
; first, get end of file
XCHG AX,DX ; AX <- low
XCHG DX,CX ; DX <- high
ASSUME DS:NOTHING
ADD AX,[DI+sf_fcb+fcb_FILSIZ]
ADC DX,[DI+sf_fcb+fcb_FILSIZ+2]
JMP SHORT lseek_ret
lseek_beginning:
XCHG AX,DX ; AX <- low
XCHG DX,CX ; DX <- high
lseek_ret:
MOV WORD PTR [DI+sf_fcb+fcb_RR],AX
MOV WORD PTR [DI+sf_fcb+fcb_RR+2],DX
invoke get_user_stack
MOV [SI.user_DX],DX
MOV [SI.user_AX],AX
transfer SYS_RET_OK
lseek_current:
; ES:DI is pointer to sf... need to invoke set random record for place
XCHG AX,DX ; AX <- low
XCHG DX,CX ; DX <- high
ADD AX,WORD PTR [DI+sf_fcb+fcb_RR]
ADC DX,WORD PTR [DI+sf_fcb+fcb_RR+2]
JMP lseek_ret
lseek_bad:
error error_invalid_handle
$lseek ENDP
BREAK <$IOCTL - return/set device dependent stuff>
;
; Assembler usage:
; MOV BX, Handle
; MOV DX, Data
;
; (or LDS DX,BUF
; MOV CX,COUNT)
;
; MOV AH, Ioctl
; MOV AL, Request
; INT 21h
;
; Error returns:
; AX = error_invalid_handle
; = error_invalid_function
; = error_invalid_data
procedure $IOCTL,NEAR
ASSUME DS:NOTHING,ES:NOTHING
MOV SI,DS ;Stash DS for calls 2,3,4 and 5
context DS
CMP AL,3
JA ioctl_check_block ;Block device
PUSH DX
invoke get_sf_from_jfn
POP DX ;Restore DATA
JNC ioctl_check_permissions ; have valid handle
error error_invalid_handle
ioctl_check_permissions:
CMP AL,2
JAE ioctl_control_string
CMP AL,0
MOV AL,BYTE PTR ES:[DI+sf_fcb+fcb_devid]
JZ ioctl_read ; read the byte
OR DH,DH
JZ ioctl_check_device ; can I set with this data?
error error_invalid_data ; no DH <> 0
ioctl_check_device:
TEST AL,devid_ISDEV ; can I set this handle?
JZ ioctl_bad_fun ; no, it is a file.
MOV BYTE PTR ES:[DI+sf_fcb+fcb_devid],DL
transfer SYS_RET_OK
ioctl_read:
XOR AH,AH
TEST AL,devid_ISDEV ; Should I set high byte
JZ ioctl_no_high ; no
LES DI,DWORD PTR ES:[DI+sf_fcb+fcb_FIRCLUS] ;Get device pointer
MOV AH,BYTE PTR ES:[DI.SDEVATT+1] ;Get high byte
ioctl_no_high:
invoke get_user_stack
MOV DX,AX
MOV [SI.user_DX],DX
transfer SYS_RET_OK
ioctl_control_string:
TEST BYTE PTR ES:[DI+sf_fcb+fcb_devid],devid_ISDEV ; can I?
JZ ioctl_bad_fun ; no, it is a file.
LES DI,DWORD PTR ES:[DI+sf_fcb+fcb_FIRCLUS] ;Get device pointer
XOR BL,BL ; Unit number of char dev = 0
JMP SHORT ioctl_do_string
ioctl_check_block:
DEC AL
DEC AL ;4=2,5=3,6=4,7=5
CMP AL,3
JBE ioctl_get_dev
MOV AH,1
SUB AL,4 ;6=0,7=1
JZ ioctl_get_status
MOV AH,3
DEC AL
JNZ ioctl_bad_fun
ioctl_get_status:
PUSH AX
invoke GET_IO_FCB
POP AX
JC ioctl_acc_err
invoke IOFUNC
MOV AH,AL
MOV AL,0FFH
JNZ ioctl_status_ret
INC AL
ioctl_status_ret:
transfer SYS_RET_OK
ioctl_bad_fun:
error error_invalid_function
ioctl_acc_err:
error error_access_denied
ioctl_get_dev:
PUSH CX
PUSH DX
PUSH AX
PUSH SI ;DS in disguise
MOV AL,BL ;Drive
invoke GETTHISDRV
JC ioctl_bad_drv
invoke FATREAD ;"get" the drive
MOV BL,ES:[BP.dpb_UNIT] ; Unit number
LES DI,ES:[BP.dpb_driver_addr]
CLC ;Make sure error jump not taken
ioctl_bad_drv:
POP SI
POP AX
POP DX
POP CX
JC ioctl_acc_err
ioctl_do_string:
TEST ES:[DI.SDEVATT],DEVIOCTL ;See if device accepts control
JZ ioctl_bad_fun ;NO
DEC AL
DEC AL
JZ ioctl_control_read
MOV [IOCALL.REQFUNC],DEVWRIOCTL
JMP SHORT ioctl_control_call
ioctl_control_read:
MOV [IOCALL.REQFUNC],DEVRDIOCTL
ioctl_control_call:
MOV AL,DRDWRHL
MOV AH,BL ;Unit number
MOV WORD PTR [IOCALL.REQLEN],AX
XOR AX,AX
MOV [IOCALL.REQSTAT],AX
MOV [IOMED],AL
MOV [IOSCNT],CX
MOV WORD PTR [IOXAD],DX
MOV WORD PTR [IOXAD+2],SI
PUSH ES
POP DS
ASSUME DS:NOTHING
MOV SI,DI ;DS:SI -> driver
PUSH SS
POP ES
MOV BX,OFFSET DOSGROUP:IOCALL ;ES:BX -> Call header
invoke DEVIOCALL2
MOV AX,[IOSCNT] ;Get actual bytes transferred
transfer SYS_RET_OK
$IOCTL ENDP
BREAK <File_Times - modify write times on a handle>
;
; Assembler usage:
; MOV AH, FileTimes
; MOV AL, func
; MOV BX, handle
; ; if AL = 1 then then next two are mandatory
; MOV CX, time
; MOV DX, date
; INT 21h
; ; if AL = 0 then CX/DX has the last write time/date
; ; for the handle.
;
; Error returns:
; AX = error_invalid_function
; = error_invalid_handle
;
procedure $File_times,near
CMP AL,2
JB filetimes_ok
error error_invalid_function
filetimes_ok:
PUSH SS
POP DS
CALL Get_sf_from_jfn
JNC filetimes_disp
error error_invalid_handle
filetimes_disp:
OR AL,AL
JNZ filetimes_set
MOV CX,ES:[DI.sf_fcb.fcb_FTIME]
MOV DX,ES:[DI.sf_fcb.fcb_FDATE]
invoke Get_user_stack
MOV [SI.user_CX],CX
MOV [SI.user_DX],DX
transfer SYS_RET_OK
filetimes_set:
MOV ES:[DI.sf_fcb.fcb_FTIME],CX
MOV ES:[DI.sf_fcb.fcb_FDATE],DX
AND ES:[DI.sf_fcb.fcb_DEVID],NOT devid_file_clean
transfer SYS_RET_OK
$file_times ENDP
do_ext
CODE ENDS
END