⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 init.asm

📁 DOS 源代码 系列之 command 源码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
        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 + -