功能号 | 入口参数 | 出口参数 |
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