home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
sampler0
/
owner.asm
< prev
next >
Wrap
Assembly Source File
|
1987-04-21
|
30KB
|
676 lines
PAGE ,132
TITLE Cluster Owner Program, Version 1.61, 21-Apr-1987
;
; Written By Steven Georgiades
;
;
; If you have any questions or comments about this or any other
; SMG program, call or write:
;
; Steven M. Georgiades
; SMG Software
; 701-H South Hayward Street
; Anaheim, CA 92804
;
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
OWNER: JMP BEGIN
DIGIT DB "0123456789ABCDEF"
PARM_ERR DB "Illegal Parameter!",7
CRLF DB 13,10,"$"
READERR DB "Error Reading Drive X:",7,13,10,"$"
SIGNON DB "Cluster Owner Program, Version 1.61",13,10
DB "SMG Software",13,10
DB "(C) Copyright 1986,1987 Steven Georgiades",13,10,10,"$"
USAGE DB "Usage:",13,10,10
DB " OWNER [d:] n [[d:] n [...]]",13,10,10
DB " d: = Optional Drive Letter",13,10
DB " n = Cluster Number to Check",13,10,10,"$"
CLUSTMSG DB "Cluster XXXXX $"
OWNERMSG DB "is Owned by $"
BADMSG DB "is Marked as Bad",13,10,"$"
FREEMSG DB "is not is Use by any File",13,10,"$"
INVALID DB "does not Exist!",7,13,10,"$"
LOSTMSG DB "Appears to be Lost!",7,13,10,"$"
RESVMSG DB "is Reserved",13,10,"$"
CLSTSEC DW ?
CLSTTOT DW ?
CLUST DW ?
DIR_LEN DW ?
DIRBUF DW ?
DIRSEC DW ?
DRIVE DB ?
EOF DW 0FF8H
FATSEC DW ?
FATSIZE DB 3
LASTDRV DB -1
RDIR_LEN DW ?
SECSIZE DW ?
STARTSEC DW ?
DIRNAME DB 14 DUP(?)
FILESPEC DB "X:\"
PATH DB "$",79 DUP(?)
FILENAME DB 14 DUP(?)
BEGIN: MOV AH,9 ; Output Sign-On Message
MOV DX,OFFSET SIGNON
INT 21H
MOV AH,19H ; Get Default Drive Number
INT 21H
MOV DRIVE,AL ; and Save
MOV SI,OFFSET PARAM ; Set up Pointer to Parameter
LODSB ; Read Parameter Length
CMP AL,2
JNB GET_PARM
MOV DX,OFFSET USAGE
JMP SHORT GET_OW03
GET_PARM: 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,
JZ EXIT ; Continue Proccessing
CMP BYTE PTR [SI],':' ; If Drive Letter,
JNE NOTDRIVE
AND AL,0DFH ; Convert to Drive Number
SUB AL,'A'
MOV DRIVE,AL ; and Save
LODSB ; Skip Colon
JMP SHORT STRIP ; Continue
NOTDRIVE: DEC SI ; ReUse Last Character
CALL GET_WORD ; Read Cluster Number (Hex)
JNE PARM_OK ; If Error,
PARMERR: MOV DX,OFFSET PARM_ERR ; Output Parameter Error
MOV AH,9
INT 21H
MOV AX,4C01H ; Exit to DOS
INT 21H
PARM_OK: MOV CLUST,DX ; Save Cluster Number
CALL GET_OWNR ; Find Cluster Owner
JMP SHORT STRIP ; Get Next Parameter
EXIT: MOV AX,4C00H ; Exit to DOS
INT 21H
GET_OWNR: PUSH AX ; Save Registers
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
MOV PATH,'$' ; Initialize Path
MOV AL,DRIVE ; If drive has changed,
CMP AL,LASTDRV
JNE GET_OW01
JMP GET_OW07
GET_OW01: MOV LASTDRV,AL ; Last Drive = This Drive
MOV CX,1 ; Read Boot Record
MOV DX,0
MOV BX,OFFSET FATBUF
INT 25H
JNC GET_OW04 ; If Error,
GET_OW02: POPF
MOV AL,DRIVE ; Convert Drive Number
ADD AL,'A'
MOV READERR[20],AL
MOV DX,OFFSET READERR ; Point to Read Error
GET_OW03: MOV AH,9 ; Output Error Message
INT 21H
MOV AX,4C01H ; Exit to DOS
INT 21H
GET_OW04: 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 RDIR_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 GET_OW05
INC AX
GET_OW05: MOV DIRSEC,AX ; Save DIR Sectors
ADD CX,AX ; Add DIR Sectors to Reserved
MOV STARTSEC,CX ; Save in STARTSEC
MOV AX,FATSEC ; Determine FAT Buffer Size
MOV BX,SECSIZE
MUL BX
ADD AX,OFFSET FATBUF
MOV DIRBUF,AX ; Save DIRBUF Pointer
MOV AX,FATBUF[19] ; Read Total Sectors on Media
SUB AX,CX ; Calc. Total Data Clusters
MOV BX,CLSTSEC
XOR DX,DX
DIV BX
ADD AX,2
MOV CLSTTOT,AX ; and Save
CMP AX,4081 ; Adjust FAT Size
JLE GET_OW06
MOV FATSIZE,4
MOV EOF,0FFF8H
JMP SHORT GET_OW07
GET_OW06: MOV FATSIZE,3
MOV EOF,0FF8H
GET_OW07: MOV AL,DRIVE ; Read FAT
MOV CX,FATSEC
MOV DX,1
MOV BX,OFFSET FATBUF
INT 25H
JNC GET_OW08
JMP GET_OW02 ; If Error, Say So
GET_OW08: POPF
MOV BX,CLUST ; Get Cluster Number
MOV AX,BX ; Convert Cluster # to Decimal
MOV DI,OFFSET CLUSTMSG[13]
CALL DEC5OUT
CALL STRIP0 ; Strip Off Leading Zeroes
MOV AH,9
MOV DX,OFFSET CLUSTMSG ; Output Cluster Message
INT 21H
CMP BX,CLSTTOT ; Test Cluster Number
JNB GET_OW09
CMP BX,2
JNB GET_OW10
GET_OW09: MOV DX,OFFSET INVALID ; If Invalid, Say So
JMP SHORT GET_OW17
GET_OW10: CALL NEXTCLST ; Determine Next Cluster
OR BX,BX ; If Not in Use, Say So
JNZ GET_OW11
MOV DX,OFFSET FREEMSG
JMP SHORT GET_OW17
GET_OW11: MOV AX,EOF ; If In Use, Continue
CMP BX,AX
JAE GET_OW13
DEC AX ; If Bad, Say So
CMP BX,AX
JNE GET_OW12
MOV DX,OFFSET BADMSG
JMP SHORT GET_OW17
GET_OW12: SUB AX,7 ; If Reserved, Say So
CMP BX,AX
JB GET_OW13
MOV DX,OFFSET RESVMSG
JMP SHORT GET_OW17
GET_OW13: MOV AX,CLUST ; Get Cluster Number
GET_OW14: MOV BX,AX ; Get Previous Cluster in Chain
CALL PREVCLST
OR AX,AX ; If Not First, Repeat
JNZ GET_OW14
MOV CLUST,BX ; Save First Cluster in Chain
GET_OW15: CALL GETDIR ; Load the Current Directory
CALL SRCHCLST ; Search Directory for Cluster
JNC GET_OW16 ; If Found, Exit Search Loop
CALL SRCHDIR ; Search Dir for Sub-Directory
JNC GET_OW15 ; If Found, Continue Search Loop
CALL DIRNEXT ; Use Next Sub-Directory
JNC GET_OW15 ; If Found, Continue Search Loop
MOV DX,OFFSET LOSTMSG ; Else Couldn't find Cluster
JMP SHORT GET_OW17
GET_OW16: MOV AL,DRIVE ; Convert Drive Number to Letter
ADD AL,'A'
MOV FILESPEC,AL
MOV AH,9 ; Output Owner Message
MOV DX,OFFSET OWNERMSG
INT 21H
MOV DX,OFFSET FILESPEC ; Output FileSpec
INT 21H
MOV DX,OFFSET FILENAME ; Output FileName
INT 21H
MOV DX,OFFSET CRLF
GET_OW17: MOV AH,9
INT 21H
POP SI ; Restore Registers
POP DI
POP DX
POP CX
POP BX
POP AX
RET ; Done
GETDIR: PUSH AX ; Save Registers
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
MOV AL,DRIVE ; Read Root Directory
MOV CX,DIRSEC
MOV DX,STARTSEC
SUB DX,CX
MOV BX,DIRBUF
INT 25H
POPF
MOV AX,RDIR_LEN ; DIR Length = Root DIR Length
MOV DIR_LEN,AX
MOV SI,OFFSET PATH ; Point to First Element of Path
GETDIR1: MOV DI,OFFSET DIRNAME ; Point to FileName Buffer
GETDIR2: LODSB ; Copy Path Element to FileName
CMP AL,'\' ; until '\' or '$'
JE GETDIR3
CMP AL,'$'
JE GETDIR4
STOSB
JMP SHORT GETDIR2
GETDIR3: MOV AL,0 ; Read Subdirectory
STOSB
CALL READDIR
JC GETDIR5 ; If Error, Say So
JMP SHORT GETDIR1 ; Get Next Element
GETDIR4: CLC ; Clear Error Flag
GETDIR5: POP SI ; Restore Registers
POP DI
POP DX
POP CX
POP BX
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
DIRNEXT: PUSH AX ; Save Registers
PUSH BX
PUSH CX
PUSH DI
PUSH SI
DIRNEXT1: MOV DI,OFFSET PATH ; Scan to End of Path
MOV CX,80
MOV AL,'$'
REPNE SCASB
JNE DIRNEXT3 ; If No End, Error
CMP CX,79 ; If Null Path, Error
JE DIRNEXT3
STD ; Auto-Decrement
MOV AX,78 ; Determine Path Length
SUB AX,CX
MOV CX,AX
SUB DI,2 ; Point to End of DirName
MOV AL,0 ; Set End of DirName
STOSB
MOV AL,'\' ; Scan to Previous DirName
REPNE SCASB
JE DIRNEXT2 ; If Not Found,
MOV DI,OFFSET PATH[-2] ; Point to Start of Path
DIRNEXT2: CLD ; Auto-Increment
ADD DI,2 ; Copy Last SubDir to FileName
PUSH DI
MOV SI,DI
MOV DI,OFFSET FILENAME
CALL MOVSTR
POP DI
MOV AL,'$' ; Terminate Path String
STOSB
CALL GETDIR ; Read Directory
JC DIRNEXT4 ; If Error, Say So
MOV SI,OFFSET FILENAME
MOV DI,OFFSET DIRNAME
CALL MOVSTR
CALL SRCHFILE ; Search for FileName
JC DIRNEXT4 ; If Error, Say So
MOV SI,BX ; Save Pointer
ADD SI,32 ; Point to Next Dir Entry
MOV AX,SI ; Determine Dir Entry Count
SUB AX,DIRBUF
MOV CL,5
SHR AX,CL
MOV CX,DIR_LEN
SUB CX,AX
CALL FINDDIR ; Find Next SubDirectory
JC DIRNEXT1
JMP SHORT DIRNEXT4
DIRNEXT3: STC ; Set Error Return Flag
DIRNEXT4: POP SI ; Restore Registers
POP DI
POP CX
POP BX
POP AX
RET ; Done
SRCHDIR: PUSH CX ; Save Registers
PUSH SI
MOV SI,DIRBUF ; Point to First DIR Entry
MOV CX,DIR_LEN ; Load DIR Length
CALL FINDDIR ; Find SubDirectory
POP SI ; Restore Registers
POP CX
RET ; Done
FINDDIR: PUSH AX ; Save Registers
PUSH DI
FINDDIR1: JCXZ FINDDIR4 ; If Zero, Not Found
FINDDIR2: CMP BYTE PTR [SI],0 ; If Null, End of Search
JE FINDDIR4
CMP BYTE PTR [SI],'.' ; If '.' or '..', Skip
JE FINDDIR3
CMP BYTE PTR [SI],0E5H ; If Deleted, Skip
JE FINDDIR3
TEST BYTE PTR [SI+11],10H ; Test File Attribute
JNZ FINDDIR5 ; If Match, Found
FINDDIR3: ADD SI,32 ; Else Next DIR Entry
LOOP FINDDIR2 ; and Repeat
FINDDIR4: STC ; Set Error Flag
JMP SHORT FINDDIR6 ; Done
FINDDIR5: MOV DI,OFFSET DIRNAME
CALL UNPARSE ; UnParse Directory Name
MOV DI,OFFSET PATH ; Search for End of Path
MOV AL,'$'
MOV CX,80
REPNE SCASB
JNE FINDDIR4 ; If Not Found, Error
DEC DI
MOV BX,SI ; Set Pointer to DIR Entry
MOV SI,OFFSET DIRNAME ; Copy Directory Name to Path
CALL MOVSTR
DEC DI
MOV AX,'$\' ; Terminate Path
STOSW
CLC ; Clear Error Flag
FINDDIR6: POP DI ; Restore Registers
POP AX
RET ; Done
SRCHFILE: PUSH AX ; Save Register
PUSH CX
PUSH DI
PUSH SI
MOV AX,2900H ; Parse Filename
MOV SI,OFFSET DIRNAME
MOV DI,OFFSET FCB
INT 21H
INC DI ; Point to Filename in FCB
MOV SI,DIRBUF ; Point to Start of DIRBUF
MOV CX,DIR_LEN ; Load DIR Length
JCXZ SRCHFIL2 ; If Zero, Not Found
SRCHFIL1: PUSH CX ; Save Registers
PUSH DI
PUSH SI
MOV CX,11 ; Compare Filename
REPE CMPSB
POP SI ; Restore Registers
POP DI
POP CX
JE SRCHFIL3 ; If Match, Found
ADD SI,32 ; Else Next DIR Entry
LOOP SRCHFIL1 ; and Repeat
SRCHFIL2: STC ; Set Error Flag
JMP SHORT SRCHFIL4 ; Done
SRCHFIL3: MOV BX,SI ; Set Pointer to DIR Entry
CLC ; Clear Error Flag
SRCHFIL4: POP SI ; Restore Registers
POP DI
POP CX
POP AX
RET ; Done
SRCHCLST: PUSH AX ; Save Register
PUSH CX
PUSH DI
PUSH SI
MOV SI,DIRBUF ; Point to First DIR Entry
MOV CX,DIR_LEN ; Load DIR Length
JCXZ SRCHCLS3 ; If Zero, Not Found
MOV BX,CLUST
SRCHCLS1: CMP BYTE PTR [SI],0 ; If Null, End of Search
JE SRCHCLS3
CMP BYTE PTR [SI],'.' ; If '.' or '..', Skip
JE SRCHCLS2
CMP BYTE PTR [SI],0E5H ; If Deleted, Skip
JE SRCHCLS2
CMP BX,[SI+26] ; Compare Start Cluster Number
JE SRCHCLS4 ; If Match, Found
SRCHCLS2: ADD SI,32 ; Else Next DIR Entry
LOOP SRCHCLS1 ; and Repeat
SRCHCLS3: STC ; Set Error Flag
JMP SHORT SRCHCLS5 ; Done
SRCHCLS4: MOV DI,OFFSET FILENAME ; UnParse File Name
CALL UNPARSE
CLC ; Clear Error Flag
SRCHCLS5: POP SI ; Restore Registers
POP DI
POP CX
POP AX
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
PREVCLST: PUSH BX ; Save Registers
PUSH CX
PUSH DX
MOV DX,BX ; Reserve Cluster Number
MOV CX,CLSTTOT ; Start Looking at Last Cluster
PREVCLS1: MOV BX,CX ; Check Cluster
INC BX
CALL NEXTCLST
CMP BX,DX ; If Match, Use It
LOOPNE PREVCLS1 ; Else Repeat
JNE PREVCLS2 ; If No Match, Return Zero
ADD CX,2 ; Adjust for Cluster Number
PREVCLS2: MOV AX,CX ; AX = Cluster Number
POP DX ; Restore Registers
POP CX
POP BX
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
UNPARSE: PUSH CX ; Save Registers
PUSH DI
PUSH SI
MOV CX,8 ; FileName Length = 8 Max
UNPARSE1: LODSB ; Read Character
CMP AL,' ' ; If Space, Exit Loop
JE UNPARSE2
STOSB ; Move Character
LOOP UNPARSE1 ; Repeat
UNPARSE2: MOV AL,'.' ; Put a Dot in the String
STOSB
POP SI ; Point to Extension
PUSH SI
ADD SI,8
MOV CX,3 ; Extension Length = 3 Max
UNPARSE3: LODSB ; Read Character
CMP AL,' ' ; If Space, Exit Loop
JE UNPARSE4
STOSB ; Move Character
LOOP UNPARSE3 ; Repeat
UNPARSE4: CMP CX,3 ; If No Extension, Remove Dot
JNE UNPARSE5
DEC DI
UNPARSE5: MOV AL,0 ; Terminate FileName
STOSB
MOV AL,'$'
STOSB
POP SI ; Restore Registers
POP DI
POP CX
RET ; Done
MOVSTR: LODSB ; Read Source
STOSB ; Write Destination
OR AL,AL ; If Not EOS, Repeat
JNZ MOVSTR
RET ; Done
GET_WORD: PUSH BX ; Save Registers
PUSH DI
PUSH SI ; Save Pointer
XOR DX,DX ; Value = 0
GET_WRD1: LODSB ; Read Character
CMP AL,'0' ; If Not Numeric, Done
JB GET_WRD2
CMP AL,'9'
JA GET_WRD2
SUB AL,'0' ; Convert to BCD
CBW
MOV BX,AX ; Value = Value*10+BCD
MOV AX,10
MUL DX
ADD AX,BX
MOV DX,AX
JMP GET_WRD1 ; Repeat
GET_WRD2: DEC SI
POP DI ; Restore Pointer
CMP DI,SI ; Compare Pointer
POP DI ; Restore Registers
POP BX
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
FATBUF LABEL WORD
CODE ENDS
END OWNER