| 功能号 | 入口参数 | 出口参数 |
| AH = 4EH 查找第一个匹配文件项 |
CX = 文件属性 | 标志 CF 复位 = 成功 找到文件名在 DTA 内 缺省 DTA 在PSP:0080H 处 |
| DS:DX = 要查找的文件名 ASC 字符串 | 标志 CF 置位 = 出错 | |
| AH = 4FH 查找下一个匹配文件项 |
标志 CF 复位 = 成功 找到文件名在 DTA 内 缺省 DTA 在 PSP:0080H 处 |
|
| 标志 CF 置位 = 出错 |
DTA 的内容如下:
| 偏移量 | 长度 | 含义 |
| 15H | 字节 | 找到文件的属性 |
| 16H | 字 | 文件时间 位11-15:小时 位5-10:分 位0-4:秒/2 |
| 18H | 字 | 文件日期 位9-15:年-1980 位8-5:月 位0-4:日 |
| 1AH | 双字 | 文件大小 |
| 1EH | 13字节 | ASC II 文件名+扩展名 |
源程序:
;Copyright by LuoYunBin
;http://asm.yeah.net
.286P
CODE SEGMENT
ASSUME CS:CODE,DS:CODE
ORG 100H
START:
JMP INSTALL
INSTALL:
CALL GET_COM_LINE ;处理命令行
CALL SCAN_DISK ;全盘查找子程序
MOV AH,4CH
INT 21H
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; search the hole diskette files
; programmed by LYB
; include following procedures
; scan_disk: scan disk and get all filename
; -----------------------------------------
; enter ds:si = scan drive or path name
; return FIND_FILE = found file name
; SD_ATTR = file attribute
; use DO_FILE process to file operation
; the data in sd_buffer is like this
; addr1: word -1, + path string
; addr2: word addr1, + path string
; addr3: word addr2, + path string
; ...
; PATH_SP point to last address
SCAN_DISK PROC NEAR
JMP SCAN_START
; data for do_file process
SD_ATTR DW ? ;要找的文件属性
FIND_FILE DB 128 DUP (0) ;找到的文件名
; data use scan_disk itself
PATH_EP DW ? ;目录名缓冲区指针
PATH_SP DW PATH_BUFFER ;path buffer stack point
FINDING_FILE DB 8 DUP (0)
FINDING_EXT DB 3 DUP (0)
TEMP_FILE DB 8 DUP (0)
TEMP_EXT DB 3 DUP (0)
SCAN_START:
PUSH CS
POP DS
PUSH CS
POP ES ;set ds,es = cs
MOV SI,80H
CALL PHASE_NAME ;phase file name
MOV SI,PATH_SP
SD_LOP:
INC SI
INC SI
MOV DI,OFFSET FIND_FILE
CLD
CALL MOVE_BYTE
DEC DI
CMP BYTE PTR DS:[DI-1],'\' ;path as N:\
JZ SD1
MOV AL,'\'
STOSB
SD1:
MOV PATH_EP,DI ;path end point
MOV AX,'.*'
STOSW ;add *.*
MOV AL,'*'
STOSB
XOR AL,AL
STOSB
MOV AH,4EH
MOV DX,OFFSET FIND_FILE ;找第一个文件
MOV CX,37H ;找所有文件属性包括子目录
INT 21H
JB SD_LOP2_END
SD_LOP2:
CALL PROS_DIR ;处理目录项
MOV AH,4FH ;找下一个文件
INT 21H
JNB SD_LOP2
SD_LOP2_END:
MOV SI,PATH_SP ;检查目录缓冲区
CMP SI,OFFSET PATH_BUFFER ;如果还有目录要找,则继续
JNZ SD_NEW_DIR
RET
SD_NEW_DIR:
MOV DI,[SI] ;从缓冲区中取出新目录
MOV PATH_SP,DI
JMP SD_LOP
PROS_DIR PROC
MOV SI,80H ;80H 为 DTA 地址
XOR AH,AH
MOV AL,DS:[SI+0015H]
MOV SD_ATTR,AX ;找到的文件属性
ADD SI,1EH
PUSH SI
MOV DI,PATH_EP ;把文件名加到路径上
CALL MOVE_BYTE
POP SI
TEST SD_ATTR,10H ;是否为子目录
JNZ PD_IS_DIR
CALL CHECK_FIND
JNZ PD_RET
CALL DO_FILE ;对找到的文件进行处理
;本程序的处理程序仅为打印文件名,实际应用中,如果是用于消毒程序,可以
;在 DO_FILE 子程序中对文件进行检查
PD_RET:
RET
PD_IS_DIR:
CMP BYTE PTR DS:[SI],'.' ;是 . 或 .. 则忽略
JZ PD_RET
MOV DI,PATH_SP ;如果找到新目录
PUSH DI ;则把它加入目录名缓冲区
INC DI
INC DI
MOV CX,-1
XOR AL,AL
REPNZ SCASB ;find string end
POP [DI] ;fill new address
MOV PATH_SP,DI ;point to previous address
INC DI
INC DI ;add path string
MOV SI,OFFSET FIND_FILE
CALL MOVE_BYTE
RET
PROS_DIR ENDP
MOVE_BYTE PROC
LODSB
OR AL,AL
JZ MB_RET
STOSB
JMP SHORT MOVE_BYTE
MB_RET:
STOSB
RET
MOVE_BYTE ENDP
;=================================================
; check file name in DTA if match
; the searching file name
;本子程序的作用是,如果命令行指定查找特定文件
;则比较是否找到,如命令行输入找 *.EXE 那么
;就是在这儿比较
;=================================================
CHECK_FIND PROC
MOV DI,OFFSET TEMP_FILE
MOV CX,11
XOR AL,AL
CLD
REP STOSB
MOV SI,80H+1EH
MOV DI,OFFSET TEMP_FILE
CF_LOP1:
LODSB
OR AL,AL
JZ CF_LOP2_END
CMP AL,'.'
JZ CF_LOP1_END
STOSB
JMP SHORT CF_LOP1
CF_LOP1_END:
MOV DI,OFFSET TEMP_EXT
CF_LOP2:
LODSB
OR AL,AL
JZ CF_LOP2_END
STOSB
JMP SHORT CF_LOP2
CF_LOP2_END:
MOV SI,OFFSET TEMP_FILE
MOV DI,OFFSET FINDING_FILE
MOV CX,11
CF_LOP3:
LODSB
MOV AH,[DI]
INC DI
CMP AH,'?'
JZ CF_MATCH ;char match
CMP AH,AL
JZ CF_MATCH ;char match
CF_END:
RET
CF_MATCH:
LOOP CF_LOP3
RET
CHECK_FIND ENDP
; get .ext and name and path name from com_line
; input data in DS:SI
; output scan file name in ES:DI
; 对要找的文件字符串进行预处理,分离路径和文件名
PHASE_NAME PROC
MOV DI,OFFSET FIND_FILE
MOV BP,DI
XOR AX,AX
MOV CX,128
CLD
REP STOSB
MOV DI,BP
DEC BP ;bp point to find_file-1
PN_LOP:
LODSB
STOSB
OR AL,AL
JZ PN_LOP_END
CMP AL,'?'
JZ PN_WILD
CMP AL,'*'
JZ PN_WILD
CMP AL,'\' ;path end point
JZ PN_PARA
CMP AL,':'
JNZ PN_LOP
CMP BYTE PTR [SI],'\'
JZ PN_LOP
MOV AL,'\'
STOSB
PN_PARA:
MOV BP,DI ;save path end
DEC BP
JMP SHORT PN_LOP
PN_WILD:
MOV AH,1 ;set wild char flag
JMP SHORT PN_LOP
PN_LOP_END:
OR AH,AH ;=1, then has wild char
JNZ PN_SPAR
MOV AH,4EH
MOV CX,37H
MOV DX,OFFSET FIND_FILE ;check if is dir
INT 21H
JB PN_SPAR ;sparater path and file name
TEST BYTE PTR DS:[80H+15H],10H
JZ PN_SPAR ;if not dir
MOV BP,DI ;is dir
DEC BP
MOV AX,'.*'
STOSW
MOV AL,'*'
STOSB
XOR AL,AL
STOSB
PN_SPAR:
CMP BP,OFFSET FIND_FILE-1
JZ PN_SPAR1
MOV BYTE PTR DS:[BP],0
MOV SI,OFFSET FIND_FILE
MOV DI,OFFSET PATH_BUFFER+2
CALL MOVE_BYTE
PN_SPAR1:
INC BP
MOV SI,BP
MOV DI,OFFSET FINDING_FILE
MOV CX,8
PN_LOP1:
LODSB ;get filename
CMP AL,'.'
JZ PN_LOP2_1
OR AL,AL
JZ PN_LOP3_END
CMP AL,'*'
JZ PN_LOP1_STORE
STOSB
LOOP PN_LOP1
JMP SHORT PN_LOP2
PN_LOP1_STORE:
MOV AL,'?'
REP STOSB
PN_LOP2:
LODSB
PN_LOP2_1:
OR AL,AL
JZ PN_LOP3_END
CMP AL,'.'
JNZ PN_LOP2
MOV DI,OFFSET FINDING_EXT
MOV CX,3
PN_LOP3:
LODSB ;get ext name
OR AL,AL
JZ PN_LOP3_END
CMP AL,'*'
JZ PN_LOP3_STORE
STOSB
LOOP PN_LOP3
JMP SHORT PN_LOP3_END
PN_LOP3_STORE:
MOV AL,'?'
REP STOSB
PN_LOP3_END:
MOV AL,'?'
CMP FINDING_FILE,0
JNZ PN1
MOV DI,OFFSET FINDING_FILE
MOV CX,8
REP STOSB
PN1:
CMP FINDING_EXT,0
JNZ PN2
MOV DI,OFFSET FINDING_EXT
MOV CX,3
REP STOSB
PN2:
RET
PHASE_NAME ENDP
SCAN_DISK ENDP
DO_FILE PROC
MOV SI,OFFSET D_SEARCHING
CALL PRINTF
RET
DO_FILE ENDP
D_SEARCHING DB 'Searching file: %c%79t',0DH,0
DW FIND_FILE
GET_COM_LINE PROC
; get command line file name
; to CL_FILE and return CY when no command line
; return NC when has command line
; the sub change lower letter to upper letter
; 命令行处理子程序
MOV SI,81H
MOV DI,80H
CLD
CMD_LOP:
LODSB
CMP AL,0DH
JZ CMD_LOP_END
CMP AL,' '
JBE CMD_LOP ;如果是小写字母
CMP AL,'a' ;则转换到大写
JB STOS_IT ;因为大小写字母 ASC 码值刚好差 20H
CMP AL,'z' ;所以把 ASC 码减 20H 就换到大写了
JA STOS_IT
SUB AL,20H ;convert to upper case
STOS_IT:
STOSB
JMP SHORT CMD_LOP
CMD_LOP_END:
XOR AL,AL
STOSB
RET
GET_COM_LINE ENDP
INCLUDE PRINTF.ASM ;一个公用的显示程序
FILE_END EQU THIS BYTE
PATH_BUFFER DB 1000H DUP (0) ;path buffer
CODE ENDS
END START