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

📄 init.asm

📁 DOS 源代码 系列之 command 源码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	mov	di,offset DATARES:Int2f_Entry

	mov	ds,word ptr es:ResJmpTable+2	;get segment address
	mov	si,word ptr es:ResJmpTable		;get offset address

	mov 	cx,NUM_RELOC_ENTRIES 			;number of dword ptrs
	shl	cx,1
	shl	cx,1				;size of table in bytes

	cld
	rep	movsb				;copy the jump table
;
;Check if the resident code is in HMA. We assume that it is in HMA if its 
;code segment > 0f000h. If in HMA, we set the ComInHMA flag
;
	cmp	es:[di-2],0f000h			;is resident code in HMA?
	jb	res_low			;no, dont set flag

	mov	es:ComInHMA,1			;indicate code in HMA

res_low:
	pop	ds
	pop	es
	jmp	short finish_init
;
;Now, we can move the resident code to its final location, either to HIMEM
;or to overlay the messages in the data segment if the user has not used the
;/msg switch.
;
move_code:
	call	Move_res_code			;move the code

finish_init:
	jmp	RESGROUP:EndInit 			;g finish initializing

;
;	Get length of string pointed to by DS:SI.  Length includes NULL.
;	Length is returned in CX
;
GetStrLen:
	xor	cx,cx
NxtChar:
	lodsb
	inc	cx
	or	al,al
	jnz	NxtChar
	ret
;
; If the transient has been loaded in TranSeg, then we need to use that
; segment for calls to routines in the transient area. Otherwise, the current
; code segment is used
; Segment returned in AX.
;
Setup_Seg:
	mov	ax,TrnSeg
	cmp	TrnMvFlg, 1			; Has transient portion been moved
	jz	setup_end
	push	bx
	mov	bx,cs
	mov	ax,offset ResGroup:TranStart
	shr	ax,1
	shr	ax,1
	shr	ax,1
	shr	ax,1
	add	ax,bx
	pop	bx
setup_end:
	ret


;***	RPrintParse - display parse error message
;
;	ENTRY	DX = parse error #
;
;	EXIT	nothing
;
;	USED	flags
;
;	EFFECTS
;	  Message is displayed on stdout.

RPrintParse	proc

	assume	ds:ResGroup,ss:ResGroup

	push	dx				; preserve DX
	xchg	bx,dx				; bx = parse error #
						; dx = saved BX
	dec	bx				; bx = parse error index, from 0
	shl	bx,1				; bx = offset in word table
	mov	bx,ParsMsgPtrs[bx]			; bx = ptr to error msg
	xchg	bx,dx				; dx = ptr to error msg
						; bx = restored
	call	RPrint				; print the message
	pop	dx				; restore DX
	ret

RPrintParse	endp



IfindE:
	call	ifind				; find the name
	jc	ifind2				; carry means not found
	jmp	short Iscasb1 			; scan for = sign
;
; on return of find1, es:di points to beginning of name
;
ifind:
	cld
	call	Icount0 			; cx = length of name
	mov	es,EnvirSeg
	xor	di,di

ifind1:
	push	cx
	push	si
	push	di

Ifind11:
	lodsb

	ifdef	DBCS

	call	ItestKanj
	jz	NotKanj4
	dec	si
	lodsw
	inc	di
	inc	di
	cmp	ax,es:[di-2]
	jnz	Ifind12
	dec	cx
	loop	Ifind11
	jmp	short Ifind12
NotKanj4:

	endif

	call	IupConv
	inc	di
	cmp	al,es:[di-1]
	jnz	Ifind12
	loop	Ifind11

Ifind12:
	pop	di
	pop	si
	pop	cx
	jz	Ifind2
	push	cx
	call	Iscasb2 			; scan for a nul
	pop	cx
	cmp	byte ptr es:[di],0
	jnz	Ifind1
	stc					; indicate not found

Ifind2:
	ret

Icount0:
	push	ds
	pop	es
	mov	di,si

	push	di				; count number of chars until "="
	call	Iscasb1
	jmp	short Icountx
	push	di				; count number of chars until nul
	call	Iscasb2

Icountx:
	pop	cx
	sub	di,cx
	xchg	di,cx
	ret

Iscasb1:
	mov	al,Equalsign			; scan for an =
	jmp	short Iscasbx

Iscasb2:
	xor	al,al				; scan for a nul

Iscasbx:
	mov	cx,100h
	repnz	scasb
	ret


; ****************************************************************
; *
; * ROUTINE:	 IUPCONV    (ADDED BY EMG 4.00)
; *
; * FUNCTION:	 This routine returns the upper case equivalent of
; *		 the character in AL from the file upper case table
; *		 in DOS if character if above  ascii 128, else
; *		 subtracts 20H if between "a" and "z".
; *
; * INPUT:	 DS	      set to resident
; *		 AL	      char to be upper cased
; *		 FUCASE_ADDR  set to the file upper case table
; *
; * OUTPUT:	 AL	      upper cased character
; *
; ****************************************************************


IupConv proc	near				
	assume	ds:ResGroup			;

	cmp	al,80h				; see if char is > ascii 128
	jb	other_fucase			; no - upper case math
	sub	al,80h				; only upper 128 chars in table
	push	ds				;
	push	bx				;
	lds	bx,dword ptr fucase_addr+1		; get table address
	add	bx,2				; skip over first word
	xlat	ds:byte ptr [bx]			; convert to upper case
	pop	bx				;
	pop	ds				;
	jmp	short iupconv_end			; we finished - exit

other_fucase:					;
	cmp	al,Lcasea			; if between "a" and "z",
	jb	iupconv_end			;     subtract 20h to get
	cmp	al,Lcasez			; upper case equivalent.
	ja	iupconv_end			;
	sub	al,20h				; Change lower-case to upper

iupconv_end:					;
	ret

IupConv endp					;


init_contc_specialcase:
						; This routine is called if control-C
	add	sp,6				;  is type during the date/time prompt
	push	si				;  at initialization time.  The desired
	mov	si,dx				;  response is to make it look like the
	mov	word ptr [si+1],0d00h			;  user typed <CR> by "popping" the
	pop	si				;  INT 21h stuff off the stack, putting
	iret					;  a <CR> in the user's buffer, and
						;  returning directly to the user.
						; In this case the user is TCODE.


; ****************************************************************
; *
; * ROUTINE:	 Setup_for_messages
; *
; * FUNCTION:	 Sets up system for PARSE and EXTENDED ERROR
; *		 messages as follows:
; *
; *		 IF /P and /MSG are entered
; *		    keep PARSE and EXTENDED ERRORS in memory
; *		 ELSE IF /P is entered
; *		    use PARSE and EXTENDED ERRORS on disk
; *		    remove PARSE ERRORS from memory
; *		 ELSE
; *		    remove PARSE ERRORS from memory
; *		 ENDIF
; *
; * INPUT:	 PERMCOM	Set up with user input
; *		 EXT_MSG	Set up with user input
; *		 System set up to retain PARSE ERRORS
; *
; * OUTPUT:	 registers unchanged
; *
; ****************************************************************


setup_for_messages	proc	near		

	push	bx
	push	ds				; save data segment
	push	es				; save environment segment
	push	ax				;
	push	dx				;
	push	di				;
	mov	ax,cs				; get local segment to ES and DS
	mov	ds,ax				;
	mov	es,ax				;

	cmp	PermCom,0			; was permcom set?
	jz	no_permcom			; No - don't worry about messages

;*	We're permanent.  Install our message services int 2f handler.

	push	es
	mov	ax,(GET_INTERRUPT_VECTOR shl 8) or 2Fh
	int	21h
	mov	word ptr Int2fHandler,bx
	mov	word ptr Int2fHandler+2,es
	pop	es

;	DS = RESGROUP seg addr

;
; M005; We will not hook int 2fh on any command.com other than the first.
; M005; Carousel loads as a permanent command.com and when we exit Carousel,
; M005; it just wipes our arena out. So, int 2fh is still hooked and the
; M005; first int 2fh call after exit from Carousel (from the DOS terminate
; M005; call) goes off into space.
;
	cmp	FirstCom,0			; M005
	je	no_msg_hook			; M005
