It's not going to the F: drive.

; This code MAY contain Random PE Compression, Anti Siege Engine,
; and IBI(c) Technology 
;
;  If you besiege a city for a long time while attempting to capture it,
;  you must not chop down its trees, for you may eat fruit from them and should not
;  cut them down.  Deuteronomy 20:19   
;
;              Works thru WinXP SP2
;
;              MUST USE tasm31.exe and tlink51.exe to compile !!
;
;              WON'T FIND FILES WITH MORE THAN A 3 CHAR EXTENSION !!
;
;              Lengthened path to 128 characters
;              Change to drive to search floppies
;
lf      equ    0ah                    ; ASCII line feed
cr      equ    0dh                    ; ASCII carriage return
ff      equ    0ch                    ; ASCII form feed
tab    equ    09h
eom    equ    '$'                    ; end of message flag

                                        ; Program Segment Prefix
default_fcb equ 05ch
command equ 80h
default_dta equ 080h

; This is the format for the DOS Data Transfer Area 
; searches for a file match in directories.

DTA STRUC
RESERVED db 21 dup (?)
ATTRIBUTE db 0
TIME dw 0
DATE dw 0
DTA_SIZE dd 0
NAME_FOUND db 13 dup (?)
DTA ENDS

cseg segment para public 'CODE'

        assume  cs:cseg,ds:data,es:data,ss:stak

; This is the main program that sets up the initial conditions for
; SDIR which, in turn, does a recursive search.
;
; Reads: PATH_NAME
; Writes: FILE_NAME
; Calls: SDIR

whereis proc far
 
        push    ds              ; save final return
        xor    ax,ax
        push    ax
        mov    bp,sp            ; save pointer to final return
            ; in case we want to exit
        ; inside recursive routine

        mov    ax,data          ; make data segment addressable
        mov    es,ax            ; via ES
        call    clr_screen
        call    infile          ; get name of search target

        mov    ax,data          ; make data segment addressable
        mov    ds,ax            ; via DS
        jnc    short whereis2  ; jump if filename was ok

                                ; filename was missing,
        mov  dx,offset msg1    ; print error message and exit
        mov  ah,9
        int  21h
        ret

whereis2:
        mov    di,offset PATH_NAME
        xor    al,al              ; Search for the zero at the end
        cld                        ; of PATH_NAME
        mov    cx,128              ; Max path length
        repnz  scasb
        mov    bx,di
        dec    bx                  ; DS:BX points to end of PATH_NAME
        mov    dx,0                ; Tell SDIR this is first
        call    SDIR                ; Now do the recursive search
        mov    ax,match_count      ; were any matches found?
        or      ax,ax
        jz      whereis8            ; no,jump
        ret                        ; yes,just exit

whereis8:
        mov  dx,offset msg2      ; no, print "no match"
        mov  ah,9
        int  21h
        ret
                                    ; this is a special crash
                                    ; exit, which may be taken
                                    ; from inside recursed proc.
whereis9:
        mov  sp,bp
        ret

whereis endp

clr_screen      proc    near    ; clear screen using direct video writes
                                ; faster than DOS functions
        push        ax
        push        es
        mov        ax,0b800h  ; Start at memory 0b800
        mov        es,ax
        xor        di,di
        mov        cx,2000     
        mov        ax,0720h    ; Black bg, white fg, 20h = space char
        rep        stosw
        pop        ax
        pop        es
        ret

clr_screen      endp

;  This procedure searches all the files in the current directory
;  looking for a match.  It also prints the full name for each match.
;
;  DS:BX          Pointer to end of current path name     
;  DS:DX          Old disk transfer area (DTA)           
;
; Reads: Disk Transfer Area (DTA)
; Writes: Disk Transfer Area (DTA)
; Calls: BUILD_NAME, FMATCH, PNAME
; NMATCH, BUILD_STAR_NAME, SSUB

SDIR PROC NEAR

PUSH SI ; Need to restore on exit
PUSH DX
CALL BUILD_NAME ; Build the absolute search name
CALL FMATCH ; See if there is a match here
JC sdir2 ; No match, check subdirectories

CALL PNAME ; Write name of match.
sdir1:
CALL NMATCH ; Find the next match
JC sdir2 ; No match, search sub-directories

CALL PNAME ; Match, write absolute name
JMP sdir1 ; Look for the next matching name

sdir2: ; No match, so try sub-directories.
POP DX ; Restore DTA
PUSH DX
CALL BUILD_STAR_NAME ; Search for all directories
CALL FMATCH ; Get first entry
JC SDIR5 ; There are no entries
MOV SI,DX ; Put address of DTA into SI
TEST .ATTRIBUTE,10H ; Is it a directory entry?
JNZ SDIR4 ; Yes, then search sub-directory
SDIR3:
CALL NMATCH ; No, then find the next match
JC SDIR5 ; There are no more entries
TEST .ATTRIBUTE,10H ; Is this a directory?
JZ SDIR3 ; No, then try again
SDIR4:
CMP .NAME_FOUND,'.' ; Is this a . or .. directory?
JE SDIR3 ; Yes, skip to next directory
CALL SSUB ; Search the sub-directory
PUSH AX ; Now reset the DTA
MOV AH,1AH
INT 21H
POP AX
JMP SDIR3
SDIR5:
POP DX
POP SI
RET

SDIR ENDP

; This procedure searches the subdirectory whose name is in the DTA
;
;      DS:BX                  End of the current path name           
; DS:.NAME_FOUND Name of subdirectory for search
; Reads: PATH_NAME
; Writes: PATH_NAME
; Calls: SDIR

SSUB PROC NEAR

PUSH DI
PUSH SI
PUSH AX
PUSH BX
CLD ; Set for increment
MOV SI,DX ; Put address of DTA into SI
ADD SI,OFFSET NAME_FOUND ; Set to start of sub-directory name
MOV DI,BX ; DS:DI -- 0 at end of path name

ssub1: ; Copy sub-directory to path name
LODSB ; Copy one character
STOSB
OR AL,AL ; Was it a 0?
JNZ ssub1 ; No, keep copying
MOV BX,DI ; Set BX to end of new path name
STD ; Set flag for decrement
STOSB ; Store a 0 at end of string
MOV AL,'\'
STOSB ; Place '\' at end of path name
CALL SDIR ; Search this new path
POP BX ; Restore the old end-of-path
MOV BYTE PTR ,0 ; And store a zero here
POP AX
POP SI
POP DI
RET

SSUB ENDP

; This procedure prints the matched name after the path name
;
; DS:DX    Pointer to current disk transfer area   
;
; Reads: PATH_NAME, NAME_FOUND (in DTA)
; Calls: pasciiz, CRLF

PNAME PROC NEAR

PUSH AX
PUSH DX
  MOV    DX,OFFSET PATH_NAME
  MOV    AL,                ; Save character at end of path
  MOV    BYTE PTR ,0        ; Set for end of string
  CALL pasciiz
  MOV    ,AL                ; Restore character
  POP    DX                      ; Recover old pointer
  PUSH DX
  ADD DX,OFFSET NAME_FOUND
  CALL pasciiz
  CALL    CRLF
  ; pause at each screenful of files found
  inc    match_count            ; count names displayed

  push ax
  push bx
  mov ax,match_count
  mov dx,0
  mov    cx,18h        ; 18h = 24 decimal
  div    cx            ; ax/cx
  and    dx,dx        ; any bits set to 1 indicate a remainder,
  jnz    PNAME9        ; so pause and display a message

mov dx,offset Press_a_Key1 
mov ah,09h
int 21h

mov ah,08h
int 21h

mov dx,offset Press_a_Key2
mov ah,09h
int 21h

PNAME9:
pop bx
pop ax

POP DX
  POP    AX   
RET
PNAME ENDP

;  This procedure builds an absolute search name from PATH_NAME
;  followed by FILE_NAME.                                       
;
; Reads: FILE_NAME
; Calls: BUILD to build the name

BUILD_NAME PROC NEAR
PUSH SI
MOV SI,OFFSET FILE_NAME
CALL BUILD
POP SI
RET
BUILD_NAME ENDP

BUILD_STAR_NAME PROC NEAR
PUSH SI
MOV SI,OFFSET STAR_NAME
CALL BUILD
POP SI
RET
BUILD_STAR_NAME ENDP

; This procedure appends the string at DS:SI to PATH_NAME in
; PATH_NAME.  It knows where the path name ends from knowing how
; long PATH_NAME is.
;
; DS:SI Name of file
; DS:BX End of PATH_NAME
;
; Reads: DS:SI
; Writes: PATH_NAME

BUILD PROC NEAR
PUSH AX
PUSH DI
MOV DI,BX
  CLD                            ; Set direction for increment

build1:
  LODSB                          ; Copy one character of name
  STOSB
  OR      AL,AL                  ; End of string yet?
  JNZ    build1                  ; No, keep copying
POP DI
POP AX
RET
BUILD ENDP

;  This procedure finds the first match between the name given by
;  DS:DX and the directory entries found in the directory PATH_NAME.
;
;  DS:DX Pointer to current disk transfer area
; Returns:
; CF 0 A match was found
; 1 No match found
; AX Error code returned:
; 2 File not found
; 18 No more files
; DS:DX Pointer to new disk transfer area
;
; Reads: PATH_NAME
; Writes: dbuff

FMATCH PROC NEAR
PUSH CX
  CMP    DX,0                    ; First one?
  JA      allocate                ; No, then allocate space
MOV DX,OFFSET dbuff-TYPE DTA
allocate:
  add    dx,type DTA          ; no, then allocate room for new DTA

;  Bitfields for file attributes:
;Bit(s) Description (Table 01420)
; 7 shareable (Novell NetWare)
; 7 pending deleted files (Novell DOS, OpenDOS)
; 6 unused
; 5 archive
; 4 directory
; 3 volume label
; execute-only (Novell NetWare)
; 2 system
; 1 hidden
; 0 read-only

  mov    cx,00010111b          ; search for ALL files and dirs
  MOV    AH,1AH                ; Set disk transfer address
  INT    21H
  PUSH    DX                    ; Need DX for address of search name
  MOV    DX,OFFSET PATH_NAME
  MOV    AH,4EH                ; Call for "find first match"
  INT    21H
  POP    DX
  POP    CX
  RET                          ; Return with carry flag info
FMATCH ENDP

; Get next match for filename
; (very similar to Get first match routine)

; Returns:
; CF 0 A match was found
; 1 No match found
; AX Error code returned:
; 2 File not found
; 18 No more files
;
; Reads: PATH_NAME
; Writes: dbuff

NMATCH PROC NEAR
PUSH CX
PUSH DX
MOV DX,OFFSET PATH_NAME
  MOV    CX,10H                  ; Attribute for files and directories
  MOV    AH,4FH                  ; Call for "Find next match"
INT 21H
POP DX
POP CX
  RET                            ; Return with carry flag intact
NMATCH ENDP

;  Send CRLF sequence to the screen.

CRLF PROC NEAR
PUSH AX
PUSH DX
MOV AH,02
MOV DL,0AH
INT 21H
MOV DL,0DH
INT 21H
POP DX
POP AX
RET
CRLF ENDP

;  Display ASCIIZ string
;  Call with DS:DX = string addr

pasciiz PROC NEAR
PUSH AX
PUSH DX
PUSH SI
  CLD                            ; Set direction for increment
  MOV    SI,DX                  ; Set up pointer to string
MOV AH,2

pasciiz1:
  LODSB                          ; Get character
  or      al,al                  ; if zero,all done
jz pasciiz2
MOV DL,AL
  INT    21H                    ; Write one character
  jmp    pasciiz1                ; loop till string exhausted

pasciiz2:
POP SI
POP DX
POP AX
RET
pasciiz ENDP

infile  proc    near            ; process name of input file
                                ; DS:SI <- addr command line
mov si,offset command
                                ; ES:DI <- addr filespec buffer
mov di,offset FILE_NAME
cld
  lodsb                  ; any command line present?
  or      al,al          ; return error status if not.
jz infile4

infile1:                      ; scan over leading blanks
  lodsb                ; to file name
  cmp    al,cr        ; if we hit carriage return
  jz      infile4      ; filename is missing.

  cmp    al,20h        ; is this a blank?
  jz      infile1      ; if so keep scanning.

  xor    ah,ah        ; reset "." found flag
                        ; found first char of name
infile2:

  cmp    al,'\'        ; if slash,reset "." flag
jne infile22
  xor  ah,ah

infile22:                    ; check if extension specified

cmp al,'.'
jne infile24
inc ah

infile24:
  stosb                ; move last char. to output
                        ; file name buffer.
  lodsb                ; check next character, found
  cmp    al,cr        ; carriage return yet? 
  je      infile3      ; yes,exit with success code

  cmp    al,'/'        ; or if we hit a switch delimiter
  jne infile26

infile25:
  lodsb                ; get the switch char and save it
  or      al,20h        ; force to lower case
  mov byte ptr es:switch,al
  jmp    infile3      ; then jump to finish up

infile26:
  cmp    al,20h      ; is this a blank?
  jne    infile2    ; if not keep moving chars.

infile27:
  lodsb              ; search up to end, in case of switch
  cmp al,'/'
  je      infile25    ; found switch,go save it

  cmp al,cr
  jne    infile27    ; otherwise, fscan until CR found

infile3:                    ; found end of input name
  or      ah,ah      ; was "." found?
  jnz    infile35    ; yes,jump

  mov    al,'.'      ; no,force ext to wildcard
  stosb
  mov    al,'*'
  stosb

infile35:
  xor    al,al      ; store trailing null byte
  stosb              ; exit with CY=0 as success flag
  clc                 
  ret

infile4:              ; exit with carry =1
  stc                ; for error flag
ret
infile  endp

cseg ends

data segment para public 'DATA'

STAR_NAME db '*.*',0

PATH_NAME      db      'f:\',0
                db      131 dup (0)  ; Space for 128 character path name

FILE_NAME      db      13 dup (0)    ; Save room for full DOS file name

msg1            db      cr,lf
                db      '    WHERE  Fast File Finder  (c) Copyright Andrew Kennedy 2004'
                db      cr,lf
                db      cr,lf
                db      '    WHERE *.asm'
                db      cr,lf
                db      cr,lf
                db      '    Hit CTRL C to end search.'
                db     cr,lf,eom

msg2            db        cr,lf
                db        'No match found.'
                db        cr,lf,eom

Press_a_Key1    db        '-- Press a key --',eom
Press_a_Key2    db        cr,'                ',cr,eom

match_count    dw      0        ; number of filenames matching
                                  ; input filespec

switch          db      0        ; char following / saved here

dbuff          equ    $        ; this starts the scratch area
                                  ; which will be used as search
                                  ; buffers. It is right under
                                  ; the stack, which is made very
                                  ; large to give it room.
data ends

stak  segment para stack 'STACK' ; large stack for increased speed
db 32768 dup (?)
stak  ends

end    whereis
             

Posted on 2007-05-30 17:04:40 by skywalker