📄 init.asm
字号:
add bx,15 ; round up the size
mov cl,4 ;
shr bx,cl ; size of command.com
mov ah,SETBLOCK ; free all memory above pgm
int 21h ;
pop ax ;
;
; Compute maximum size of environment
;
mov EnvMax,(SIZE Environment + 15) / 16 + (EnvMaximum-zero + 15)/16 - 1
;
; Compute minimum size of environment
;
mov EnvSiz, ENVSML / 16
mov dx,offset TranGroup:Transpaceend + 15 ; dx = size of transient
mov cl,4 ; in paragraphs.
shr dx,cl
mov Trnsize,dx ; save size of transient in paragraphs
sub ax,dx ; max seg addr - # para's needed for transient
mov Trnseg,ax ; = seg addr to load the transient at.
mov ax,ds:PDB_Environ ; ax = environment segment
mov EnvirSeg,ax ;
or ax,ax ; if there is no environment segment,
jz buildenv ; make one
cmp FirstCom,0 ; if this is the first command.com,
je environpassed ; do a merge job (make sure COMSPEC exists)
;
; We allocate a buffer here just large enough to hold the 'PATH=' and
; the COMSPEC. After parsing, we will allocate an environment of the right
; size and free this buffer. We need this buffer because we no longer have an
; ENVIRONMENT segment but need a place to store the COMSPEC which can be
; given on the command line before we know the environment size. This routine
; will not return in case of an allocation error. It will either exit or hang
; depending on whether or not this is the first COMMAND.COM or not.
;
buildenv:
call alloc_env ; try to allocate buffer
environpassed:
mov es,ax ; and it load into es.
assume es:nothing
gottheenvir:
;
; Initialize the command drive
;
mov ah,GET_DEFAULT_DRIVE
int 21h
inc al
mov Comdrv,al
mov al,byte ptr ds:Fcb ; al = default drive number for command
or al,al
jz nocomdrv ; no drive specified
mov ah,':'
mov Comdrv,al
add al,40h ; convert number to uppercase character
ifndef ROMDOS
; (Don't add drive specifier to ROM COMMAND COMSPEC.)
std
cmp AllocedEnv,0 ; if a new environment is being built,
je notwidenv ; move the default comspec string in it
mov di,ComspOffset
cmp byte ptr es:[di+1],':' ; drive specifier already exist?
je notwidenv ; yes, must have been inherited that way
push ds ; 2 bytes to make room for a drivespec.
push es ; the drivespec is in ax and is copied
pop ds ; on to the front of the string.
lea si,[di+MAX_COMSPEC-3]
lea di,[di+MAX_COMSPEC-1]
mov cx,MAX_COMSPEC - 2
rep movsb
pop ds
mov word ptr es:[di-1],ax
endif ;ROMDOS
notwidenv:
cld ; add the drivespec to the string
mov word ptr AutoBat,ax ; used to reference autoexec.bat
mov word ptr KautoBat,ax ; used to reference kautoexe.bat 3/3/kk
nocomdrv:
call setvect ; set interrupt vectors 22h, 23h, & 24h
;*********************************
; parsing starts here
;*********************************
push cs ; get local segment
push cs ; into ds,es
pop ds ;
pop es ;
assume ds:ResGroup,es:ResGroup
mov si,80h ; get command line
lodsb ; get length of line
mov di,si ; get line position in di
xor ah,ah ; ax = length of command line
;
; insure that the command line correctly ends with a cr
;
add di,ax ; go to end of command line
mov byte ptr [di],0dh ; insert a carriage return
xor cx,cx ; clear cx
mov Num_positionals,cx ; initialize positionals
;
; Scan the command line looking for the parameters
;
Parse_command_line:
mov di,offset ResGroup:Parse_Command; Get address of parse_command
mov cx,Num_positionals ; Get number of positionals
xor dx,dx ; clear dx
mov Old_parse_ptr,si ; save position before calling parser
call init_parse ; call parser
mov Num_positionals,cx ; Save number of positionals
cmp ax,END_OF_LINE ; are we at end of line?
jne t1
jmp ArgsDone ; yes - exit
t1: cmp ax,RESULT_NO_ERROR ; did an error occur
jz parse_cont ; no - continue
;
; Before issuing error message - make sure switch is not /C
;
parse_line_error:
push si ; save line position
push ax ; save error number
cmp ax,BADSWT_PTR ; Was error invalid switch?
jnz parse_line_error_disp ; No - just issue message
mov di,si ; Get terminating pointer in DI
mov si,Old_parse_ptr ; Get starting pointer in SI
init_chk_delim:
cmp si,di ; at end of parsed parameter?
jz parse_line_error_disp ; Yes - just display message
lodsb ;
cmp al,Space ; Skip blank spaces
jz init_chk_delim ;
cmp al,TAB_CHR ; Skip tab characters
jz init_chk_delim ;
cmp al,Rswitchar ; Switch?
jnz parse_line_error_disp ; No - just issue message
lodsb ; Get the char after the switch
ifdef DBCS
call ItestKanj ; Is it DBCS?
jnz parse_line_error_disp ; Yes - can't be /C or /K
endif
call iupconv ; upper case it
cmp al,Scswitch ; it is /C?
jnz check_k_too ;
pop dx ; even up stack
pop dx ; even up stack
jmp setSSwitch ; Yes - go set COMMAND /C
check_k_too:
cmp al,Skswitch ; it is /K?
jnz parse_line_error_disp ;
pop dx ; even up stack
pop dx ; even up stack
jmp setKSwitch ; Yes - go set COMMAND /K
parse_line_error_disp:
pop ax ; restore error number
pop si ; restore line position
mov dx,ax ; get message number
call RPrintParse
call CrLf
jmp short Parse_command_line ; continue parsing
parse_cont:
;
; See if a switch was entered
;
; Bugbug: See if Comnd1_Syn can be moved into a reg. before the compare
cmp Comnd1_Syn,offset ResGroup:Command_f_syn ; was /F entered?
jz SetFSwitch ; yes go set fail switch
cmp Comnd1_Syn,offset resgroup:Command_p_syn ; was /P entered?
Jz SetPSwitch ; yes go set up PERMCOM
cmp Comnd1_Syn,offset resgroup:Command_d_syn ; was /D entered?
jz SetDSwitch ; yes go set date switch
cmp Comnd1_Syn,offset resgroup:Command_c_syn ; was /C entered?
jz SetSSwitch ; yes go set up SINGLECOM
cmp Comnd1_Syn,offset resgroup:Command_k_syn ; was /K entered?
jz SetKSwitch ; yes go set up SINGLECOM
cmp Comnd1_Syn,offset resgroup:Command_e_syn ; was /E entered?
jz SetESwitch ; yes go set up environment
cmp Comnd1_Syn,offset resgroup:Command_m_syn ; was /MSG entered?
jz SetMSwitchjmp ; yes go set up message flag
jmp ChkOtherArgs ; Must be something else
SetMSwitchjmp: ; long jump needed
jmp SetMswitch ;
SetFSwitch:
cmp fFail,-1 ; has fail switch been set?
jnz failok ; no - set it
mov ax,Moreargs_ptr ; set up too many arguments
jmp parse_line_error ; go issue error message
failok:
mov fFail,-1 ; fail all INT 24s.
jmp Parse_command_line ;
SetPSwitch:
;
; We have a permanent COMMAND switch /P. Flag this and stash the
; termination address.
;
cmp PermCom,0 ; has /p switch been set?
jz permcomok ; no - set it
mov ax,moreargs_ptr ; set up too many arguments
jmp parse_line_error ; go issue error message
permcomok:
inc PermCom
mov word ptr OldTerm,offset DATARES:LodCom_Trap
mov word ptr OldTerm+2,ds
;
; make sure that we display the date and time. if the flag was not
; initialized, set it to indicate yes, do prompt.
;
cmp byte ptr PrdAttm,-1
jnz Parse_command_line_jmp ; keep parsing
mov byte ptr PrdAttm,0 ; if not set explicit, set to prompt
Parse_command_line_jmp: ;
jmp parse_command_line ; keep parsing
SetDSwitch:
;
; Flag no date/time prompting.
;
cmp Dswitch,0 ; has /D switch been set?
jz setdateok ; no - set it
mov ax,Moreargs_ptr ; set up too many arguments
jmp parse_line_error ; go issue error message
setdateok:
inc Dswitch ; indicate /D entered
mov byte ptr PrdAttm,1 ; user explicitly says no date time
jmp Parse_command_line ; continue parsing
SetKSwitch:
mov SemiPermCom,0
jmp short SetSorKSwitch
SetSSwitch:
;
; Set up pointer to command line, flag no date/time and turn off singlecom.
;
mov Permcom,0 ; a singlecom must not be a permcom
SetSorKSwitch:
mov SingleCom,si ; point to the rest of the command line
mov byte ptr PrdAttm,1 ; no date or time either, explicit
jmp ArgsDone
;
; Look for environment-size setting switch
;
; The environment size is represented in decimal bytes and is
; converted into pargraphs (rounded up to the next paragraph).
;
SetESwitch:
cmp Eswitch,0 ; has fail switch been set?
jz eswitchok ; no - set it
mov ax,Moreargs_ptr ; set up too many arguments
jmp Parse_line_error ; go issue error message
eswitchok:
inc Eswitch ; indicate /E entered
mov di,offset ResGroup:Comnd1_Addr ; get number returned
mov bx,word ptr [di] ; into bx
add bx, 0fh ; Round up to next paragraph
mov cl,4 ; convert to pargraphs
shr bx, cl ; by right 4
mov EnvSiz,BX ; EnvSiz is in paragraphs
jmp Parse_command_line ; continue parsing command line
SetMSwitch:
cmp Ext_msg,SET_EXTENDED_MSG ; has /MSG switch been set?
jnz setMswitchok ; no - set it
mov ax,Moreargs_ptr ; set up too many arguments
jmp Parse_line_error ; go issue error message
setMswitchok:
mov Ext_msg,SET_EXTENDED_MSG ; set /MSG switch
jmp Parse_command_line ; keep parsing
ArgsDoneJ:
jmp ArgsDone
;
; We have a non-switch character here.
;
ChkOtherArgs:
push ds ;
push si ; save place in command line
lds si,Comnd1_Addr ; get address of filespec
assume ds:nothing ;
mov dx,si ; put in dx also
mov ax,(OPEN shl 8) or 2 ; Read and write
int 21h
jc ChkSrchSpec ; Wasn't a file
mov bx,ax
mov ax,IOCTL shl 8
int 21h
test dl,80h
jnz IsaDevice
BadSetCon: ;
mov ah,CLOSE ; Close initial handle, wasn't a device
int 21h
jmp short ChkSrchSpec
IsaDevice:
xor dh,dh
or dl,3 ; Make sure has CON attributes
mov ax,(IOCTL shl 8) or 1
int 21h
jc BadSetCon ; Can't set attributes - quit
mov dx,bx ; Save new handle
cmp es:DevFlag,1
jz DevErr
push cx
mov cx,3
xor bx,bx
rcclloop: ; Close 0,1 and 2
mov ah,CLOSE
int 21h
inc bx
loop rcclloop
mov bx,dx ; New device handle
mov ah,XDUP
int 21h ; Dup to 0
mov ah,XDUP
int 21h ; Dup to 1
mov ah,XDUP
int 21h ; Dup to 2
mov ah,CLOSE
int 21h ; Close initial handle
pop cx
pop si ; restore position of command line
pop ds ;
;
; Register the fact that we already have redirected the output and cannot do
; it again
;
inc es:DevFlag ;
jmp Parse_command_line ; continue parsing
DevErr:
pop si
pop ds
mov dx,1
call RPrintParse ; "Too many parameters"
call CrLf
jmp Parse_command_line
ChkSrchSpec: ; Not a device, so must be directory spec
cmp es:PathFlag,1 ; already set COMSPEC?
jz DevErr ; yes, error
inc es:PathFlag ; mark that we have a path
;
; We have to override the passed environment. Allocate a buffer for use now.
; This buffer will later be replaced by a proper environment
;
call alloc_env ; environment buffer
mov es,ax
assume es:nothing
push si ; remember location of file
xor cx,cx ; clear cx for counting
countloop:
lodsb ; get a character
inc cx ; increment counter
cmp al,END_OF_LINE_OUT ; are we at end of line?
jnz countloop ; no - keep counting
mov al,Space
dec si ; move back one
mov byte ptr [si],al ; put a space at end of line
;
; We now know how long the new pathspec for command.com is. Time to
; figure out how long the current COMSPEC setting is, and then to move
; all the environment data up, throwing that COMSPEC setting away, and
; preparing to append the new COMSPEC. ComspOffset (the offset of
; where the filespec exists in the environment) is updated as well.
;
push cx ;
mov cx,ENVBIG ;
mov di,ComspOffset ; get location of COMSPEC
mov al,0 ;
repne scasb ; find the end of COMSPEC
mov si,di ;
comp_endenv: ;
scasb ; end of env?
je got_endenv ; yes
repne scasb ;
jmp comp_endenv ;
got_endenv: ;
mov cx,di ;
sub cx,si ;
mov di,ComspOffset ;
sub di,ComspStrLen ;
push ds ;
push es ;
pop ds ;
rep movsb ;
dec di ; copy in new COMSPEC=
push cs ;
pop ds ;
assume ds:ResGroup ;
mov si,offset RESGROUP:ComspString ;
mov cx,ComspStrLen ;
rep movsb ;
mov ComspOffset,di ;
pop ds ;
assume ds:nothing ;
pop cx ;
pop si ; get new comspec location back
ComtrLoop:
lodsb
dec cx
cmp al,Space
jz SetComsr
stosb
ifdef DBCS
xor ah,ah
endif
jcxz setcomsr
ifdef DBCS
push ds ; Make sure we have
push cs ; local DS for
pop ds ; ItestKanj
call ItestKanj
pop ds ; restore parser ds
jz ComtrLoop
dec cx
movsb
inc ah
jcxz setcomsr
endif
jmp short comtrloop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -