📄 cwswapr.asm
字号:
call dword ptr lmem [GoToWedge]
; mov ax,04b00h
; int 21h ; exec
;
; Return from EXEC system call. Don't count on any register except
; CS to be restored (DOS 2.11 and previous versions killed all regs).
;
mov bx,cs
mov ds,bx
mov es,bx
cli
mov ss,bx
mov sp,lmem spx
sti
cld
mov lmem eretcode,ax ; save return code
pushf
pop bx
mov lmem retflags,bx ; and returned flags
; restore dta
push ds
lds dx,lmem dtasave
mov ah,1ah ; set DTA address
int 21h
pop ds
;
; Cancel Redirection
;
IF REDIRECT
mov si,lredirsav
mov di,psp_handletab+5
mov cx,3
rep movsw
mov si,lstdinsav
xor cx,cx
;
lredirclose:
lodsw
cmp ax,-1
je lredclosenext
mov bx,ax
mov ah,46h
int 21h
;
lredclosenext:
inc cx
cmp cx,3
jb lredirclose
ENDIF
;
IFDEF SHRINKPSP
cmp lmem lprep.swapmethod,0
je exec_memok
jg exec_expand
ELSE
jmp NEAR PTR exec_memok
ENDIF
;
; Terminate.
;
test lmem retflags,1 ; carry?
jnz exec_term ; use EXEc retcode if set
mov ah,4dh ; else get program return code
int 21h
;
exec_term:
mov ah,4ch
int 21h
;
;
exec_expand:
IFDEF SHRINKPSP
mov ah,4ah ; expand memory
mov bx,lmem lcurrdesc.msize
int 21h
jnc exec_memok
mov ax,4cffh
int 21h ; terminate on error
ENDIF
;
; Swap memory back
;
nop
nop
nop
;
exec_memok:
;
; FALL THROUGH to the appropriate swap-in routine
;
;
getmcboff = offset get_mcb - offset lowcode_begin
iretoff = offset ireti - offset lowcode_begin
doexec_entry = offset doexec - offset lowcode_begin
base_length = offset $ - offset lowcode_begin
;
;-----------------------------------------------------------------------
;
; The various swap in routines follow. Only one of the routines
; is copied to low memory.
; Note that the routines are never actually called, the EXEC return
; code falls through. The final RET thus will return to the restored
; memory image.
;
; On entry, DS must point to low core.
; On exit to the restored code, DS is unchanged.
;
;
; swapin_ems: swap in from EMS.
;
swapin_ems proc far
;
xor bx,bx
mov si,ems_parasize
mov dx,lmem lprep.handle ; EMS handle
;
swinems_main:
push ds
mov cx,lmem lcurrdesc.swsize ; block length in paras
mov di,lmem lcurrdesc.swoffset ; swap offset
mov es,lmem lcurrdesc.addr ; segment to swap
mov ds,lmem lprep.ems_pageframe ; page frame address
;
mov ax,ems_parasize ; max length
sub ax,si ; minus current offset
jnz swinems_ok ; go copy if nonzero
;
swinems_loop:
mov ax,4400h ; map in next page
int EMM_INT
or ah,ah
jnz swinems_error
mov si,0 ; reset offset
inc bx ; bump up page number
mov ax,ems_parasize ; max length to copy
;
swinems_ok:
cmp ax,cx ; length to copy
jbe swinems_doit ; go do it if <= total length
mov ax,cx ; else use total length
;
swinems_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 si,cl ; convert to byte address
mov cx,ax
rep movsw
pop di
pop si
pop cx ; copy length in paras
mov ax,es
add ax,cx ; add copy length to dest segment
add si,cx ; and EMS page offset
mov es,ax
pop cx ; remaining length
or cx,cx ; did we copy everything?
jnz swinems_loop ; go loop if not
;
pop ds
cmp lmem lcurrdesc.num_follow,0 ; another MCB?
je swinems_complete ; exit if not
;
; Another MCB follows, read next mcb descriptor into currdesc
;
cmp si,ems_parasize
jb swinems_nonewpage ; no new block needed
mov ax,4400h ; map page, phys = 0
int EMM_INT
or ah,ah
jnz swinems_error1
mov si,0
inc bx
;
swinems_nonewpage:
push si
push ds
mov ax,ds
mov es,ax
mov ds,lmem lprep.ems_pageframe ; page frame address
mov cl,4
shl si,cl ; convert to byte address
mov cx,TYPE mcbdesc
mov di,lcurrdesc
rep movsb
pop ds
pop si
inc si ; one paragraph
;
push bx
call lmem cgetmcb
pop bx
jc swinems_error1
jmp swinems_main
;
swinems_complete:
mov ah,45h ; release EMS pages
int EMM_INT
ret
;
swinems_error:
pop ds
swinems_error1:
mov ah,45h ; release EMS pages on error
int EMM_INT
mov ax,4cffh
int 21h ; terminate
;
swapin_ems endp
;
swinems_length = offset $ - offset swapin_ems
;
;
; swapin_xms: swap in from XMS.
;
swapin_xms proc far
;
mov ax,lmem lprep.handle ; XMS handle
mov lmem lxmsctl.srchnd,ax ; source is XMS
mov lmem lxmsctl.desthnd,0 ; dest is normal memory
mov lmem lxmsctl.srclo,0
mov lmem lxmsctl.srchi,0
;
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.sp_swapfilename
mov ax,3d00h ; open file
int 21h
jc swinfile_error2
mov bx,ax ; file handle
;
; do this in case of shrinkage of non-owned MCB between PSP MCB and next owned MCB
mov ax,ds ; ax==PSP
dec ax ; ax==PSP MCB
mov lmem lprep.first_mcb,ax ; init first MCB to PSP
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.sp_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.sp_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 + 3) / 4) * 4
;
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
;
;--------------------------------------------------------------------
;
;
;
; 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 "swap_prep" structure is initialized by prep_swap.
;
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)
;
;--------------------------------------------------------------------
;
;
; 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,swap_prep.handle ; EMS handle
mov bx,ems_curpage ; current EMS page
mov di,ems_curoff ; current EMS page offset (paras)
mov es,swap_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
;
push ds
pop es
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,swap_prep.handle ; XMS handle
mov xmsctl.desthnd,ax
mov si,offset xmsctl
mov ah,0bh
call swap_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 swap_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,swap_prep.handle ; XMS handle
call swap_prep.xmm
mov ax,RC_SWAPERROR
or ax,ax
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -