home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcresour
/
1988_08
/
search.asm
< prev
next >
Wrap
Assembly Source File
|
1988-04-18
|
7KB
|
259 lines
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