FindStruc struc db 21 dup (?) ;reserved area Attr db ? ;attribute of file Time dw ? ;time of last write Date dw ? ;date of last write Fsize dd ? ;filesize Fname db 13 dup (?) ;filename FindStruc ends CMDSIZE equ 94h ;current resident size of ;command.com is 94h paras code segment byte public 'CODE' assume cs:code, ds:code, es:code org 100h public start start: mov sp,offset MyStack ;set ss:sp to our stack mov ax,offset EndProg add ax,15 mov cl,4 shr ax,cl ;para size of this program mov bx,ax ;bx = this program's size mov cx,es add ax,cx ;ax = top of this program sub ax,1000h - CMDSIZE ;are we below the first 64K? jae no_mem ;no, dont reserve memory neg ax ;additional memory to be reserved add bx,ax no_mem: ;bx = #paras needed mov ah,4ah int 21h ;resize to desired size ; ;Prepare to execute the desired program ; call Exec_prepare jnc do_exec mov al,1 ;return error jmp short exit do_exec: cmp helpflg,1 je do_help mov ah,4bh mov dx,offset ExecPath mov bx,offset ExecBlk int 21h ;do the Exec jc exec_err ;error while executing ; ;No error on execution. Get the return code of the program we executed and ;return that as our return code. ; mov ah,4dh int 21h ;al = return code now exit: mov ah,4ch int 21h ;terminate ourselves exec_err: mov dx,offset ErrMsg ;Error executing command.com mov al,1 call dispmsg jmp short exit do_help: mov dx,offset HelpMsg ;Display help for loadfix call dispmsg xor al,al jmp short exit ;*** ;Dispmsg -- Displays messages that are terminated by '$' ; ;Input: ds:dx = pointer to message ; ;Output: None ; ;Registers: ax ;*** dispmsg proc near mov ah,9 int 21h ret dispmsg endp ;*** ;Exec_prepare -- Searches the environment for the COMSPEC and sets up the ;command line and FCBs for the Exec call ; ;Input: None ; ;Output: Carry set => error. Error message is displayed here ; Carry clear => all parameters set successfully ; ;Registers: ax, cx, dx, si, di ;*** Exec_prepare proc near push ds push es mov si,81h ;ds:si points at our command line call skip_white ;skip all leading whitespace cmp byte ptr [si],0dh ;Did we hit a CR? je no_parms ;yes, no parameters given ; ;Check if we have a /? here ; cmp byte ptr [si],'/' jne no_help cmp byte ptr [si+1],'?' jne no_help inc helpflg ;/? given -- print help jmp short exefnd no_help: mov dx,si ;ds:dx now points at the program mov si,offset CmdOpt mov di,offset CmdParms inc di mov cl,CmdOptLen xor ch,ch rep movsb mov si,dx xor cx,cx st_lp: lodsb stosb inc cx cmp al,0dh jne st_lp dec cx add cl,CmdOptLen ;command line cannot be >128 mov CmdParms,cl mov si,offset CmdParms mov word ptr CmdPtr,si mov word ptr CmdPtr+2,cs ;store command line pointer mov word ptr Fcb1+2,cs mov word ptr Fcb2+2,cs call find_comspec jc no_comspec mov si,offset ExecPath xchg si,di push ds push es pop ds pop es comspec_lp: lodsb stosb or al,al jnz comspec_lp exefnd: clc execp_ret: pop es pop ds ret no_parms: mov dx,offset NoParms call dispmsg stc jmp short execp_ret no_comspec: mov dx,offset NoComspec call dispmsg stc jmp short execp_ret Exec_prepare endp ;*** ;skip_white -- Skips all whitespace characters until it hits a non-whitespace ; ;Input: ds:si = string to be looked at ; ;Output: ds:si points at the first non-whitespace char in the string ; ;Registers: ax, si ;*** skip_white proc near lodsb cmp al,20h ;Blank? je skip_white ;yes, skip cmp al,9 ;Tab? je skip_white ;yes, skip dec si ;point at the first non-white ret skip_white endp ;*** ;find_comspec -- searches in the environment for the COMSPEC variable ; ;Input: None ; ;Output: es:di points at the arguments of the COMSPEC= variable ; ;Registers: si ;*** find_comspec proc near mov si,offset Comspec_Text ; ; input: ds:si points to a "=" terminated string ; output: es:di points to the arguments in the environment ; zero is set if name not found ; carry flag is set if name not valid format ; call find ; find the name jc done_findp ; carry means not found call scasb1 ; scan for = sign done_findp: ret find_comspec endp ;*** ;find -- scans the environment for the variable whose name is passed in ; ;Input: ds:si points at the environment variable to be scanned for ; ;Output: es:di points at the environment variable ; ;Registers: ax, di ;*** find proc near cld call count0 ; cx = length of name mov es,es:[2ch] ; get environment segment ; ;Bugbug: What if the environment segment here is 0? ; xor di,di find1: push cx push si push di find11: lodsb inc di cmp al,es:[di-1] jnz find12 loop find11 find12: pop di pop si pop cx jz end_find push cx call scasb2 ; scan for a nul pop cx cmp byte ptr es:[di],0 jnz find1 stc ; indicate not found end_find: ret find endp ;*** ;count0 -- returns length of string until the first '=' char ; ;Input: ds:si points at the string ; ;Output: cx = length until '=' ; ;Registers: di ;*** count0 proc near mov di,si ;ds = es = cs push di ; count number of chars until "=" call scasb1 pop cx sub di,cx xchg di,cx ret count0 endp ;*** ;scasb1 -- scans string for the first '=' ;scasb2 -- scans string for the first null ; ;Input: es:di = string ; ;Output: es:di points after the desired char ; ;Registers: ax, cx ;*** scasb1 proc near mov al,'=' ; scan for an = jmp short scasbx scasb2: xor al,al ; scan for a nul scasbx: mov cx,100h repnz scasb ret scasb1 endp ;************************** ;Data ;************************** ExecBlk label word dw 0 CmdPtr dd ? Fcb1 dw offset MyFcb1 dw ? Fcb2 dw offset MyFcb2 dw ? dw 128 dup (1) MyStack label word CmdOpt db '/C ' CmdOptLen db $ - CmdOpt CmdParms db 128 dup (?) ;buffer to hold prog to be Exec'ed ExecPath db 67 dup (?) ;holds path to COMMAND.COM ComSpec_Text db 'COMSPEC=',0 MyFcb1 db 0 db 11 dup (' ') MyFcb2 db 0 db 11 dup (' ') Helpflg db 0 ;default is no help include loadmsg.msg EndProg label byte code ends end start