📄 iwhereis.asm
字号:
mov [NextFileSpec],offset FileSpec
mov [PathPtr],offset Path
mov [DrivePtr],offset Drive
mov al,[FileSpecCounter]
ProcessFileSpec: ; Jump to here if AL already loaded
cmp al,MAX_FILE_SPECS
je @@StartFileSearch ;**3
inc al
call GetArgument
or al,al
jz @@StartFileSearch ; If al=0, we are at the end of arguments.
mov al,[byte es:di+1]
call IsDelimiter
jc HandleDosCommand
; **2
; push es ; Store the location of the unparsed file spec.
; push di
;
; ; Pull apart the drive, path and filename so we can store the
; ; filename specification.
;
; push ds ; Push the address to store the drive spec. in
; if (@Cpu and 100b) eq 100b
; push offset Drive
; else
; mov ax, offset Drive
; push ax
; endif
; push ds ; Push the address to store the path spec. in
; if (@Cpu and 100b) eq 100b
; push offset Path
; else
; mov ax, offset Path
; push ax
; endif
; push ds ; Push address to store filename spec. in
; if (@Cpu and 100b) eq 100b
; push offset FileSpec
; else
; mov ax, offset FileSpec
; push ax
; endif
; Parse the filename into it's components
call ParseFilename,es,di, \ ;Filespec to be parsed
ds,[DrivePtr], \ ;**6
ds,[PathPtr], \
ds,[NextFileSpec]
mov al,[FileSpecCounter]
or al,al
jz CheckFirstArg ; If al is zero, we are checking first
; argument, so we can allow drive and
; path specification.
mov bx,[PathPtr]
cmp [byte bx], 0 ; Check if the parsed path is empty
jne @@IllegalPath
mov bx,[DrivePtr] ; Check if the parsed drive is empty
cmp [byte bx],0
jne @@IllegalPath
jmp @@GetAnotherFileSpec
@@IllegalPath: ; Give an error for path on parameter other
; than the first.
call PathAfterFirst
CheckFirstArg:
; For the next arguments, set the pointers to dummy areas
; since we don't pay attention to the path and drive for
; arguments other than the first.
mov [PathPtr],offset tempPath
mov [DrivePtr],offset tempDrive
cmp [byte Path], 0 ; Check if the path is empty
jne HaveAPath
mov [byte Path], 1
mov [byte Path+1], '\'
HaveAPath:
cmp [byte Drive], 0 ; Check if a drive definition exists
je DontChangeDrives
cmp [byte Drive+1], 61h ; Check if the drive letter is lower
jng IsCapitalized ; case
sub [byte Drive+1], 20h ; Capitalize the drive letter
IsCapitalized:
mov al, [byte Drive+1]
sub al, 'A'
ChangeDrive <al> ; Change to the appropriate drive
jmp DoneWithFirstArg
DontChangeDrives:
mov [byte Drive], 2 ; Initialize the drive
mov al, [byte OldDrive]
mov [byte Drive+1], al ; string with the
add [byte Drive+1], 'A' ; current drive.
DoneWithFirstArg:
jmp @@GetAnotherFileSpec
HandleDosCommand:
; If a DOS command is given, it is surrounded by quotes.
; We need to strip the quotes, and store it in the module that
; handles executing DOS commands.
call ParseDosCommand
jnc @@DoneWithArg ; If no errors, we are done with this arg
call OnlyOneDosCommand
@@GetAnotherFileSpec:
add [NextFileSpec],FILE_SPEC_SIZE
; Increment the FileSpecCounter
mov al,[FileSpecCounter]
inc al
mov [FileSpecCounter],al ; FileSpecCounter has # files found so far
@@DoneWithArg:
jmp ProcessFileSpec
@@StartFileSearch:
; We are now done analyzing the command line parameters.
; Copy the start path onto the stack
sub sp, MAX_PATH_LENGTH ; Make room on the stack
mov si, sp
xor ah, ah
mov al, [byte Path] ; Get the path length
inc al ; We want to copy the length byte also
inc al ; And the null terminator
call ByteCopy,ds,offset Path,ss,si ; Copy the path onto the stack
call FindFiles ; Do the search for the file(s)
call Terminate ; End the program
;*************************************************************************
endp main
proc Terminate
; This procedure handles exiting from WHEREIS and restoring the
; original directory and drive.
mov ax, [SavedDS]
mov ds,ax
mov al, [byte OldDrive] ; Get the original disk drive
ChangeDrive <al> ; Restore the original disk drive
ChangeDirectory <seg HomeDirectory>, <((offset HomeDirectory) - 1)>
mov es,[Old1BHandlerSeg]
mov bx,[Old1BHandlerOfs]
SetVector 1Bh, es, bx
mov ah, DOS_TERMINATE_EXE
int DOS_FUNCTION
endp Terminate
proc Int1B far
; This procedure handles intercepting CTRL-BREAK so that the
; main directory searching loop can break out.
mov [BreakPressed],1 ; Set break flag
iret
endp Int1B
proc Initialize
; This procedure initializes all global variables and data structures
; used by the program.
;
; Input
; none
; Output
; none
; Calling conventions
; NA
; Registers modified
; ax, flags
; Store the PSP address by storing es in the variable PspAddress.
; Note that we do it this way instead of using DOS function 62h because
; the function is only available on DOS 3.0 or later.
mov [PspAddress], es
push ds
GetCurrentDir <0>, <seg HomeDirectory>, <offset HomeDirectory>
pop ds
GetDrive ; Get the current disk drive
mov [byte OldDrive], al ; Save it
; Install a control break handler.
push ds
mov ax,ds ; Save DS for future reference by break handler!
mov [SavedDS],ax
SetVector 23h,<seg Terminate>,<offset Terminate>
; mov ah,25h ; Int 25 = Set interrupt
; mov al,23h
; mov dx,seg Terminate
; mov ds,dx
; mov dx,offset Terminate
; int 21h
; Also, so the main loop for going thru directories can respond
; in a timely fashion to ctrl-break being pressed, install a
; handler for vector 1Bh.
GetVector 1Bh
pop ds
mov [Old1BHandlerSeg],es
mov [Old1BHandlerOfs],bx
push ds
SetVector 1Bh, <seg Int1B>, <offset Int1B>
pop ds
; Verify that the user provided command line parameters.
call ParamCount
or al, al ; Were any parameters passed by user?
jnz @@Exit
call UsageScreen ; If no, display usage screen
@@Exit:
ret
endp Initialize
proc UsageScreen
; This routine displays a 'usage' screen that describes the syntax for
; using WHEREIS. It then terminates the program.
;
; Input
; ds - Points to data segment where usage screen text is located
; Output
; none
; Calling conventions
; NA
; Registers modified
; ax, cx, dx
call WriteAsciizString,ds,offset Syntax
call Terminate ; Terminate program
endp UsageScreen
proc PathAfterFirst
; This routine displays a 'usage' screen that tells the user that
; drive and path info may only be given on the first argument.
; It then terminates the program.
;
; Input
; ds - Points to data segment where usage screen text is located
; Output
; none
; Calling conventions
; NA
; Registers modified
; ax, cx, dx
call WritePascalString,ds,offset OnlyFirst ;**2
call Terminate ; Terminate program
endp
proc OnlyOneDosCommand
; This routine displays a 'usage' screen that tells the user that
; drive and path info may only be given on the first argument.
; It then terminates the program.
;
; Input
; ds - Points to data segment where usage screen text is located
; Output
; none
; Calling conventions
; NA
; Registers modified
; ax, cx, dx
call WritePascalString,ds,offset OnlyOneCommand
call Terminate ; Terminate program
endp OnlyOneDosCommand
endif ; ifndef MDL
end EntryPoint
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -