home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
sampler0
/
chain.asm
< prev
next >
Wrap
Assembly Source File
|
1989-05-28
|
25KB
|
591 lines
PAGE ,132
TITLE File Chain Program, Version 2.16, 24-Dec-1986
; Bug Fix Version 2.17, 28 May 1989 by David Gwillim
; Subdirectories were reported as using 0 clusters with 100% waste
; Also corrected typo for pgm lines storing file size to SIZEMSB
; Changed/Added lines marked with a comment starting with ;!!
;
; Written By Steven Georgiades
;
; File Chain Program
; Will respond with a list of the disk clusters that make up the file chain
; for the requested file.
;
; If you are using this program and find it of value, your
; contribution in any amount ($5.00 suggested) will be greatly
; appreciated. Makes checks payable to Steven M. Georgiades.
; Thank you.
;
; If you have any questions or comments about this or any other
; SMG program, call or write:
;
; Steven M. Georgiades
; 701-H South Hayward Street
; Anaheim, CA 92804
; (714) 826-9549
;
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
ORG 5CH
FCB LABEL BYTE
ORG 80H
PARAM LABEL BYTE
ORG 100H
CHAIN: JMP BEGIN
CHAINMSG1 DB "The Chain for $"
CHAINMSG2 DB " is:",13,10,10,"$"
CHAINMSG3 DB 13,10,10
CHAINMSG4 DB "Total Clusters in File = XXXXX",13,10,10
CHAINMSG5 DB "Physical File Length = XXXXXXXX",13,10,"$" ;!!
CHAINMSG6 DB "Logical File Length = XXXXXXXX ("
PERCENT DB " 0.00% Waste)",13,10,"$"
ISDIR DB 'File is a SUBDIRECTORY',13,10,"$" ;!!
LOGSZMSG DW OFFSET CHAINMSG6
CLSTSTR DB "XXXXX$"
PRCNT100 DB "100.0"
ANDSTR DB " , $"
THRUSTR DB " to$"
SPECERR DB "Invalid File or Path Specification",7,": $"
CRLF DB 13,10,"$"
SIGNON DB "File Chain Program, Version 2.17",13,10 ;!!
DB "SMG Software",13,10
DB "(C) Copyright 1986, 1989 Steven M. Georgiades" ;!!
DB 13,10,13,10,"$" ;!!
USAGE DB 13,10,"Usage:",13,10,13,10 ;!!
DB " CHAIN [d:][path]filename[.ext]",13,10,13,10 ;!!
DB " Will respond with a list of the disk clusters that make up the specified",13,10
DB " file. Note that wildcards are NOT allowed.",13,10,"$"
CLSTSEC DW ?
DIR_LEN DW ?
DIRBUF DW ?
DIRSEC DW ?
DRIVE DB ?
EOF DW 0FF8H
FATSEC DW ?
FATSIZE DB 3
FILENAME DB 13 DUP(0)
PREV DW ?
RANGE DB 0
SECSIZE DW ?
SIZLSB DW ?
SIZMSB DW ?
STARTSEC DW ?
FILESPEC DB "$",79 DUP(0)
BEGIN: MOV AH,9 ; Output Sign-On Message
MOV DX,OFFSET SIGNON
INT 21H
MOV AH,19H ; Get Default Drive
INT 21H
MOV DRIVE,AL ; and Save
MOV SI,OFFSET PARAM ; Set up Pointer to Parameter
LODSB ; Read Parameter Length
CBW
MOV BX,AX
MOV BYTE PTR [SI][BX],0 ; Terminate Parameter String
STRIP: LODSB ; Strip Off Leading Whitespace
CMP AL,' '
JE STRIP
CMP AL,9
JE STRIP
OR AL,AL ; If End-of-Parameter, Error
JNZ NO_ERR1
MOV DX,OFFSET USAGE
JMP ERROUT
NO_ERR1: DEC SI ; ReUse Last Character
MOV DI,OFFSET FILESPEC ; Point to FileSpec Buffer
CMP BYTE PTR [SI+1],':' ; If 2nd Character is Colon,
JNE GET_PATH
AND AL,0DFH
SUB AL,'A' ; Get Drive Number
MOV DRIVE,AL
ADD SI,2 ; and Scan Past
GET_PATH: MOV AL,DRIVE ; Get Drive Number
ADD AL,'A' ; Convert to Drive Number
STOSB ; in FileSpec
MOV AL,':' ; Add Colon to FileSpec
STOSB
CMP BYTE PTR [SI],'\' ; If Next Character is not '\',
JE COPYPATH
MOV AL,'\'
STOSB
PUSH SI ; Get Current Path to FileSpec
MOV SI,DI
MOV AH,47H
MOV DL,DRIVE
INC DL
INT 21H
POP SI
MOV AL,0 ; Find End-of-FileSpec
MOV CX,64
REPNE SCASB
JE NO_ERR2
JMP ERROR
NO_ERR2: DEC DI
CMP BYTE PTR [DI-1],'\' ; If Root DIR, Skip
JE COPYPATH
MOV AL,'\' ; End-of-FileSpec = '\'
STOSB
COPYPATH: LODSB ; Copy Rest of Parameter
OR AL,AL ; to FileSpec
JZ COPYDONE
STOSB
JMP SHORT COPYPATH
COPYDONE: MOV AL,'$' ; Set End-of-FileSpec
STOSB
MOV DX,OFFSET FILESPEC ; Convert to Upper Case
CALL UPPER
MOV AL,DRIVE ; Read Boot Record
MOV CX,1
MOV DX,0
MOV BX,OFFSET FATBUF
INT 25H
POPF
MOV AX,FATBUF[11] ; Read Sector Size
MOV SECSIZE,AX ; and Save
MOV AL,BYTE PTR FATBUF[13] ; Read Sectors per Cluster
XOR AH,AH
MOV CLSTSEC,AX ; and Save
MOV CX,FATBUF[14] ; Read # of Reserved Sectors
MOV AL,BYTE PTR FATBUF[16] ; Read # of FAT's
XOR AH,AH ; Convert to Word
MOV BX,FATBUF[22] ; Read Sectors per FAT
MOV FATSEC,BX
MUL BX ; Calculate Total FAT Sectors
ADD CX,AX ; Add to Reserved Sectors
MOV AX,FATBUF[17] ; Read Number of DIR Entries
MOV DIR_LEN,AX
PUSH CX ; Calculate DIR Sectors
MOV CL,5
SHL AX,CL
POP CX
MOV BX,SECSIZE
XOR DX,DX
DIV BX
OR DX,DX ; Adjust for Partial Sector
JZ NO_ADD
INC AX
NO_ADD: MOV DIRSEC,AX ; Save DIR Sectors
ADD CX,AX ; Add DIR Sectors to Reserved
MOV STARTSEC,CX ; Save in STARTSEC
MOV AX,FATSEC ; Calculate FAT Buffer Size
MOV BX,SECSIZE
MUL BX
MOV BX,AX
LEA AX,FATBUF[BX] ; Get DIR Buffer Pointer
MOV DIRBUF,AX
MOV AX,FATBUF[19] ; Read Total Sectors on Media
SUB AX,CX ; Calculate Total Data Clusters
MOV BX,CLSTSEC
XOR DX,DX
DIV BX
CMP AX,4079 ; If Necessary, Adjust FAT Size
JLE FAT_OK
MOV FATSIZE,4
MOV EOF,0FFF8H
FAT_OK: MOV AL,DRIVE ; Read FAT
MOV CX,FATSEC
MOV DX,1
MOV BX,OFFSET FATBUF
INT 25H
POPF
MOV AL,DRIVE ; Read Root Directory
MOV CX,DIRSEC
MOV DX,STARTSEC
SUB DX,CX
MOV BX,DIRBUF
INT 25H
POPF
MOV SI,OFFSET FILESPEC[3] ; Point to First Element of Path
NEXT_FLD: MOV DI,OFFSET FILENAME ; Point to FileName Buffer
NEXTCHAR: LODSB ; Copy Path Element to FileName
CMP AL,'\' ; until '\' or '$'
JE GOT_DIR
CMP AL,'$'
JE GOT_FNM
STOSB
JMP SHORT NEXTCHAR
GOT_DIR: MOV AL,0 ; If '\', Read Subdirectory
STOSB
CALL READDIR
JNC NEXT_FLD ; If No Error, Get Next Dir
JMP ERROR ; Else Flag Error
GOT_FNM: MOV AL,0 ; If '$',
STOSB
CALL SRCHFILE ; Read File DIR Info
JNC NO_ERR3
JMP ERROR ; If Error, Say So
NO_ERR3: MOV AX,[BX+28] ; Read File Length
MOV SIZLSB,AX
MOV DX,[BX+30]
MOV SIZMSB,DX ;!! was mov sizmsb,ax
MOV DI,OFFSET CHAINMSG6[31] ; Convert to ASCII
CALL DEC8OUT ; Strip Off Leading Zeroes
CALL STRIP0
MOV AH,9 ; Output FileSpec Message
MOV DX,OFFSET CHAINMSG1
INT 21H
MOV AH,9
MOV DX,OFFSET FILESPEC
INT 21H
MOV AH,9
MOV DX,OFFSET CHAINMSG2
INT 21H
MOV BX,[BX+26] ; Read Starting Cluster Number
XOR CX,CX ; Cluster Count = 0
OR BX,BX ; If Start Cluster = 0, Done
JZ LASTCLST
MOV AX,BX ; Output First Cluster Number
CALL OUT_CLST
MOV PREV,BX ; Previous Cluster = First
INC CX ; Cluster Count = 1
CALL NEXTCLST ; Get Next Cluster Number
CMP BX,EOF ; If Last, Skip
JNB LASTCLST
CLSTLOOP: INC CX ; Increment Cluster Count
MOV AX,PREV ; If Cluster is Previous + 1,
INC AX
CMP AX,BX
JNE CLSTOUT
MOV RANGE,-1 ; Set Range Flag
JMP SHORT NEXTONE
CLSTOUT: CMP RANGE,0 ; Else
JE NORANGE ; If Range Flag is Set,
MOV AH,9 ; Output " - "
MOV DX,OFFSET THRUSTR
INT 21H
MOV AX,PREV ; Output Last Clstr in Range
CALL OUT_CLST
MOV RANGE,0 ; Reset Range Flag
NORANGE: MOV AH,9 ; Output ", "
MOV DX,OFFSET ANDSTR
INT 21H
MOV AX,BX ; Output Cluster Number
CALL OUT_CLST
NEXTONE: MOV PREV,BX ; Previous = Current
CALL NEXTCLST ; Get Next Cluster Number
CMP BX,EOF ; If Not EOF, Repeat
JB CLSTLOOP
CMP RANGE,0 ; If Range Flag is Set,
JE LASTCLST
MOV AH,2 ; Output " - "
MOV DL,'-'
INT 21H
MOV AX,PREV ; Output Last Cluster of Range
CALL OUT_CLST
LASTCLST: MOV AX,SIZMSB ; If Size = 0, 100% Waste
OR AX,SIZLSB
JNZ NOT_ZERO
JCXZ LC1 ;!! allow for <DIR> files
MOV LOGSZMSG,OFFSET ISDIR ;!! say this is a subdirectory
JMP SHORT CLSTCNT ;!!
LC1: MOV SI,OFFSET PRCNT100
MOV DI,OFFSET PERCENT
MOV CX,5
REP MOVSB
JMP SHORT CLSTCNT
NOT_ZERO: MOV AX,SECSIZE ; Calculate Percent Waste
MOV BX,CLSTSEC
MUL BX
MOV BX,AX
MUL CX
SUB AX,SIZLSB
MOV DX,100
MUL DX
DIV BX
PUSH DX
XOR DX,DX
DIV CX
PUSH DX
MOV DI,OFFSET PERCENT[2] ; Convert Percent to ASCII
CALL DEC2OUT
CALL STRIP0
POP AX
MUL BX
POP DI
ADD AX,DI
ADC DX,0
DIV CX
MOV DX,100
MUL DX
DIV BX
MOV DI,OFFSET PERCENT[5]
CALL DEC2OUT
CLSTCNT: MOV AX,CX ; Convert Cluster Count to ASCII
MOV DI,OFFSET CHAINMSG4[31]
CALL DEC5OUT
CALL STRIP0 ; Strip Off Leading Zeroes
MOV AX,CLSTSEC ; Calculate Physical File Size
MUL CX
MOV CX,SECSIZE
MUL CX
MOV DI,OFFSET CHAINMSG5[31] ; Convert to ASCII
CALL DEC8OUT
CALL STRIP0 ; Strip Off Leading Zeroes
MOV AH,9 ; Output Trailer Message
MOV DX,OFFSET CHAINMSG3
INT 21H
MOV AH,9 ;!! Output Logical Size message
MOV DX,LOGSZMSG ;!!
INT 21H ;!!
MOV AX,4C00H ; Exit to DOS
INT 21H
ERROR: MOV AH,9 ; Output Error Message
MOV DX,OFFSET SPECERR
INT 21H
MOV AH,9
MOV DX,OFFSET FILESPEC ; Output FileSpec
INT 21H
MOV DX,OFFSET CRLF
ERROUT: MOV AH,9
INT 21H
MOV AX,4C01H ; Exit to DOS
INT 21H
SRCHFILE: PUSH AX ; Save Register
PUSH CX
PUSH DI
PUSH SI
CMP FILENAME,'.' ; If Filename Starts with '.',
JNE SRCHFIL2
MOV SI,OFFSET FILENAME ; Copy Filename to FCB
MOV DI,OFFSET FCB[1]
MOV CX,11
SRCHFIL1: LODSB
STOSB
OR AL,AL
LOOPNZ SRCHFIL1
INC CX ; and Pad With Spaces
DEC DI
MOV AL,' '
REP STOSB
JMP SHORT SRCHFIL3
SRCHFIL2: MOV AX,2900H ; Else Parse Filename
MOV SI,OFFSET FILENAME
MOV DI,OFFSET FCB
INT 21H
SRCHFIL3: MOV DI,OFFSET FCB[1] ; Point to Filename in FCB
MOV SI,DIRBUF ; Point to Start of DIRBUF
MOV CX,DIR_LEN ; Load DIR Length
JCXZ SRCHFIL5 ; If Zero, Not Found
SRCHFIL4: PUSH CX ; Save Registers
PUSH DI
PUSH SI
MOV CX,11 ; Compare Filename
REPE CMPSB
POP SI ; Restore Registers
POP DI
POP CX
JE SRCHFIL6 ; If Match, Found
ADD SI,32 ; Else Next DIR Entry
LOOP SRCHFIL4 ; and Repeat
SRCHFIL5: STC ; Set Error Flag
JMP SHORT SRCHFIL7 ; Done
SRCHFIL6: MOV BX,SI ; Set Pointer to DIR Entry
CLC ; Clear Error Flag
SRCHFIL7: POP SI ; Restore Registers
POP DI
POP CX
POP AX
RET ; Done
READDIR: PUSH CX ; Save Registers
PUSH DI
PUSH SI
CALL SRCHFILE ; Search for DIR
JC READDIR2 ; If Not Found, Error
MOV BX,[BX+26] ; Get Starting Cluster Number
MOV DIR_LEN,0 ; DIR Length = 0
OR BX,BX ; If Start Cluster = 0, Error
JZ READDIR2
MOV AX,SECSIZE ; Calculate DIR Entries/Cluster
MOV CX,CLSTSEC
MUL CX
MOV CL,5
SHR AX,CL
MOV CX,AX
MOV DI,DIRBUF ; Point to DIR Buffer
READDIR1: CALL READCLST ; Read Cluster
ADD DIR_LEN,CX ; Increment DIR Length
CMP BX,EOF ; If Not Last Cluster,
JB READDIR1 ; Get Next Cluster
JMP SHORT READDIR3 ; Done Reading DIR
READDIR2: STC ; Set Error Flag
READDIR3: POP SI ; Restore Registers
POP DI
POP CX
RET ; Done
READCLST: PUSH AX ; Save Registers
PUSH CX
PUSH DX
MOV AX,BX ; Calculate Absolute Sector #
SUB AX,2
MOV CX,CLSTSEC
MUL CX
ADD AX,STARTSEC
MOV DX,AX
MOV AL,DRIVE
PUSH BX ; Save Registers
PUSH DI
MOV BX,DI ; Read Cluster
INT 25H
POPF
POP DI ; Restore Registers
POP BX
CALL NEXTCLST ; Get Next Cluster Number
MOV AX,CLSTSEC ; Increment Buffer Pointer
MOV CX,SECSIZE
MUL CX
ADD DI,AX
POP DX ; Restore Registers
POP CX
POP AX
RET ; Done
NEXTCLST: CMP FATSIZE,3 ; If FAT Size = 16 Bits,
JE NEXTCLS1
SHL BX,1 ; Simply Read Next Cluster #
MOV BX,FATBUF[BX]
RET ; Done
NEXTCLS1: PUSH AX ; Save Registers
PUSH CX
MOV AX,BX ; Word # = Cluster # * 1.5
SHL AX,1
ADD BX,AX
SHR BX,1
MOV BX,FATBUF[BX]
JNC NEXTCLS2 ; If Odd, Use 12 MSB's
MOV CL,4
SHR BX,CL
NEXTCLS2: AND BX,0FFFH ; Else Use 12 LSB's
POP CX ; Restore Registers
POP AX
RET ; Done
UPPER: PUSH AX ; Save Registers
PUSH DX
PUSH DI
PUSH SI
MOV SI,DX ; Set Up Source Index
MOV DI,DX ; Set Up Destination Index
UPPER1: LODSB ; Read From Source
OR AL,AL ; If EOS, Done
JZ UPPER3
CMP AL,'a' ; If Lower Case,
JL UPPER2
CMP AL,'z'
JG UPPER2
SUB AL,'a'-'A' ; Convert to Upper Case
UPPER2: STOSB ; Save in Destination
JMP SHORT UPPER1 ; Repeat
UPPER3: POP SI ; Restore Registers
POP DI
POP DX
POP AX
RET ; Done
OUT_CLST: PUSH AX ; Save Registers
PUSH DX
PUSH DI
MOV DI,OFFSET CLSTSTR[5] ; Convert Cluster # to Decimal
CALL DEC5OUT
CALL STRIP0 ; Strip Off Leading Zeroes
MOV AH,9 ; Output Cluster Number
MOV DX,OFFSET CLSTSTR
INT 21H
POP DI ; Restore Registers
POP DX
POP AX
RET ; Done
STRIP0: CMP BYTE PTR [DI],'0' ; If Character != '0', Done
JNE STRIP1
CMP BYTE PTR [DI+1],'0' ; If Next Character != Digit,
JL STRIP1 ; Done
CMP BYTE PTR [DI+1],'9'
JG STRIP1
MOV BYTE PTR [DI],' ' ; Change '0' to ' '
INC DI ; Point to Next Character
JMP SHORT STRIP0 ; Repeat
STRIP1: RET ; Done
DEC2OUT: PUSH AX ; Save Registers
PUSH BX
XOR AH,AH ; Clear AH
MOV BL,10 ; AH=AX%10,AL=AX/10
DIV BL
ADD AX,'00' ; Convert to ASCII
SUB DI,2
MOV [DI],AX ; Store in String
POP BX ; Restore Registers
POP AX
RET ; Done
DEC4OUT: PUSH AX ; Save Registers
PUSH BX
MOV BL,100 ; AH=AX%100,AL=AX/100
DIV BL
XCHG AH,AL ; Convert 2 LSD's
CALL DEC2OUT
XCHG AH,AL ; Convert 2 MSD's
CALL DEC2OUT
POP BX ; Restore Registers
POP AX
RET ; Done
DEC5OUT: PUSH AX ; Save Registers
PUSH BX
PUSH DX ; DX=AX%10000,AX=AX/10000
MOV BX,10000
XOR DX,DX
DIV BX
XCHG DX,AX ; Convert 4 LSD's
CALL DEC4OUT
XCHG DX,AX ; Convert MSD
ADD AL,'0'
SUB DI,1
MOV [DI],AL
POP DX ; Restore Registers
POP BX
POP AX
RET ; Done
DEC8OUT: PUSH AX ; Save Registers
PUSH BX
PUSH DX
MOV BX,10000 ; DX=DX:AX%10000,AX=DX:AX/10000
DIV BX
XCHG DX,AX ; Convert 4 LSD's
CALL DEC4OUT
XCHG DX,AX ; Convert 4 MSD's
CALL DEC4OUT
POP DX ; Restore Registers
POP BX
POP AX
RET ; Done
FATBUF LABEL WORD
CODE ENDS
END CHAIN