📄 cwswapr.asm
字号:
mov ax,0ffffh
stosb
mov cx,7
rep stosw
;
;
; Handle Redirection
;
IF REDIRECT
mov es,pspseg
mov di,lstdinsav
mov ax,-1
stosw
stosw
stosw
mov di,lstdinsav
xor cx,cx
IF ptrsize
lds si,stdin
mov ax,ds
or ax,si
ELSE
mov si,stdin
mov ds,datseg
or si,si
ENDIF
call @redirect
jc failed_redir
inc cx
IF ptrsize
lds si,stdout
mov ax,ds
or ax,si
ELSE
mov si,stdout
or si,si
ENDIF
call @redirect
jc failed_redir
inc cx
IF ptrsize
lds si,stderr
mov ax,ds
or ax,si
ELSE
mov si,stderr
or si,si
ENDIF
call @redirect
jnc redir_complete
;
failed_redir:
push ax
;
; restore handle table and pointer
;
mov ds,pspseg
mov si,lstdinsav
xor cx,cx
;
redirclose:
lodsw
cmp ax,-1
je redclosenext
mov bx,ax
mov ah,46h
int 21h
;
redclosenext:
inc cx
cmp cx,3
jb redirclose
;
mov ds,pspseg
mov es,pspseg
mov si,lhandlesave
mov di,psp_handletab
mov cx,10
rep movsw
mov di,psp_handlenum
movsw
movsw
movsw
;
; Restore overwritten part of program
;
mov ds,datseg
mov es,pspseg
mov si,offset save_dat
mov di,5ch
mov cx,savespace
rep movsb
;
pop ax
mov ah,RC_REDIRFAIL SHR 8
jmp swapout_kill
;
redir_complete:
mov ds,pspseg
mov es,pspseg
mov si,psp_handletab+5
mov di,lredirsav
mov cx,3
rep movsw
mov di,psp_handletab+5
mov cx,3
mov ax,0ffffh
rep stosw
ENDIF
;
; Prepare exec parameter block
;
mov ax,es
mov es:expar.fcb1seg,ax
mov es:expar.fcb2seg,ax
mov es:expar.pparseg,ax
mov es:expar.envseg,0
;
; The 'zero' word is located at 80h in the PSP, the start of
; the command line. So as not to confuse MCB walking programs,
; a command line length of zero is inserted here.
;
mov es:zero,0d00h ; 00h,0dh = empty command line
;
; Init default fcb's by parsing parameter string
;
; IF ptrsize
; lds si,params
; ELSE
mov si,OFFSET params
mov ds,datseg
; ENDIF
push si
mov di,xfcb1
mov es:expar.fcb1,di
push di
mov cx,16
xor ax,ax
rep stosw ; init both fcb's to 0
pop di
mov ax,2901h
int 21h
mov di,xfcb2
mov es:expar.fcb2,di
mov ax,2901h
int 21h
pop si
;
; move command tail string into low core
;
mov di,progpars
mov es:expar.ppar,di
xor cx,cx
inc di
cmdcpy:
lodsb
or al,al
jz cmdcpy_end
stosb
inc cx
jmp cmdcpy
;
cmdcpy_end:
mov al,0dh
stosb
mov es:progpars,cl
;
; move filename string into low core
;
; IF ptrsize
; lds si,execfname
; ELSE
mov si,OFFSET execfname
; ENDIF
mov di,filename
fncpy:
lodsb
stosb
or al,al
jnz fncpy
;
; Setup environment copy
;
mov bx,keep_paras ; paras to keep
; xor bx,bx
COMMENT !
mov cx,envlen ; environment size
jcxz no_environ ; go jump if no environment
cmp swapping,0
jne do_envcopy
;
; Not swapping, use the environment pointer directly.
; Note that the environment copy must be paragraph aligned.
;
IF ptrsize
mov ax,word ptr (envp)+2
mov bx,word ptr (envp)
ELSE
mov ax,ds
mov bx,envp
ENDIF
add bx,15 ; make sure it's paragraph aligned
mov cl,4
shr bx,cl ; and convert to segment addr
add ax,bx
mov es:expar.envseg,ax ; new environment segment
xor cx,cx ; mark no copy
xor bx,bx ; and no shrink
jmp short no_environ
;
; Swapping or EXECing without return. Set up the pointers for
; an environment copy (we can't do the copy yet, it might overwrite
; this code).
;
do_envcopy:
inc cx
shr cx,1 ; words to copy
mov ax,cx ; convert envsize to paras
add ax,7
shr ax,1
shr ax,1
shr ax,1
add bx,ax ; add envsize to paras to keep
IF ptrsize
lds si,envp
ELSE
mov si,envp
ENDIF
;
mov ax,es ; low core segment
add ax,keep_paras ; plus fixed paras
mov es:expar.envseg,ax ; = new environment segment
END COMMENT !
;
; Save stack regs, switch to local stack
;
no_environ:
mov es:save_ss,ss
mov es:save_sp,sp
mov ax,es
cli
mov ss,ax
mov sp,mystack
sti
;
; push cx ; save env length
; push si ; save env pointer
push ds ; save env segment
;
; save and patch INT0 (division by zero) vector
;
xor ax,ax
mov ds,ax
mov ax,word ptr ds:0
mov es:div0_off,ax
mov ax,word ptr ds:2
mov es:div0_seg,ax
mov word ptr ds:0,codebeg + iretoff
mov word ptr ds:2,es
;
pop ds ; pop environment segment
; pop si ; pop environment offset
; pop cx ; pop environment length
mov di,swapbeg ; environment destination
;
; Push return address on local stack
;
push cs ; push return segment
mov ax,offset exec_cont
push ax ; push return offset
mov es:spx,sp ; save stack pointer
;
; Goto low core code
;
push es ; push entry segment
mov ax,codebeg + doexec_entry
push ax ; push entry offset
retf
;
;----------------------------------------------------------------
;
; Low core code will return to this location, with DS set to
; the PSP segment.
;
exec_cont:
push ds
pop es
cli
mov ss,ds:save_ss ; reload stack
mov sp,ds:save_sp
sti
;
; restore handle table and pointer
;
mov si,lhandlesave
mov di,psp_handletab
mov cx,10
rep movsw
mov di,psp_handlenum
movsw
movsw
movsw
;
; restore INT0 (division by zero) vector
;
xor cx,cx
mov ds,cx
mov cx,es:div0_off
mov word ptr ds:0,cx
mov cx,es:div0_seg
mov word ptr ds:2,cx
;
mov ds,datseg
;
;
mov ax,es:eretcode
mov bx,es:retflags
;
; Restore overwritten part of program
;
mov si,offset save_dat
mov di,5ch
mov cx,savespace
rep movsb
;
; int 3
test bx,1 ; carry set?
jnz exec_fault ; return EXEC error code if fault
mov ah,4dh ; else get program return code
int 21h
xor ah,ah ; zap high value
ret
;
exec_fault:
mov ax,SWAPPERERROR
; mov ah,3 ; return error as 03xx
ret
;
do_spawn ENDP
;
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;
emm_name db 'EMMXXXX0'
;
; prep_swap - prepare for swapping.
;
; This routine checks all parameters necessary for swapping,
; and attempts to set up the swap-out area in EMS/XMS, or on file.
; In detail:
;
; 1) Check whether the do_spawn routine is located
; too low in memory, so it would get overwritten.
; If this is true, return an error code (-2).
;
; 2) Walk the memory control block chain, adding up the
; paragraphs in all blocks assigned to this process.
;
; 3) Check EMS (if the method parameter allows EMS):
; - is an EMS driver installed?
; - are sufficient EMS pages available?
; if all goes well, the EMS pages are allocated, and the
; routine returns success (1).
;
; 4) Check XMS (if the method parameter allows XMS):
; - is an XMS driver installed?
; - is a sufficient XMS block available?
; if all goes well, the XMS block is allocated, and the
; routine returns success (2).
;
; 5) Check file swap (if the method parameter allows it):
; - try to create the file
; - pre-allocate the file space needed by seeking to the end
; and writing a byte.
; If the file can be written, the routine returns success (4).
;
; 6) Return an error code (-1).
;
pmethod DW ?
;prep_swap PROC uses si di,pmethod:word,swapfname:ptr byte
prep_swap PROC FAR
LOCAL totparas: word
;
;
mov ax,fs ; ax -> wedge segment
dec ax
cmp DPMIFlag,0 ; see if using DPMI
jne isdpmi
dec ax ; CauseWay uses 1 para for its own purposes, compute MCB
isdpmi:
mov swap_prep.noswap2_mcb,ax ; don't swap out wedge segment
mov ax,PSP
mov es,ax ; es -> PSP
mov ax,es:[36h] ; es -> file handle table segment
dec ax
cmp DPMIFlag,0 ; see if using DPMI
jne isdpmi2
dec ax ; CauseWay uses 1 para for its own purposes, compute MCB
isdpmi2:
mov swap_prep.noswap3_mcb,ax ; don't swap out file handle table segment
mov ax,PSP
dec ax
mov swap_prep.psp_mcb,ax
mov swap_prep.first_mcb,ax ; init first MCB to PSP
;
; Make a copy of the environment pointer in the PSP
;
inc ax
mov es,ax
mov bx,es:psp_envptr
dec bx
mov swap_prep.env_mcb,bx
; mov swap_prep.noswap_mcb,0
; test pmethod,DONT_SWAP_ENV
; jz can_swap_env
mov swap_prep.noswap_mcb,bx
;
can_swap_env:
;
; Check if spawn is too low in memory
;
mov bx,cs
mov dx,offset lowcode_begin
mov cl,4
shr dx,cl
add bx,dx ; normalized start of this code
mov dx,keep_paras ; the end of the modified area
add dx,ax ; plus PSP = end paragraph
cmp bx,dx
ja prepswap_ok ; ok if start of code > end of low mem
mov ax,-2
mov swap_prep.swapmethod,al
ret
;
; Walk the chain of memory blocks, adding up the paragraphs
; in all blocks belonging to this process.
; We try to find the first MCB by getting DOS's "list of lists",
; and fetching the word at offset -2 of the returned address.
; If this fails, we use our PSP as the starting point.
;
prepswap_ok:
xor bx,bx
mov es,bx
mov ah,52h ; get list of lists
int 21h
mov ax,es
or ax,bx
jz prep_no_first
mov es,es:[bx-2] ; first MCB
cmp es:id,4dh ; normal ID?
jne prep_no_first
mov swap_prep.first_mcb,es
;
prep_no_first:
mov es,swap_prep.psp_mcb ; ES points to base MCB
mov cx,es ; save this value
mov bx,es:owner ; the current process
mov dx,es:paras ; memory size in the base block
sub dx,keep_paras ; minus resident paragraphs
mov si,0 ; number of MCBs except base
mov di,swap_prep.noswap_mcb
mov bp,swap_prep.noswap2_mcb
mov ax,swap_prep.first_mcb
mov swap_prep.first_mcb,0
;
prep_mcb_walk:
mov es,ax
cmp ax,cx ; base block?
jbe prep_walk_next ; then don't count again
cmp ax,di ; Non-swap MCB?
je prep_walk_next ; then don't count
cmp ax,bp ; Non-swap MCB?
je prep_walk_next ; then don't count
cmp ax,swap_prep.noswap3_mcb ; non-swap MCB
je prep_walk_next ; then don't count
;
cmp bx,es:owner ; our process?
jne prep_walk_next ; next if not
inc si
mov ax,es:paras ; else get number of paragraphs
add ax,2 ; + 1 for descriptor + 1 for MCB
add dx,ax ; total number of paras
cmp swap_prep.first_mcb,0
jne prep_walk_next
mov swap_prep.first_mcb,es
;
prep_walk_next:
cmp es:id,4dh ; normal block?
jne prep_mcb_ready ; ready if end of chain
mov ax,es
add ax,es:paras ; start + length
inc ax ; next MCB
jmp prep_mcb_walk
;
prep_mcb_ready:
mov totparas,dx
mov swap_prep.total_mcbs,si
;
;
test pmethod,XMS_FIRST
jnz check_xms
;
; Check for EMS swap
;
check_ems:
test pmethod,USE_EMS
jz prep_no_ems
;
push ds
mov al,EMM_INT
mov ah,35h
int 21h ; get EMM int vector
mov ax,cs
mov ds,ax
mov si,offset emm_name
mov di,10
mov cx,8
repz cmpsb ; EMM name present?
pop ds
jnz prep_no_ems
;
mov ah,40h ; get EMS status
int EMM_INT
or ah,ah ; EMS ok?
jnz prep_no_ems
;
mov ah,46h ; get EMS version
int EMM_INT
or ah,ah ; AH must be 0
jnz prep_no_ems
;
cmp al,30h ; >= version 3.0?
jb prep_no_ems
;
mov ah,41h ; Get page frame address
int EMM_INT
or ah,ah
jnz prep_no_ems
;
; EMS present, try to allocate pages
;
mov swap_prep.ems_pageframe,bx
mov bx,totparas
add bx,ems_paramask
mov cl,ems_shift
shr bx,cl
mov ah,43h ; allocate handle and pages
int EMM_INT
or ah,ah ; success?
jnz prep_no_ems
;
; EMS pages allocated, swap to EMS
;
mov swap_prep.handle,dx
mov ax,USE_EMS
mov swap_prep.swapmethod,al
ret
;
; No EMS allowed, or EMS not present/full. Try XMS.
;
prep_no_ems:
test pmethod,XMS_FIRST
jnz check_file ; don't try again
;
check_xms:
test pmethod,USE_XMS
jz prep_no_xms
;
mov ax,4300h ; check if XMM driver present
int 2fh
cmp al,80h ; is XMM installed?
jne prep_no_xms
mov ax,4310h ; get XMM entrypoint
int 2fh
mov word ptr swap_prep.xmm,bx ; save entry address
mov word ptr swap_prep.xmm+2,es
;
mov dx,totparas
add dx,xms_paramask ; round to nearest multiple of 1k
mov cl,xms_shift
shr dx,cl ; convert to k
mov ah,9 ; allocate extended memory block
call swap_prep.xmm
or ax,ax
jz prep_no_xms
;
; XMS block allocated, swap to XMS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -