📄 woapmrm.asm
字号:
RMSwapInLast:
mov ax,cx ;get amount left into ax:bx
mov bx,dx ;ax:bx has size of last portion
jmp RMSwapInNext ;read it in and move it
RMSwapInDone:
clc ;no error while moving
jmp short RMSwapInXmsBlockRet
RMSwapInFail:
stc ;swap out failed
RMSwapInXmsBlockRet:
cEnd
;----------------------------------------------------------------------------;
; GetXmsFreeArenaSel: ;
; ;
; This routine is a NOP in real mode. In protected mode, it prepares the ;
; selector for the base of the area to be allocated for xms and finds the ;
; first free windows high heap arena selector with which we can start ;
; swapping the windows xms image out. ;
;----------------------------------------------------------------------------;
cProc GetXmsFreeArenaSel,<NEAR,PUBLIC,PASCAL>
cBegin
cEnd
;----------------------------------------------------------------------------;
; GetAppXmsBase: ;
; ;
; This routine returns in CX:DX the base of the extended memory to be alloca-;
; -ted to the dos application. ;
;----------------------------------------------------------------------------;
GetAppXmsBase proc near
; lock the XMS block to get its base and then release the lock. We will not
; be doing any error checking here as we are sure to have a valid handle.
mov dx,HighMemXmsHandle ;handle of the extended memory block
mov ah,0ch ;function code for lock block
call lpXmsControl ;lock it.
mov cx,bx ;get loword of base
xchg cx,dx ;cx:dx has the base
pushem cx,dx ;save the base
mov ah,0dh ;function code for unlocking the block
mov dx,HighMemXmsHandle ;handle of the xms block
call lpXmsControl ;unlock the block
popem cx,dx ;get back the base
ret
GetAppXmsBase endp
;----------------------------------------------------------------------------;
; GetRealModeSeg: ;
; ;
; This routine takes a selector as parameter and returns in AX the correspo- ;
; -nding real mode segment. ;
;----------------------------------------------------------------------------;
cProc GetRealModeSeg,<NEAR,PUBLIC,PASCAL>
parmW SrcSel ;selector whose address to be extracted
cBegin
mov ax,SrcSel ;this itself is the segment
cEnd
;----------------------------------------------------------------------------;
; ShuffleSegments: ;
; ;
; Relocates the winoldap segments to where they will be resident when the Dos;
; application resides and transfers parameters to the stub segment. ;
; ;
; The exact actions, will depend on whether we are executing real or protect-;
; -ed mode winoldap. ;
;----------------------------------------------------------------------------;
cProc ShuffleSegments,<NEAR,PUBLIC,PASCAL>
cBegin
cld ;do not take chances with this
; now load data into the real mode stub.
cCall LoadRealModeStub
; now zero out the memory after the stub.
cCall ZeroOutMemory,<LowMemSel,LowMemParaSize,SizeReservedARea>
; if XMS is allocated to the app, ZEROINIT the xms block
mov ax,word ptr [XmsBankSize];get the low word
mov dx,word ptr [XmsBankSize+2]
push ax ;save
or ax,dx ;is the size 0 ?
pop ax ;dx:ax has bank size
jz @f ;no xms allocation
mov bx,0ffffh ;ZEROINIT opcode
cCall RMSwapInXmsBlock,<bx,dx,ax,bx>
@@:
cEnd
;----------------------------------------------------------------------------;
; MoveWoaIntoStubArea: ;
; ;
; This routine relocates the main winoldap code and data segment down to the ;
; start of either the low or the high heap area to make room for rolling the ;
; dos app in. ;
; ;
; In protected mode winoldap, they moved to the start of the high heap area ;
; where as in real mode winoldap, they are moved to the start of the low heap;
; area. ;
;----------------------------------------------------------------------------;
cProc MoveWoaIntoStubArea,<NEAR,PASCAL,PUBLIC>
cBegin
cld ;do not take chances with this
;*** cCall MoveWoa,<LowMemSel,WoaHighCsSel,WoaHighDsSel>
cEnd
;----------------------------------------------------------------------------;
; InvokeStubCode: ;
; ;
; This routine invokes the real mode stub code and control will come back ;
; on a context switch or once the old app ends. ;
; ;
; The invocation code will be different for real and protected modes. ;
;----------------------------------------------------------------------------;
cProc InvokeStubCode,<NEAR,PUBLIC,PASCAL>
cBegin
; prepare the call address from the values of CS,IP in the client register set
mov ax,RealMode_CS
mov wptr [lpStubEntry+2],ax ;save segment of stubcode
mov ax,RealMode_IP
mov wptr [lpStubEntry],ax ;save entry offset
; load the other segment registers.
pushem ds,bp ;save in new stack
mov ax,RealMode_DS
mov es,ax ;initialize
mov ax,RealMode_AX
call lpStubEntry ;invoke the stub code
popem ds,bp ;get back saved ds
mov RealMode_AX,ax
mov RealMode_BX,bx
mov AppUsesXMS,cx ;tells us whether app used XMS or not
mov NodeToSwitchTo,dl ;for directed hot key switch
smov es,ds ;set es to be same as ds
cEnd
;----------------------------------------------------------------------------;
; GetSegSize: ;
; ;
; This routine gets the size of a segment. Code is different for real and ;
; protected modes. ;
;----------------------------------------------------------------------------;
cProc GetSegSize,<NEAR,PUBLIC,PASCAL>
parmW SegSel ;segment or selector value
cBegin
push es ;save it
mov ax,SegSel ;get the segment value
dec ax ;the associated arena segment
mov es,ax ;have it in es
mov ax,es:[3] ;get the size in paragraphs
shiftl ax,4 ;gives the size in bytes
pop es ;restore
xor dx,dx ;hope segments are never exactly 64k
cEnd
;----------------------------------------------------------------------------;
; ZeroOutMemory: ;
; ;
; Given a start selector and a DWORD size, this routine clears out that ;
; amount of memory from the base of the selector. ;
;----------------------------------------------------------------------------;
cProc ZeroOutMemory,<NEAR,PUBLIC,PASCAL>,<es,di,cx>
parmW BaseSel ;selector for base
parmW MemParaSize ;size of area in paras
parmW ResSize ;reserved size at top.
localD SelBase ;original base
cBegin.
mov bx,BaseSel ;get the base
add bx,ResSize ;add in reservbed size in para
mov es,bx ;start sel
mov ax,MemParaSize ;get the para size
sub ax,ResSize ;subtract reserved area size
call GetSizeInBytes ;AX:BX has size in bytes
mov dx,ax ;DX:BX has the size.
xor di,di ;start at 0 offset
zero_loop:
or dx,dx ;still > 64K ?
jz zero_last ;no.
mov cx,8000h ;32K word
xor ax,ax
rep stosw ;zero out the segment.
dec dx ;one more 64k band done.
mov cx,es ;get the selector
add cx,1000h ;next 64k band
mov es,cx ;next segment
jmp short zero_loop ;continue.
zero_last:
mov cx,bx ;get remaining size
shr cx,1 ;convert to word
xor ax,ax ;zero put
rep stosw ;zero the last segment
cEnd
;----------------------------------------------------------------------------;
; GetSelectorBase: ;
; ;
; Entry: BX -- Selector ;
; Return: CX:DX -- 32 bit base ;
; Destroys: AX ;
;----------------------------------------------------------------------------;
GetSelectorBase proc near
mov dx,bx ;get the segment value
mov cl,4 ;need to shift by 4
shl dx,cl ;low word of base
xor ax,ax ;will prepare hiword here
mov al,bh ;get the upper byte of seg address
shr al,cl ;ax has high word of base
mov cx,ax ;now CX:DX has the base
ret
GetSelectorBase endp
;----------------------------------------------------------------------------;
; SetSelectorBaseLim64: ;
; ;
; Entry: BX -- Selector ;
; CX:DX -- base of the selector ;
; Return: selector set to have specified base and limit of 64k and access ;
; rights of data. ;
; Destroys: AX ;
;----------------------------------------------------------------------------;
SetSelectorBaseLim64 proc near
pushem cx,dx ;save
mov ax,cx ;have the high base word
mov cl,4 ;need shift by 4
shr dx,cl ;prepare low thre nibbles
ror ax,cl ;get low nibble of AX into hi pos.
or dh,ah ;dx has the proper segment value
mov bx,dx ;return it in bx
popem cx,dx ;restore
ret
SetSelectorBaseLim64 endp
;----------------------------------------------------------------------------;
; EmergencyExit: ;
; ;
; This routine is called to exit back to dos once windows swap in attempt ;
; fails. In protected mode windows, we have to use a special INT 2F function ;
; to first switch to the dos extenders PSP and then exit. In real mode, wino-;
; -ld ap executes always on the kernel's PSP so we can directly do the exit. ;
;----------------------------------------------------------------------------;
EmergencyExit proc near
assumes ds,Data
; if the there is a vailid 'HighMemXmsHandle', unlock and free the xms
; block.
mov dx,HighMemXmsHandle ;get the handle
or dx,dx ;is it null ?
jz @f ;no xms to free
; unlock the xms block and free it.
mov ah,0dh ;unlock block code
call [lpXmsControl] ;block unlocked
mov ah,0ah ;free xms block code
call [lpXmsControl] ;all of xms allocated to win released
@@:
; now do the exit
mov ax,4c01h ;exit code,exit with error
int 21h ;exit back to dos
EmergencyExit endp
;----------------------------------------------------------------------------;
; This routine invokes the error manager. ;
;----------------------------------------------------------------------------;
ErrorHandler:
call ErrorManager ;this never returns
;----------------------------------------------------------------------------;
sEnd Code
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -