📄 cstart.asm
字号:
cmp exec_filetype,0 ; was it a CMD
jne exec30
push ax
mov ax,XIOS_PCKBD ; we are in must-be-24 line
mov cl,0 ; mode, get back to default mode
mov dl,defconsole ; for console number
call xios
pop ax
exec30:
pop di
pop si
pop bp
ret
_TEXT ENDS
Assume CS:DGROUP, DS:DGROUP, SS:DGROUP
else
;
; Novell 2.1 intercepts the DOSPLUS 4B00 return by updating the
; PSP USER_SS/SP and when it returns ALL registers except CS:IP
; have been corrupted.
;
extrn stack_min:word ; Minimum Stack Address
extrn heap_top:word
readline label dword ; FAR pointer to READLINE routine
dw dataOFFSET msdos_readline
readline_seg dw ?
critical dd ? ; Critical Error Handler Address
exec_sp dw ?
exec_ss dw ?
exec_block label byte
exec_env dw ? ; Environment Segment
exec_clineoff dw ? ; ASCIIZ Command line Offset
exec_clineseg dw ? ; ASCIIZ Command Line Segment
exec_fcb1off dw dataOFFSET fcb1 ; FCB1 Contents Offset
exec_fcb1seg dw ? ; FCB1 Contents Segment
exec_fcb2off dw dataOFFSET fcb2 ; FCB2 Contents Offset
exec_fcb2seg dw ? ; FCB2 Contents Segment
exec label dword ; FAR pointer to EXEC routine
dw dataOFFSET msdos_exec
exec_seg dw ?
msdos_exec_ret label dword ; FAR pointer to exit EXEC routine
dw codeOFFSET _exec_ret
msdos_exec_ret_seg dw ?
fcb1 db 16 dup (?) ; FCB1 Buffer
fcb2 db 16 dup (?) ; FCB2 Buffer
crc dw ? ; COMMAND.COM crc
; For Dual Language Support...
ifdef DLS
;;ED_TEXT SEGMENT para public 'CDATA'
Public _rld_msgs,_rld_text
_rld_msgs dw 120 ;RELOAD_LEN ; size of this message buffer
_reload_msgs dw 0 ; First part of Code reload prompt
_reload_msgf dw 0 ; Second part of Code reload prompt
_reload_msgm dw 0 ; Unlikely part of Code reload prompt
dw 0 ; end of list
_rld_text db 120 dup (?) ; message text is placed here
RELOAD_LEN equ $-_reload_msgs
;;ED_TEXT ENDS
else
extrn _reload_msgs:byte ; First part of Code reload prompt
extrn _reload_msgf:byte ; Second part of Code reload prompt
extrn _reload_msgm:byte ; No memory available message
endif
reload_flag db 0 ; Reloading Command Processor
in_exec db 0
high_code dw TRUE ; Enable High Code
exe_file dw FALSE ; True if COMMAND.COM is really an EXE
return_code dw ? ; Exec return code
net_error_mode db ?
; int2E data
i2e_lock dw 0 ; mutex flag
i2e_user_ss dw 0 ; users ss, sp
i2e_user_sp dw 0
i2e_stack dw 0
i2e_cmd dw 0 ; offset of local copy of command line
i2e_c_entry label dword
i2e_c_offs dw codeOFFSET _int2e_handler
i2e_c_seg dw ?
i2e_i23vec label dword
i2e_i23off dw ?
i2e_i23seg dw ?
i2e_i24vec label dword
i2e_i24off dw ?
i2e_i24seg dw ?
endif
_DATA ENDS
_BSS SEGMENT
Public _edata
_edata label BYTE ; end of data (start of bss)
_BSS ENDS
ETEXT SEGMENT
;
; The RLSTACK segment holds the stack used by the READLINE routine.
; This must be in High memory for the PolyTron PolyWindows product.
;
; "ETEXT" also forces the linker to pad the CGROUP to at least
; real_code bytes. Otherwise the file length can be upto 15 bytes
; shorter then real_code + total_length. This obviously causes
; problems with CALC_CRC and the file reloading.
;
db RLSTACK_SIZE dup(0CCh)
rlstack label word
ETEXT ENDS
ifdef CDOSTMP
STACK SEGMENT
Public _end
_end label BYTE ; end of bss (start of starup/stack)
db (C_HEAP_SIZE - 6) dup (0DDh) ; C Heap Area
stack_top label word
stack_ip dw ? ; Initial Offset
stack_cs dw ? ; Initial Code Segment (Unknown)
stack_flags dw ? ; Initial Flags (Unknown)
temp_buffer db 512 dup(0) ; temp far buffer for *gp_far_buff
STACK ENDS
else
STACK SEGMENT
stack_start:
; HEAP_TOP is initialised to _end so the _RELOAD_FILE and CMDLINE
; variables are allocated on the HEAP.
;
Public _end
_end label BYTE ; end of bss (start of startup/stack)
db 255,'3771146-XXXX-654321'
page
;
; The CS register is now adjusted so that this startup
; can be used in the form of an .EXE or .COM. Whatever the
; execution format of this file DS still points at the PSP
; but must be careful when resizing the RAM.
;
getIP PROC FAR
cld ; be sure of DIR flag...
pop di ; Get the Program Counter
sub di,dataOFFSET retIP ; Correct for retIP
mov cl,4 ; Convert Offset values to Segments
mov ax,cs ; Get the current CS
shr di,cl ; Convert Initial IP to Segment
add ax,di ; add to CS and save for CALLF to MAIN
push ax ; Save the New CS and the offset to
mov ax,dataOFFSET gotCS ; the next instruction and then execute
push ax
ret ; a RETF instruction to correct CS.
getIP ENDP
ifdef DOSPLUS
; Most of the PSP (FCB's and command buffer) is unused - we reclaim this space
; by relocating the resident part of COMMAND.COM
reloc_code:
;----------
; On Entry:
; CS = DGROUP, DS = PSP, ES = nothing
; On Exit:
; CS = relocated DGROUP
;
; We build a "REP MOVSB ! RETF 6" on the stack. We also fiddle the near return
; address into a FAR. We then setup our registers appropriately and execute
; this code.
;
if 1
ret
else
cmp ds:byte ptr 0080h,7fh ; discard garbage cmdline lengths
jb reloc_code10
ret
reloc_code10:
pop bx ; recover return offset
mov ax,0
push ax ; 0 (part of RETF 6)
mov ax,006cah
push ax ; RETF 6 on stack
mov ax,0a4f3h
push ax ; REP MOVSB on stack
mov al,ds:0080h ; Get the Command length
xor ah,ah
mov cl,4 ; convert AX to cmdline length
shr ax,cl ; in rounded down para's
add ax,9 ; keep at least this much
mov si,ds
add ax,si ; add in PSP
mov es,ax
mov cx,sp ; save address of code on stack
push ax
push bx ; new RETF address on stack
push ss
push cx ; address of CODE on stack
push cs
pop ds ; DS -> DGROUP
xor si,si ; setup DS:SI, ES:DI and CX
xor di,di ; ready to do REP MOVSB
mov cx,total_length ; DGROUP length
add cx,real_code ;+CGROUP length
db 0cbh ; RETF to code on stack
endif
endif
gotCS:
;out 0fdh,al ; for debug purposes
mov [__psp],ds ; Save our PSP in the local variable
ifdef DOSPLUS
mov ax,cs ; put our stack somewhere safe
mov ss,ax
mov sp,dataOFFSET rlstack
push ds
push di
call reloc_code ; relocate code over unused bit of PSP
pop di
pop ds
endif
ifdef DLS
call _my_dls_init
endif
mov [code_seg],cs ; Initialise the DATA segment address
mov [data_seg],cs ; and calculate the current address
mov [exec_seg],cs ; of the Code Segment
mov [readline_seg],cs ; use it to fixup some JMPFs
mov [_batch_seg_ptr+2],cs
mov [low_seg],cs ; we may be relocated to upper or high
; memory so remember the current segment
mov bx,cs ; Path up the JMPF instructions
sub bx,[__psp] ; around the MSDOS EXEC code to
mov cl,4
shl bx,cl
add cs:[exec_psp-2],bx
mov cs:[func4b_seg],cs
mov cs:[int2E_seg],cs
mov cs:[exec_psp],ds
cmp di,0000h ; Disable Code Relocation if we have
jnz gotCS_10 ; been loaded as an .EXE file
;;mov high_code,FALSE
mov exe_file,TRUE ; Remember we are an EXE
gotCS_10:
mov di,total_length
shr di,cl
add [code_seg],di
push ds ; Initialise the Checksum so we can
mov ds,[code_seg] ; check the integrity of the high
mov si,2 ; high copy of the command processor
call calc_crc ; code
pop ds
mov [crc],ax
mov ah,0ddh ; set Novell error mode
mov dl,0 ; to 00 - BAP
int 21h
mov net_error_mode,al ; save original error mode
call get_ds ; Get DGROUP value in AX
cli ; turn off interrupts
mov ss,ax ; SS = DGROUP
mov sp,dynamic_length ; Initialise SP
;mov sp,total_length
sti ; turn interrupts back on
assume ss:DGROUP
push ax
call handler_init ; Initialise the Control Break and
pop ax ; Critical Error Interrupt Vectors
mov si,total_length ; Get the DGROUP length in bytes
add si,code_length ; Add in the Code Length
mov cl,4 ; and convert to a paragraphs
shr si,cl
mov bx,ax ; Get the Current DS
sub bx,__psp ; and calculate DS - PSP Seg
add bx,si ; DS + Data length in Para's
mov es,__psp
mov ah,MS_M_SETBLOCK
int DOS_INT
call exec_name ; Get our Load Path from the environment
cmp high_code,FALSE ; Skip Memory check if HIGH_CODE
jz cstart_10 ; support has been disabled
mov high_code,FALSE ; Assume Failure.
call alloc_com_memory ; Allocate high memory for command.com
jnc carry_on
mov ax,cs ; if no memory and CS is nearing
cmp ax,8000h ; transient part abort and go home.
jb cstart_10
mov ah,4ch
int 21h
carry_on:
mov high_code,TRUE ; Set HIGH_CODE flag TRUE
push es ; Relocate the command processor code
push ds ; into high memory
mov es,ax ; es-> destination segment
mov di,0
mov si,0
mov ds,code_seg ; ds-> code to be moved
mov cx,real_code ; convert bytes to words
shr cx,1
rep movsw ; Move code up to high memory
mov code_seg,es ; update code_seg
pop ds
pop es
; Shrink memory containing low memory version of step aside code
mov si,total_length ; Get the DGROUP length in bytes
mov cl,4 ; and convert to a paragraphs
shr si,cl
call get_ds
mov bx,ax ; Get the Current DS
sub bx,__psp ; and calculate DS - PSP Seg
add bx,si ; DS + Data length in Para's
mov ah,MS_M_SETBLOCK
int DOS_INT
cstart_10:
ifdef DOSPLUS
mov ax,4457h ; terminate HILOAD operation
mov dx,200h
int DOS_INT
call dbcs_init ; initialise the DBCS support
endif
call get_cs
push ax
mov ax,codeOFFSET memory_init
push ax
db 0CBh ; a RETF instruction to correct CS.
page
;
; Build the full path and filename of this process using the
; loadpath attached to the environment. If no filename exists
; then prevent the Command Processor code from being located
; in high memory.
;
exec_name:
push es
mov es,__psp ; Get the PSP Segment Address
mov dx,PSP_ENVIRON ; Get the environment segment
cmp dx,0000 ; Have we got an environment ?
jz exec_n11 ; No prevent High Code Support
mov es,dx ; Scan through the environment and
mov di,0 ; determine the Environment size and
mov al,0 ; the Load file name
mov cx,7FFFh
exec_n05: ; Scan through the Environment
repne scasb ; searching for the 00 00 terminator
jcxz exec_n10 ; Terminate On CX == 0000
cmp es:byte ptr [di],al ; If the next byte is zero then this is
jnz exec_n05 ; then end of the environment
cmp es:word ptr 1[di],1 ; Are we pointing at the Control Word
jnz exec_n10 ; No then no Load Path exists
push ds
mov ds,dx ; DS -> Environment Segment
;call get_ds
;mov es,ax ; ES -> Command Processor Data Seg
mov es,[low_seg]
lea si,03[di] ; Fully expand the filename so the
mov di,dataOFFSET reload_file ; user can SUBST drives
mov ah,60h
int DOS_INT
exec_n15:
if 0
mov di,dataOFFSET reload_file ; this ASCIIZ string is on the heap
xor ax,ax ; so now we need to find out how
mov cx,-1 ; much space it takes up and reserve
repne scasb ; that amount of the heap
mov heap_top,di ; byte after the NUL is available
endif
pop ds
pop es
ret
exec_n10:
mov high_code,FALSE
exec_n11:
mov ah,MS_DRV_GET
int DOS_INT ; get default drive
mov es,[low_seg]
add es:reload_file,al ; and use that for the comspec
push ds
;call get_ds
;mov es,ax ; ES -> Command Processor Data Seg
jmp exec_n15
ifdef DOSPLUS
DI_BUF_PTR equ dword ptr -4 ; pointer to DBCS lead byte table
DI_BUF_ID equ byte ptr -5 ; buffer id
DI_BUF equ byte ptr -5 ; buffer
DI_LOCALS equ 5 ; No. bytes storage local to init_dbcs
_DATA SEGMENT byte public 'DATA'
Public dbcs_table_ptr
dbcs_table_ptr label dword
dbcs_table_off dw dataOFFSET dummy_dbcs_table
dbcs_table_seg dw 0
dummy_dbcs_table dw 0
_DATA ENDS
dbcs_init proc near
;--------
; To initialise the double byte character set (DBCS) lead byte table.
; MUST be called before the first call to dbcs_lead() or dbcs_expected().
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -