📄 init.asm
字号:
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 + -