901 lines
26 KiB
NASM
901 lines
26 KiB
NASM
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
|
||
|