;
; M005; !!!SLIMIEST CAROUSEL HACK OFF ALL!!!
; M005; Carousel plays around with the interrupt vector tables. He saves it
; M005; before loading a new command.com. Then, it takes hold of the current
; M005; command.com's PSP and then looks at all interrupt vectors whose
; M005; segment matches the command.com PSP and then updates these segments
; M005; to the new command.com's PSP in his saved vector table. Whenever we
; M005; we pop into his menu, he puts this saved table into the vector table.
; M005; If we now quit, Carousel just wipes out command.com's arena and then
; M005; issues a terminate. Unfortunately, the int 2fh vector is pointing at
; M005; the command.com that was wiped out and so the next int 2fh call will
; M005; bomb. To prevent Carousel from doing this clever(1**$$#) patching, we
; M005; renormalize our int 2fh pointer so that its cs is not the same as the
; M005; command.com PSP. Now, he does no such patching and our int 2fh vector
; M005; remains nice and happy. The renormalized pointer points at a far 
; M005; jump to the actual int 2fh entry point.
;
	push	ds				; M005
	mov	dx,offset DATARES:Carousel_i2f_Hook ; M005
	sub	dx,10h				; renormalize offset; M005
	mov	ax,ds				; M005
	inc	ax				; Relocated cs ; M005
	mov	ds,ax				; M005
	mov	ax,(SET_INTERRUPT_VECTOR shl 8) or 2Fh
	int	21h
	pop	ds				; M005
	mov	word ptr Carousel_i2f_Hook+3,ds	; M005
						; patch in the cs for jump
no_msg_hook:					; M005

	cmp	Ext_Msg,SET_EXTENDED_MSG
	jne	short permcom_end			; no /msg - exit

permcom_slash_msg:				; Keep messages in memory
	mov	di,offset ResGroup:ExtMsgEnd 	; get address of resident end
	mov	ResMsgEnd,di			; save it
	jmp	short permcom_end			; exit

no_permcom:					
	cmp	Ext_msg,SET_EXTENDED_MSG		; was /msg specified?
	jnz	permcom_end			; no - no error
	mov	dx,LessArgs_Ptr 			; get message number for "Required parameter missing"
	call	RPrintParse

permcom_end:
	pop	di				;
	pop	dx				;
	pop	ax				;
	pop	es				; get environment back
	pop	ds				;
	pop	bx

	ret					;

setup_for_messages	endp




;***	CheckHelp - print help text and exit if /? is on command line
;
;	ENTRY	command-line tail at 81h
;
;	EXIT	return if /? not found
;		terminate if /? found
;
;	USED	AX,BX,CX,DX,SI,DI
;
;	EFFECTS	Help text displayed if /? found on command line

CheckHelp	proc

	assume	cs:RESGROUP,ds:RESGROUP,es:RESGROUP,ss:RESGROUP

	mov	si,81h			; DS:SI = ptr to command-line tail
	mov	di,offset RESGROUP:Parse_Command
					; ES:DI = ptr to primary parse block
	xor	cx,cx			; CX = # positional param's found
	xor	dx,dx			; DX will be ptr to result buffer

chParse:
	call	Init_Parse		; call system parser

	cmp	ax,END_OF_LINE
	je	chRet			; end of command line, no /? found
	cmp	ax,RESULT_NO_ERROR
	je	chWhich			; valid syntax element found
	jmp	chParse			; go parse more

chWhich:
	cmp	Comnd1_Syn,offset RESGROUP:Command_?_Syn
	je	chHelp			; /? found - display help & exit
	cmp	Comnd1_Syn,offset RESGROUP:Command_C_Syn
	je	chRet			; /c found - ignore rest of line
        cmp     Comnd1_Syn,offset RESGROUP:Command_K_Syn
        je      chRet                   ; /k found - ignore rest of line
	jmp	chParse			; anything else - ignore, keep looking

chHelp:
	mov	si,offset RESGROUP:HelpMsgs	; SI = ptr to msg ptr list
chHelpNext:
	lodsw					; AX = ptr to msg
	or	ax,ax
	jz	chHelpDone			; end of list - all done
	mov	dx,ax				; DX = ptr to msg
	call	RPrint				; display msg
	jmp	chHelpNext			; go do next msg
chHelpDone:
	int	20h				; terminate program

chRet:	ret

CheckHelp	endp




;***** Setup_res_end -- This routine determines the resident size of COMMAND.
; It determines based on 2 factors:
;	1. Is this is the first COMMAND?
;	2. Is COMMAND to be loaded into HIMEM?
;   The strategy works as follows:
;
;	if ( First COMMAND)
;	then if (COMMAND in HIMEM)
;		ResSize = resident_data;
;	     else
;		ResSize = resident_data + resident_code;
;	else
;	   ResSize = resident_data;
;
; Int 2fh calls have been added to determine whether or not we are the first
;COMMAND and whether DOS is in HIMEM.
;
;	ENTRY: ResMsgEnd = resident size of data in paras
;
;	EXIT:  ResSize = resident size in low memory
;
;	REGISTERS AFFECTED: ax,cx,dx
;

GET_HMA_ADDR		equ	4a02h

Setup_res_end	proc	near
	
	push	ds
	mov	ax,cs
	mov	ds,ax				;ds = RESGROUP
	assume	ds:RESGROUP

	mov	cx,ResMsgEnd			;set resident size = data

ifndef	ROMDOS

;M042 -- Begin changes
;If messages are to be kept behind, we need to round up the messages to
;the next para boundary. This is because we have a dummy segment between the
;data and the resident code segment so that the code segment starts on a
;para boundary
;
	cmp	cx,offset RESGROUP: ExtMsgEnd	;messages to be resident?
	jne	calc_res			;no, continue
	add	cx,15				;round up
	and	cx,0fff0h
calc_res:
;
;M042 -- End changes
;
	xor	ax,ax
       	cmp	FirstCom,1			;is it first command.com?
	jnz	not_first			;no, do not keep code
;
;We issue a version check call with al=01 to detect if DOS is in HMA. If so,
;bit 4 of dh is set

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -