home *** CD-ROM | disk | FTP | other *** search
- comment |
- This program will search for all files matching a given template
- (file name or file name with wild cards) on the default drive.
- Calling sequence:
- SEARCH filename
-
- Written for MASM 5.0
-
- Save as SEARCH.ASM
- Compile: MASM SEARCH;
- LINK SEARCH; (ignore stack segment warning)
- EXE2BIN SEARCH SEARCH.COM
- |
-
- rpush macro x ;;Push multiple registers
- irp y,<x>
- push y
- endm
- endm
-
- rpop macro x ;;Pop multiple registers
- irp y,<x>
- pop y
- endm
- endm
-
- DOScall macro x ;;Call MS-DOS
- mov ah,x
- int 21h
- endm
-
- DTA struc ;Disk Transfer area structure
- db 15h dup (?) ;21 reserved bytes
- atr db ? ;1-byte attribute
- time dw ? ;2-byte file time
- date dw ? ;2-byte file date
- fsize dd ? ;4-byte file size
- fname db 0dh dup (?) ;13-byte file name
- DTA ends
-
- DTAsize equ 2ch ;Size of one DTA
-
- DIR struc ;Directory name structure
- drive db ? ;Drive letter
- db ":\" ;Separator
- direc db 40h dup (?) ;Room for full subdir path
- db 0 ;Terminator
- DIR ends
-
-
- PROG segment
- assume cs:PROG, ds:PROG, es:PROG, ss:PROG
-
-
- org 100h
- start: jmp begin
-
- ;**********
- ; Program data
- ;**********
-
- curdr DIR <> ;Current drive
- startdr DIR <> ;Starting directory
-
- dirattr equ 10h ;Subdirectory attribute
- filattr equ 00h ;Find "normal" files only
-
- filname db 12 dup (?),0
- dirname db "*.*",0
- parent db "..",0
-
- cr equ 13
- lf equ 10
- tab equ 9
- crlf db cr,lf,'$'
-
- noroom db cr,lf,"Subdirectories nested too deeply."
- db cr,lf,"This program is out of room.$"
-
-
- begin: cld ;Be sure direction flag is reset
- call get_start ;Get starting subdirectory
- call get_filenam ;Get user's request
- mov ah,startdr.drive ;Get current drive
- mov curdr.drive,ah ;Save it
- mov curdr.direc,0 ;And move to top of drive
- lea dx,curdr.drive ;DS:DX ==> directory name
- DOScall 3bh ;CHDIR to root directory
- call searchdir ;Search the root directory
- lea dx,startdr.drive ;DS:DX ==> original path
- DOScall 3bh ;CHDIR to original directory
- mov al,0 ;Report success to DOS
- DOScall 4ch ;Exit program
-
- get_start proc
- rpush <si,dx>
- DOScall 19h ;Get current drive
- add al,'A' ;Make it ASCII
- mov startdr.drive,al ;Save it
- lea si,startdr.direc ;DS:SI ==> buffer
- mov dl,0 ;Select default drive
- DOScall 47h ;Get current directory
- rpop <dx,si>
- ret
- get_start endp
-
- get_filenam proc
- rpush <di,si,cx>
- lea di,filname ;ES:DI ==> storage area
- mov si,5dh ;DS:SI ==> Formatted parm #1
- cmp byte ptr [si],' ' ;Anything there?
- jnz gp0 ;Yes -- go
- mov al,0ffh ;Else report an error to caller
- DOScall 4ch ;Exit program
-
- gp0: mov cx,8 ;Filename length
- gp1: lodsb ;Get a byte
- cmp al,' ' ;Is it a space?
- je gp2 ;Yes -- go
- stosb ;Else move it
- gp2: loop gp1 ;Repeat for full name
- mov ax,'.' ;Now save separator
- stosb
- mov cx,3 ;Length of extension
- gp3: lodsb ;Get a byte
- cmp al,' ' ;Is it a space?
- je gp4 ;Yes -- go
- stosb ;Else save it
- loop gp3 ;Finish file extension
- gp4: mov al,0 ;Terminate string
- stosb
- rpop <cx,si,di>
- ret
- get_filenam endp
-
- our_dta equ sp ;Shorthand DTA address
-
- searchdir proc ;Search the current directory
- push bp ;Save previous stack frame
- mov bp,sp ;Set our stack frame
- mov ax,sp ;Get SP for testing
- sub ax,endloc ;Room for another DTA?
- jnc srd1 ;Yes -- start routine
- lea dx,noroom ;Else point to message
- DOScall 9 ;Display a string
- mov al,0ffh ;Report an error
- DOScall 4ch ;Exit program
-
- srd1: sub sp,DTAsize ;Make room for DTA
- ;**********
- ; Find matching filenames
- ;**********
- mov bx,our_dta ;Get address for ourselves
- push our_dta ;Save address to pass to subs
- mov dx,bx ;DTA address to dx
- DOScall 1ah ;Set DTA
- lea dx,filname ;DS:DX ==> filename
- mov cx,filattr ;Attribute to search for
- DOScall 4eh ;Find first file
- jc srd3 ;Nothing found -- go
- call print_dir ;Else print the subdir name
- srd2: call print_fname ;Then print the file name
- DOScall 4fh ;Find next file
- jnc srd2 ;Loop back if found
- ;**********
- ; Find subdirectories
- ;**********
- srd3: lea dx,dirname ;DS:DX ==> "*.*"
- mov cx,dirattr ;Include subdirs in search
- DOScall 4eh ;Find first file
- srd4: jc srd6 ;Go if nothing found
- mov al,[bx + DTA.atr] ;Test file's attribute
- cmp al,dirattr ;Is it a directory?
- jne srd5 ;No -- go
- mov al,[bx + DTA.fname] ;Look at file name
- cmp al,'.' ;Does it start with '.'?
- je srd5 ;Yes -- go
- push bx ;Save our DTA address
- call login ;Log in to subdir
- call searchdir ;And search it
- call logout ;Then log out of subdir
- pop bx ;Recover DTA address
- mov dx,bx ;Get original DTA address
- DOScall 1ah ;Set our DTA again
- srd5: DOScall 4fh ;Find next subdirectory
- jmp srd4 ;Loop back
-
- srd6: mov sp,bp ;Reset the stack
- pop bp ;Recover former stack frame
- ret
- searchdir endp
-
- print_dir proc
- rpush <si,dx>
- lea si,curdr.direc ;DS:SI ==> buffer area
- mov dl,0 ;Select current drive
- DOScall 47h ;Get default directory
- lea si,curdr.drive ;DS:SI ==> full path name
- call print_az ;Print ASCIIZ string
- rpop <dx,si>
- ret
- print_dir endp
-
- this_DTA equ [bp+4] ;Stack location for DTA addr.
-
- print_fname proc
- push bp ;Save frame pointer
- mov bp,sp ;Save the stack pointer
- rpush <si,dx>
- mov si,this_DTA ;DS:SI ==> DTA in use
- add si,DTA.fname ;DS:SI ==> current filename
- mov dl,tab ;First print a tab
- DOScall 2 ;Print a character
- call print_az ;Print ASCIIZ string
- rpop <dx,si,bp> ;Clear the stack
- ret
- print_fname endp
-
- print_az proc ;Print ASCIIZ string at SI
- rpush <bx,cx,dx,si> ;Save SI last
- sub cx,cx ;Start with count of 0
- pa1: lodsb ;Get a byte
- cmp al,0 ;At the end?
- jz pa2 ;Yes -- go
- inc cx ;Else count it
- jmp pa1 ;And repeat
- pa2: pop dx ;Recover original addr.
- mov bx,1 ;STDOUT handle
- DOScall 40h ;Write to file/handle
- lea dx,crlf ;Terminate line
- DOScall 9 ;Print a string
- rpop <dx,cx,bx> ;Clear the stack
- ret
- print_az endp
-
- login proc
- push bp ;Save the stack frame
- mov bp,sp ;And the stack pointer
- push dx ;Save caller's DX
- mov dx,this_DTA ;Point to current DTA
- add dx,DTA.fname ;DS:DX ==> directory name
- DOScall 3bh ;CHDIR to new directory
- rpop <dx,bp> ;Clear the stack
- ret
- login endp
-
- logout proc
- push dx ;Save caller's DX
- lea dx,parent ;DS:DX ==> '..'
- DOScall 3bh ;CHDIR to parent directory
- pop dx ;Clear the stack
- ret
- logout endp
- endloc dw $ + 100h + DTAsize ;Leave room for normal stack
- ; and one DTA
- prog ends
- end start
-