ITEEDU

第1章 Iczelion的Win32汇编教程

第2章 Iczelion的ODBC教程

第3章 Iczelion的VxD教程

第4章 Iczelion的PE教程

第5章 罗云彬的Win32汇编教程

第6章 Win32ASM经验点滴

第7章 X86汇编语言编程

第8章 加密解密

第9章 病毒的分析和防治

全盘搜索程序

概述:

不知你编过全盘搜索程序没有,本程序用在消毒程序以及其他需要主动搜索磁盘上所有文件的地方,由于以前我自己的注释都是英文的,所以这次简单加上了一些中文。
本程序要用到的 DOS 中断很少,仅为 4EH 和 4FH,功能是查找第一个匹配文件名和继续查找,编程难点是要用到类似于堆栈的数据结构,把找到的子目录名暂时存起来,等当前目录找完后在取出来,然后继续查找下一个目录,我用的方法是开一个缓冲区,定义一个指针,用来指向缓冲区结束的地方。用的是先进先出方式,为了节省空间,每个目录项长度不等长,由每项的前 2 个字节来指向前面一条目录项。具体见源程序。
本程序要用到的 INT 21H 的 4EH 和 4FH 功能如下:

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