📄 msspawn.asm
字号:
swinxms_main:
mov ax,lmem lcurrdesc.swsize ; size in paragraphs
mov cl,4
rol ax,cl ; size in bytes + high nibble
mov dx,ax
and ax,0fff0h ; low word
and dx,0000fh ; high word
mov lmem lxmsctl.lenlo,ax ; into control block
mov lmem lxmsctl.lenhi,dx
mov ax,lmem lcurrdesc.swoffset ; swap offset
mov lmem lxmsctl.destlo,ax ; into control block
mov ax,lmem lcurrdesc.addr ; segment to swap
mov lmem lxmsctl.desthi,ax
mov si,lxmsctl
mov ah,0bh
call lmem lprep.xmm ; move it
or ax,ax
jz swinxms_error
mov ax,lmem lxmsctl.lenlo ; adjust source addr
add lmem lxmsctl.srclo,ax
mov ax,lmem lxmsctl.lenhi
adc lmem lxmsctl.srchi,ax
;
cmp lmem lcurrdesc.num_follow,0 ; another MCB?
je swinxms_complete
;
mov lmem lxmsctl.lenlo,TYPE mcbdesc
mov lmem lxmsctl.lenhi,0
mov lmem lxmsctl.desthi,ds
mov lmem lxmsctl.destlo,lcurrdesc
mov si,lxmsctl
mov ah,0bh
call lmem lprep.xmm ; move it
or ax,ax
jz swinxms_error
add lmem lxmsctl.srclo,16 ; one paragraph
adc lmem lxmsctl.srchi,0
;
call lmem cgetmcb
jc swinxms_error
jmp swinxms_main
;
swinxms_complete:
mov ah,0ah ; release XMS frame
mov dx,lmem lprep.handle ; XMS handle
call lmem lprep.xmm
ret
;
swinxms_error:
mov ah,0ah ; release XMS frame on error
call lmem lprep.xmm
mov ax,4c00h
int 21h
;
swapin_xms endp
;
swinxms_length = offset $ - offset swapin_xms
;
;
; swapin_file: swap in from file.
;
swapin_file proc far
;
mov dx,lprep.swapfilename
mov ax,3d00h ; open file
int 21h
jc swinfile_error2
mov bx,ax ; file handle
;
swinfile_main:
push ds
mov cx,lmem lcurrdesc.swsize ; size in paragraphs
mov dx,lmem lcurrdesc.swoffset ; swap offset
mov ds,lmem lcurrdesc.addr ; segment to swap
;
swinfile_loop:
mov ax,cx
cmp ah,8h ; above 32k?
jbe swinfile_ok ; go read if not
mov ax,800h ; else read 32k
;
swinfile_ok:
sub cx,ax ; remaining length
push cx ; save it
push ax ; and save paras to read
mov cl,4
shl ax,cl ; convert to bytes
mov cx,ax
mov ah,3fh ; read
int 21h
jc swinfile_error
cmp ax,cx
jne swinfile_error
pop cx ; paras read
mov ax,ds
add ax,cx ; bump up dest segment
mov ds,ax
pop cx ; remaining length
or cx,cx ; anything left?
jnz swinfile_loop ; go loop if yes
;
pop ds
cmp lmem lcurrdesc.num_follow,0 ; another MCB?
je swinfile_complete ; ready if not
mov cx,16 ; read one paragraph
mov dx,lcurrdesc
mov ah,3fh
int 21h
jc swinfile_error1
cmp ax,cx
jne swinfile_error1
;
push bx
call lmem cgetmcb
pop bx
jc swinfile_error1
jmp swinfile_main
;
;
swinfile_complete:
mov ah,3eh ; close file
int 21h
mov dx,lprep.swapfilename
mov ah,41h ; delete file
int 21h
ret
;
swinfile_error:
pop cx
pop cx
pop ds
swinfile_error1:
mov ah,3eh ; close file
int 21h
swinfile_error2:
mov dx,lprep.swapfilename
mov ah,41h ; delete file
int 21h
mov ax,4cffh
int 21h
;
swapin_file endp
;
swinfile_length = offset $ - offset swapin_file
;
;
; swapin_none: no swap, return immediately.
;
swapin_none proc far
;
ret
;
swapin_none endp
;
;
IF swinems_length GT swinxms_length
swcodelen = swinems_length
ELSE
swcodelen = swinxms_length
ENDIF
IF swinfile_length GT swcodelen
swcodelen = swinfile_length
ENDIF
;
swap_codelen = ((swcodelen + 1) / 2) * 2
;
codelen = base_length + swap_codelen
reslen = codebeg + codelen
keep_paras = (reslen + 15) shr 4 ; paragraphs to keep
swapbeg = keep_paras shl 4 ; start of swap space
savespace = swapbeg - 5ch ; length of overwritten area
;
;--------------------------------------------------------------------
;
.data?
;
;
; Space for saving the part of the memory image below the
; swap area that is overwritten by our code.
;
save_dat db savespace dup(?)
;
; Variables used while swapping out.
; The "prep" structure is initialized by prep_swap.
;
prep prep_block <>
nextmcb mcbdesc <>
currdesc mcbdesc <>
xmsctl xms_control <>
ems_curpage dw ? ; current EMS page number
ems_curoff dw ? ; current EMS offset (paragraph)
;
;--------------------------------------------------------------------
;
.code
;
; swapout_ems: swap out an MCB block to EMS.
;
; 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, != 0 if error, Zero-flag set accordingly.
;
; Uses: All regs excpt DS
;
swapout_ems proc near
;
push ds
mov cx,currdesc.swsize ; block length in paras
mov si,currdesc.swoffset ; swap offset
mov dx,prep.handle ; EMS handle
mov bx,ems_curpage ; current EMS page
mov di,ems_curoff ; current EMS page offset (paras)
mov es,prep.ems_pageframe ; page frame address
mov ds,currdesc.addr ; segment to swap
;
mov ax,ems_parasize ; max length
sub ax,di ; minus current offset
jnz swems_ok ; go copy if there's room
;
swems_loop:
mov ax,4400h ; map in next page
int EMM_INT
or ah,ah
jnz swems_error
mov di,0 ; reset offset
inc bx ; bump up page number
mov ax,ems_parasize ; max length to copy
;
swems_ok:
cmp ax,cx ; length to copy
jbe swems_doit ; go do it if <= total length
mov ax,cx ; else use total length
;
swems_doit:
sub cx,ax ; subtract copy length from total
push cx ; and save
push ax ; save the copy length in paras
push si
push di
mov cl,3
shl ax,cl ; convert to number of words (!)
inc cl
shl di,cl ; convert to byte address
mov cx,ax
rep movsw
pop di
pop si
pop cx ; copy length in paras
mov ax,ds
add ax,cx ; add copy length to source segment
add di,cx ; and EMS page offset
mov ds,ax
pop cx ; remaining length
or cx,cx ; did we copy everything?
jnz swems_loop ; go loop if not
;
pop ds
cmp currdesc.num_follow,0 ; another MCB?
je swems_complete ; exit if not
;
; Another MCB follows, append nextmcb to save block.
;
cmp di,ems_parasize
jb swems_nonewpage ; no new block needed
mov ax,4400h ; map page, phys = 0
int EMM_INT
or ah,ah
jnz swems_error1
mov di,0
inc bx
;
swems_nonewpage:
push di
mov cl,4
shl di,cl ; convert to byte address
mov cx,TYPE mcbdesc
mov si,offset nextmcb
rep movsb
pop di
inc di ; one paragraph
;
swems_complete:
mov ems_curpage,bx
mov ems_curoff,di
xor ax,ax
ret
;
swems_error:
pop ds
swems_error1:
mov ah,45h ; release EMS pages on error
int EMM_INT
mov ax,RC_SWAPERROR
or ax,ax
ret
;
swapout_ems endp
;
;
; swapout_xms: swap out an MCB block to XMS.
;
; 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_xms proc near
;
mov ax,currdesc.swsize ; size in paragraphs
mov cl,4
rol ax,cl ; size in bytes + high nibble
mov dx,ax
and ax,0fff0h ; low word
and dx,0000fh ; high word
mov xmsctl.lenlo,ax ; into control block
mov xmsctl.lenhi,dx
mov xmsctl.srchnd,0 ; source is normal memory
mov ax,currdesc.swoffset ; swap offset
mov xmsctl.srclo,ax ; into control block
mov ax,currdesc.addr ; segment to swap
mov xmsctl.srchi,ax
mov ax,prep.handle ; XMS handle
mov xmsctl.desthnd,ax
mov si,offset xmsctl
mov ah,0bh
call prep.xmm ; move it
or ax,ax
jz swxms_error
mov ax,xmsctl.lenlo ; adjust destination addr
add xmsctl.destlo,ax
mov ax,xmsctl.lenhi
adc xmsctl.desthi,ax
;
cmp currdesc.num_follow,0 ; another MCB?
je swxms_complete
;
mov xmsctl.lenlo,TYPE mcbdesc
mov xmsctl.lenhi,0
mov xmsctl.srchi,ds
mov xmsctl.srclo,offset nextmcb
mov si,offset xmsctl
mov ah,0bh
call prep.xmm ; move it
or ax,ax
jz swxms_error
add xmsctl.destlo,16 ; one paragraph
adc xmsctl.desthi,0
;
swxms_complete:
xor ax,ax
ret
;
swxms_error:
mov ah,0ah ; release XMS frame on error
mov dx,prep.handle ; XMS handle
call prep.xmm
mov ax,RC_SWAPERROR
or ax,ax
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,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 prep.swapfilename
mov ah,41h ; delete file
int 21h
mov ax,RC_SWAPERROR
or ax,ax
ret
;
swapout_file endp
;
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
;
;
do_spawn PROC uses si di,swapping: word, execfname:ptr byte,params:ptr byte,envlen:word,envp:ptr byte
local datseg,pspseg,currmcb
;
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,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:
push ds
pop es
push ds
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
pop ds
;
mov ax,swapping
cmp ax,0
jg begin_swap
;
; not swapping, prep_swap wasn't called. Init those variables in
; the 'prep' block we need in any case.
;
mov prep.swapmethod,al
je no_reduce
;
mov ax,pspseg
dec ax
mov prep.psp_mcb,ax
mov prep.first_mcb,ax
inc ax
mov es,ax
mov bx,es:psp_envptr
mov prep.env_mcb,bx
mov prep.noswap_mcb,0
cmp envlen,0
jne swp_can_swap_env
mov 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 prep.first_mcb,es
;
no_reduce:
jmp no_swap1
;
; set up first block descriptor
;
begin_swap:
mov ax,prep.first_mcb
mov currmcb,ax
mov es,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,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,prep.psp_mcb
mov dx,prep.noswap_mcb
;
swm_mcb_walk:
mov es,ax
cmp ax,cx
je swm_next_mcb
cmp ax,dx
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 prep.swapmethod,USE_EMS
je swm_ems
cmp 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:
cmp prep.swapmethod,USE_FILE
je swm_mcberr_file
cmp prep.swapmethod,USE_EMS
je swm_mcberr_ems
;
mov ah,0ah ; release XMS frame on error
mov dx,prep.handle ; XMS handle
call prep.xmm
mov ax,RC_MCBERROR
jmp short swapout_error
;
swm_mcberr_ems:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -