📄 setargv.asm
字号:
; CX = number of expanded arguments (0 = no match)
;
WildExpand proc near
push ds
mov wild_argument, si
mov wild_argument+2, ds
mov wild_destin, di
mov wild_destin+2, es
mov word ptr wild_argc, 0
;
; Find the length of the path prefix, if any.
;
mov bx, si
WildFindPath: lodsb
and al, al
jz WildEndPath
cmp al, '\'
je WildDelimiter
cmp al, ':'
je WildDelimiter
cmp al, '\'
jne WildFindPath
WildDelimiter: mov bx, si ; save addr past last delimiter
jmp SHORT WildFindPath
WildEndPath: sub bx, wild_argument
mov wild_path_len, bx
mov ah, 4eh
mov cx, wild_attr ; file attribute
lds dx, dword ptr wild_argument
int 21h ; find first matching file ...
jc WildDone
;
; We have a matching file. Add it to the destination string (unless "." or "..")
;
WildAddArg:
;
; If directories are included (10h set in wild_attr), ignore "." and ".."
;
if wild_attr AND 10h
push ss
pop ds
lea si,wild_ffblk.ff_name
cmp byte ptr [si],'.' ; skip if doesn't start with "."
jne WildNoDir
cmp byte ptr [si+1],0 ; check for "."
je WildNameNext
cmp word ptr [si+1],'.' ; check for ".."
je WildNameNext
WildNoDir:
endif
inc word ptr wild_argc
les di, dword ptr wild_destin
mov cx, wild_path_len ; prefix filename with path
jcxz WildCopyName
lds si, dword ptr wild_argument
WildCopyPath: lodsb
call ArgPushChar
loop WildCopyPath
WildCopyName: lea si,wild_ffblk.ff_name ; copy filename from ffblk
WildNameLoop: lods byte ptr ss:[si]
push ax
call ArgPushChar ; store char in destination
pop ax
and al, al ; continue until \0
jnz WildNameLoop
mov wild_destin, di
WildNameNext: mov ah, 4fh
int 21h ; find next matching file
jnc WildAddArg
;
; Done with expansion. Restore ES:DI, set CX, and return.
;
WildDone: mov cx, wild_argc
les di, dword ptr wild_destin
pop ds
ret
WildExpand endp
;------------------------------------------------------------------------------
;
; Routine to store a character in the destination string.
;
ArgPushChar proc near
cmp di, wild_buff_max ; space available ?
jae ArgMoreSpace
stosb ; yes --> store character
ret
;
; No more argument space. Grab some more memory through sbrk.
;
ArgMoreSpace: push ds
push es
push si
push di
push ax
push bx
push cx
push dx
ifndef __HUGE__
mov ds, savedDS
endif
mov ax, wild_more_space
add wild_buff_size, ax ; bump allocated size
add wild_buff_max, ax ; bump end pointer
push ax
call sbrk@
pop cx
if LDATA
and ax, dx
endif
cmp ax, -1
je NoArgSpace ; abort if not enough space
pop dx
pop cx
pop bx
pop ax
pop di
pop si
pop es
pop ds
stosb ; store character
ret
ArgPushChar endp
;------------------------------------------------------------------------------
;
; Not enough space to process the command line .... abort.
;
NoArgSpace: jmp abort@
;------------------------------------------------------------------------------
;
; Routine to process an argument.
;
ProcessArg proc near
push bx
xor al, al
call ArgPushChar ; null-terminate
pop bx
test bh, 1 ; wildcards present ?
jnz ArgWild
inc dx ; bump arg count
ret
;
; We have a wildcard argument. Expand it.
;
ArgWild: push cx
push [si] ; save word following argument
mov byte ptr [si],0 ; null-terminate argument
xchg si, wild_arg_src ; si = argument address
push di
mov di, wild_arg_dst
push dx
call WildExpand
pop dx
pop bx
and cx, cx ; see if any matched
jnz ArgWildSome
mov di, bx ; none ---> use unexpanded argument
mov cx, 1 ; bump arg count by 1
ArgWildSome: add dx, cx
mov si, wild_arg_src
pop [si] ; restore word following argument
pop cx
ret
ProcessArg endp
;------------------------------------------------------------------------------
;
; Build the argv array. [DS:SI] is the expanded command line, CX its length.
; DX has the number of arguments (including the program name).
;
BuildArgv: push ds
push dx
lds dx, dword ptr wild_DTA_save
mov ah, 1ah
int 21h ; switch to original DTA
pop dx
pop ds
add sp, wild_frame_size ; remove local variables
mov es,savedDS
mov es:[_argc@], dx
inc dx ; argv ends with a NULL pointer
shl dx, 1 ; argc * 2 (LDATA = 0)
IF LDATA
shl dx, 1 ; argc * 4 (LDATA = 1)
ENDIF
mov bx, sp ; point to program name
mov bp, sp
sub bp, dx
jb NoArgSpace
mov sp, bp ; SS:BP = argv array address
mov word ptr es:[_argv@], bp
IF LDATA
mov word ptr es:[_argv@+2], ss
ENDIF
mov [bp], bx ; set argv[0] to program name
IF LDATA
mov [bp+2], ss ; program name is on the stack
ENDIF
add bp, dPtrSize
SetArgvX label near
jcxz SetLastArg
mov [bp], si ; Set argv[n]
IF LDATA
mov [bp+2], ds
ENDIF
add bp, dPtrSize
CopyArg label near
lodsb
or al, al
loopnz CopyArg
jz SetArgvX
SetLastArg label near
xor ax, ax
mov [bp], ax
IF LDATA
mov [bp+2], ax
ENDIF
mov ds, savedDS
;==============================================================================
else
;==============================================================================
mov ds, bp
xchg si, dx ; DS: SI = Command Line address
xchg bx, cx ; CX = Command Line size including \r
mov ax, bx
mov dx, ax ; AX = BX = DX = 0
inc bx ; BX = Nb of arguments (at least 1)
Processing label near
call NextChar
ja NotQuote ; Not a quote and there are more
InString label near
jb BuildArgv ; Command line is empty now
call NextChar
ja InString ; Not a quote and there are more
NotQuote label near
cmp al, ' '
je EndArgument ; Space is an argument separator
cmp al, 13
je EndArgument ; \r is an argument separator
cmp al, 9
jne Processing ; \t is an argument separator
EndArgument label near
xor al, al ; Space and TAB are argument separators
jmp short Processing
; Character test function used in SetArgs
; On entry AL holds the previous character
; On exit AL holds the next character
; ZF on if the next character is quote (") and AL = 0
; CF on if end of command line and AL = 0
NextChar PROC NEAR
or ax, ax
jz NextChar0
inc dx ; DX = Actual length of CmdLine
stosb
or al, al
jnz NextChar0
inc bx ; BX = Number of parameters
NextChar0 label near
xchg ah, al
xor al, al
stc
jcxz NextChar2 ; End of command line --> CF ON
lodsb
dec cx
sub al, '"'
jz NextChar2 ; Quote found --> AL = 0 and ZF ON
add al, '"'
cmp al,'\'
jne NextChar1 ; It is not a \
cmp byte ptr ds:[si], '"'
jne NextChar1 ; Only " is transparent after \
lodsb
dec cx
NextChar1 label near
or si, si ; Be sure both CF & ZF are OFF
NextChar2 label near
ret
NextChar ENDP
; Invalid program name
BadProgName label near
jmp abort@
; Now, build the argv array
BuildArgv label near
pop cx
add cx, dx ; CX = Argument area size
mov ds, SavedDS
mov _argc@, bx
inc bx ; argv ends with a NULL pointer
add bx, bx ; argc * 2 (LDATA = 0)
IF LDATA
add bx, bx ; argc * 4 (LDATA = 1)
ENDIF
mov si, sp
mov bp, sp
sub bp, bx
jb BadProgName
mov sp, bp ; SS:BP = argv array address
mov word ptr _argv@, bp
IF LDATA
mov word ptr _argv@+2, ss
ENDIF
SetArgvX label near
jcxz SetLastArg
mov [bp], si ; Set argv[n]
IF LDATA
mov [bp+2], ss
ENDIF
add bp, dPtrSize
CopyArg label near
lods byte ptr ss:[si]
or al, al
loopnz CopyArg
jz SetArgvX
SetLastArg label near
xor ax, ax
mov [bp], ax
IF LDATA
mov [bp+2], ax
ENDIF
;==============================================================================
endif ; ifdef WILD
;==============================================================================
; Restore caller context and exit
IF LPROG
jmp dword ptr SavedReturn
ELSE
jmp word ptr SavedReturn
ENDIF
ifdef WILD
EndProc@ _wildargv, __CDECL__
else
EndProc@ _setargv, __CDECL__
endif
CSegEnd@
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -