📄 cwswapr.asm
字号:
ret
;
swapout_xms endp
;
;
; swapout_file: swap out an MCB block to file.
;
; Entry: "currdesc" contains description of block to swap
; "nextmcb" contains MCB-descriptor of next block
; if currdesc.num_follow is nonzero
;
; Exit: 0 if OK, -1 if error, Zero-flag set accordingly.
;
; Uses: All regs excpt DS
;
swapout_file proc near
;
push ds
mov cx,currdesc.swsize ; size in paragraphs
mov bx,swap_prep.handle ; file handle
mov dx,currdesc.swoffset ; swap offset
mov ds,currdesc.addr ; segment to swap
;
swfile_loop:
mov ax,cx
cmp ah,8h ; above 32k?
jbe swfile_ok ; go write if not
mov ax,800h ; else write 32k
;
swfile_ok:
sub cx,ax ; remaining length
push cx ; save it
push ax ; and save paras to write
mov cl,4
shl ax,cl ; convert to bytes
mov cx,ax
mov ah,40h ; write
int 21h
jc swfile_error
cmp ax,cx
jne swfile_error
pop cx ; paras written
mov ax,ds
add ax,cx ; bump up source segment
mov ds,ax
pop cx ; remaining length
or cx,cx ; anything left?
jnz swfile_loop ; go loop if yes
;
pop ds
cmp currdesc.num_follow,0 ; another MCB?
je swfile_complete ; ready if not
mov cx,16 ; write one paragraph
mov dx,offset nextmcb
mov ah,40h
int 21h
jc swfile_error1
cmp ax,cx
jne swfile_error1
;
swfile_complete:
xor ax,ax
ret
;
swfile_error:
pop cx
pop cx
pop ds
swfile_error1:
mov ah,3eh ; close file
int 21h
mov dx,offset swap_prep.sp_swapfilename
mov ah,41h ; delete file
int 21h
mov ax,RC_SWAPERROR
or ax,ax
ret
;
swapout_file endp
;
;--------------------------------------------------------------------------
;
IF REDIRECT
;
; @redirect: Redirect a file.
;
; Entry: DS:SI = Filename pointer
; AX zero if filename is NULL
; CX = Handle to redirect
; ES:DI = Handle save pointer
;
; Exit: Carry set on error, then AL has DOS error code
; ES:DI updated
;
; Uses: AX,BX,DX,SI
;
@redirect proc near
local doserr:WORD
;
or ax,ax
jz no_redirect
cmp byte ptr [si],0
jne do_redirect
;
no_redirect:
mov ax,-1
stosw
ret
;
do_redirect:
or cx,cx
jnz redir_write
mov dx,si
mov ax,3d00h ; open file, read only
int 21h
mov doserr,ax
jc redir_failed
;
redir_ok:
mov dx,ax
mov ah,45h ; duplicate handle
mov bx,cx
int 21h
mov doserr,ax
jc redir_failed_dup
push ax
mov bx,dx
mov ah,46h ; force duplicate handle
int 21h
mov doserr,ax
pop ax
jc redir_failed_force
stosw
mov ah,3eh ; close file
int 21h
clc
ret
;
redir_failed_force:
mov bx,ax
mov ah,3eh ; close file
int 21h
;
redir_failed_dup:
mov bx,dx
mov ah,3eh ; close file
int 21h
;
redir_failed:
mov ax,doserr
stc
ret
;
redir_write:
cmp byte ptr [si],'>'
jne no_append
inc si
mov dx,si
mov ax,3d02h ; open file, read/write
int 21h
jc no_append
mov bx,ax
push cx
mov ax,4202h ; move file, offset from EOF
xor cx,cx
mov dx,cx
int 21h
mov doserr,ax
pop cx
mov ax,bx
jnc redir_ok
mov dx,ax
jmp redir_failed_dup
;
no_append:
mov dx,si
mov ah,3ch
push cx
xor cx,cx
int 21h
mov doserr,ax
pop cx
jc redir_failed
jmp redir_ok
;
@redirect endp
;
ENDIF
;
;--------------------------------------------------------------------------
;
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
;
;
;do_spawn PROC uses si di,swapping: word, execfname:ptr byte,params:ptr byte,envlen:word,envp:ptr byte,stdin:ptr byte, stdout:ptr byte, stderr:ptr byte
; execfname DB "C:\DOS\COMMAND.COM",81 DUP (0)
; params DB 2,"/C",0dh,81 DUP (0)
swapping DW ?
datseg DW ?
pspseg DW ?
currmcb DW ?
execfname DB "C:\COMMAND.COM",82 DUP (0)
; params DB "/C C:\DOS\MEM.EXE",129 DUP (0)
params DB 129 DUP (0)
PSP DW ? ; real mode PSP
PSPEnvironPtr DW ? ; real mode PSP Environment Pointer
PMPSP DW ? ; protected mode PSP
DPMIFlag DB ? ; nonzero if DPMI
do_spawn PROC FAR
; local datseg:WORD,pspseg:WORD,currmcb:WORD
;
;
mov datseg,ds ; save default DS
;
;
mov bx,PSP
mov pspseg,bx
;
; Check if spawn is too low in memory
;
mov ax,cs
mov dx,offset lowcode_begin
mov cl,4
shr dx,cl
add ax,dx ; normalized start of this code
mov dx,keep_paras ; the end of the modified area
add dx,bx ; plus PSP = end paragraph
cmp ax,dx
ja doswap_ok ; ok if start of code > end of low mem
mov ax,RC_TOOLOW
ret
;
doswap_ok:
cmp swapping,0
jle method_ok
;
; check the swap method, to make sure prep_swap has been called
;
mov al,swap_prep.swapmethod
cmp al,USE_EMS
je method_ok
cmp al,USE_XMS
je method_ok
cmp al,USE_FILE
je method_ok
mov ax,RC_BADPREP
ret
;
; Save the memory below the swap space.
; We must do this before swapping, so the saved memory is
; in the swapped out image.
; Anything else we'd want to save on the stack or anywhere
; else in "normal" memory also has to be saved here, any
; modifications done to memory after the swap will be lost.
;
; Note that the memory save is done even when not swapping,
; because we use some of the variables in low core for
; simplicity.
;
method_ok:
mov es,datseg
mov ds,pspseg ; DS points to PSP
mov si,5ch
mov di,offset save_dat
mov cx,savespace / 2 ; NOTE: savespace is always even
rep movsw
;
mov ds,datseg
;
mov ax,swapping
cmp ax,0
jg begin_swap
;
; not swapping, prep_swap wasn't called. Init those variables in
; the 'swap_prep' block we need in any case.
;
mov swap_prep.swapmethod,al
je no_reduce
;
mov ax,pspseg
dec ax
mov swap_prep.psp_mcb,ax
mov swap_prep.first_mcb,ax
inc ax
mov es,ax
mov bx,es:psp_envptr
mov swap_prep.env_mcb,bx
; mov swap_prep.noswap_mcb,0
; cmp envlen,0
; jne swp_can_swap_env
mov swap_prep.noswap_mcb,bx
;
swp_can_swap_env:
xor bx,bx
mov es,bx
mov ah,52h ; get list of lists
int 21h
mov ax,es
or ax,bx
jz no_reduce
mov es,es:[bx-2] ; first MCB
cmp es:id,4dh ; normal ID?
jne no_reduce
mov swap_prep.first_mcb,es
;
no_reduce:
jmp no_swap1
;
; set up first block descriptor
;
begin_swap:
mov ax,swap_prep.first_mcb
mov currmcb,ax
mov es,swap_prep.psp_mcb ; let ES point to base MCB
mov ax,es:paras
mov currdesc.msize,ax
sub ax,keep_paras
mov currdesc.swsize,ax
mov currdesc.addr,es
mov currdesc.swoffset,swapbeg + 16
; NOTE: swapbeg is 1 para higher when seen from MCB
mov ax,swap_prep.total_mcbs
mov currdesc.num_follow,ax
;
; init other vars
;
mov xmsctl.destlo,0
mov xmsctl.desthi,0
mov ems_curpage,0
mov ems_curoff,ems_parasize
;
; Do the swapping. Each MCB block (except the last) has an
; "mcbdesc" structure appended that gives location and size
; of the next MCB.
;
swapout_main:
cmp currdesc.num_follow,0 ; next block?
je swapout_no_next ; ok if not
;
; There is another MCB block to be saved. So we don't have
; to do two calls to the save routine with complicated
; parameters, we set up the next MCB descriptor beforehand.
; Walk the MCB chain starting at the current MCB to find
; the next one belonging to this process.
;
mov ax,currmcb
mov bx,pspseg
mov cx,swap_prep.psp_mcb
mov dx,swap_prep.noswap_mcb
mov si,swap_prep.noswap2_mcb
;
swm_mcb_walk:
mov es,ax
cmp ax,cx
jbe swm_next_mcb
cmp ax,dx
je swm_next_mcb
cmp ax,si
je swm_next_mcb
cmp ax,swap_prep.noswap3_mcb
je swm_next_mcb
;
cmp bx,es:owner ; our process?
je swm_mcb_found ; found it if yes
;
swm_next_mcb:
cmp es:id,4dh ; normal block?
jne swm_mcb_error ; error if end of chain
add ax,es:paras ; start + length
inc ax ; next MCB
jmp swm_mcb_walk
;
; MCB found, set up an mcbdesc in the "nextmcb" structure
;
swm_mcb_found:
mov nextmcb.addr,es
mov ax,es:paras ; get number of paragraphs
mov nextmcb.msize,ax ; and save
inc ax
mov nextmcb.swsize,ax
mov bx,es
add bx,ax
mov currmcb,bx
mov nextmcb.swoffset,0
mov ax,currdesc.num_follow
dec ax
mov nextmcb.num_follow,ax
;
swapout_no_next:
cmp swap_prep.swapmethod,USE_EMS
je swm_ems
cmp swap_prep.swapmethod,USE_XMS
je swm_xms
call swapout_file
jmp short swm_next
;
swm_ems:
call swapout_ems
jmp short swm_next
;
swm_xms:
call swapout_xms
;
swm_next:
jnz swapout_error
cmp currdesc.num_follow,0
je swapout_complete
;
; next MCB exists, copy the "nextmcb" descriptor into
; currdesc, and loop.
;
mov es,datseg
mov si,offset nextmcb
mov di,offset currdesc
mov cx,TYPE mcbdesc
rep movsb
jmp swapout_main
;
;
swm_mcb_error:
mov ax,RC_MCBERROR
;
swapout_kill:
cmp swapping,0
jl swapout_error
push ax
cmp swap_prep.swapmethod,USE_FILE
je swm_mcberr_file
cmp swap_prep.swapmethod,USE_EMS
je swm_mcberr_ems
;
mov ah,0ah ; release XMS frame on error
mov dx,swap_prep.handle ; XMS handle
call swap_prep.xmm
pop ax
jmp short swapout_error
;
swm_mcberr_ems:
mov dx,swap_prep.handle ; EMS handle
mov ah,45h ; release EMS pages on error
int EMM_INT
pop ax
jmp short swapout_error
;
swm_mcberr_file:
mov bx,swap_prep.handle
cmp bx,-1
je swm_noclose
mov ah,3eh ; close file
int 21h
swm_noclose:
mov dx,offset swap_prep.sp_swapfilename
mov ah,41h ; delete file
int 21h
pop ax
;
swapout_error:
ret
;
;
; Swapout complete. Close the handle (EMS/file only),
; then set up low memory.
;
swapout_complete:
cmp swap_prep.swapmethod,USE_FILE
jne swoc_nofile
;
; File swap: Close the swap file to make the handle available
;
mov bx,swap_prep.handle
mov swap_prep.handle,-1
mov ah,3eh
int 21h ; close file
mov si,offset swapin_file
jnc swoc_ready
mov ax,RC_SWAPERROR
jmp swapout_kill
;
swoc_nofile:
cmp swap_prep.swapmethod,USE_EMS
jne swoc_xms
;
; EMS: Unmap page
;
mov ax,4400h
mov bx,-1
mov dx,swap_prep.handle
int EMM_INT
mov si,offset swapin_ems
jmp short swoc_ready
;
swoc_xms:
mov si,offset swapin_xms
jmp short swoc_ready
;
no_swap1:
mov si,offset swapin_none
;
; Copy the appropriate swap-in routine to low memory.
;
swoc_ready:
mov es,pspseg
mov cx,swap_codelen / 4
mov di,codebeg + base_length
push ds
mov ax,cs
mov ds,ax
rep movsd
;
; And while we're at it, copy the MCB allocation routine (which
; also includes the initial MCB release and exec call) down.
;
mov cx,base_length / 2
mov di,param_len
mov si,offset lowcode_begin
rep movsw
;
pop ds
mov bx,es
dec bx
mov es,bx ; let ES point to base MCB
;
; Again set up the base MCB descriptor, and copy it as well as
; the variables set up by prep_swap to low memory.
; This isn't too useful if we're not swapping, but it doesn't
; hurt, either. The only variable used when not swapping is
; lprep.swapmethod.
;
mov ax,es:paras
mov currdesc.msize,ax
sub ax,keep_paras
mov currdesc.swsize,ax
mov currdesc.addr,es
mov currdesc.swoffset,swapbeg + 16
mov ax,swap_prep.total_mcbs
mov currdesc.num_follow,ax
;
mov es,pspseg ; ES points to PSP again
;
mov cx,TYPE prep_block
mov si,offset swap_prep
mov di,lprep
rep movsb
mov cx,TYPE mcbdesc
mov si,offset currdesc
mov di,lcurrdesc
rep movsb
;
; now set up other variables in low core
;
mov ds,pspseg
mov ds:cgetmcb,getmcboff + codebeg
mov ds:eretcode,0
mov ds:retflags,0
;
;
; If 'NO_INHERIT' is nonzero, save the entries of the
; handle table, and set the last 15 to 0ffh (unused).
;
mov si,psp_handletab
mov di,lhandlesave
mov cx,10
rep movsw
mov si,psp_handlenum ; Length of handle table
mov ax,[si]
stosw
mov word ptr [si],20 ; set to default to be safe
add si,2
lodsw ; Handle table pointer
mov bx,ax
stosw
lodsw
stosw
cmp ax,pspseg
jne copy_handles
cmp bx,psp_handletab
je no_handlecopy
;
; if the handle table pointer in the PSP does not point to
; the default PSP location, copy the first five entries from
; this table into the PSP - but only if we have DOS >= 3.3.
;
copy_handles:
mov ds,ax
mov si,bx
mov di,psp_handletab
mov es:psp_handleptro,di
mov es:psp_handleptrs,es
movsw
movsw
movsb
;
no_handlecopy:
mov di,psp_handletab+5
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -