• 全盘搜索程序


    不知你编过全盘搜索程序没有,本程序用在消毒程序以及其他需要主动搜索磁盘上所有文件的地方,由于以前我自己的注释都是英文的,所以这次简单加上了一些中文。
       本程序要用到的 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
    

  • 相关阅读:
    vim的三种模式
    vi/vim 三种模式的操作
    vim(vi)下的三种模式及其相关命令
    linux下查看最消耗CPU、内存的进程
    hdu 5288 OO’s Sequence
    宿主机mac os无法连接到虚拟机centos
    cloudstack给已有zone加入物理网络
    oracle刚開始学习的人经常使用操作100问
    七天学会ASP.NET MVC (四)——用户授权认证问题
    JEECG常见问题大全征集
  • 原文地址:https://www.cnblogs.com/ahuo/p/414567.html
Copyright © 2020-2023  润新知