📄 woaswapi.asm
字号:
smov es,cs ;make es:bx point to Our_Ver_Struc
mov bx,StubSegOFFSET Our_ver_Struc
xor ax,ax ;also clears carry
ret
GetVersion endp
;----------------------------------------------------------------------------;
; TestMemoryRegion: ;
; Entry: ;
; AX = 1 ;
; ES:DI = start of buffer ;
; CX = size of buffer (0=64K) ;
; Interrupts are disabled and may not be enabled. ;
; DOS calls may NOT be made. ;
; Exit: ;
; carry flag clear ;
; AX = 0 If entire buffer is in global memory ;
; AX = 1 If partially in global memory ;
; AX = 2 If entire buffer is in local memory ;
; ;
; Note: The are which is swapped out by the switcher starts at CS:0 and ;
; extends for 'WoaSwapAreaParaSize' paragraphs. This is the only area ;
; that we are going to treat as local, everything else is local. ;
; ;
; There are 5 cases marked below with the appropriate return code. ;
; ;
; ;
; |-------------------| ;
; | local memory | ;
; CASE: 1 2 | 3 | 4 5 ;
; |------| |--------| |-------| |-------| |--------| ;
; |------| |--------| |-------| |-------| |--------| ;
; RETS: 0 1 |----------2--------| 1 0 ;
; ;
;----------------------------------------------------------------------------;
TestMemoryRegion proc near
pushem bx,cx,dx,si,di ;save
xor ax,ax
mov bx,es ;ax:bx has the start segment
dec cx ;one less than size
REPT 4
shl bx,1 ;shift AX:BX left by 1
rcl ax,1
ENDM
add bx,di ;add in start offset
adc ax,0 ;AX:BX has start linear address
; compare AX:BX to CS:0, If AX:BX is less we have case 1 or 2, else 3, 4 or 5
mov di,cs ;get CS
xor si,si ;SI:DI will have left edge of LocalMem
REPT 4
shl di,1 ;shift AX:BX left by 1
rcl si,1
ENDM
call CompareAXBXtoSIDI ;do the comparision
jnc short TMR_Case3or4or5 ;beyong left edge of LocalMemory
; we have case 1 or 2.
add bx,cx
adc ax,0 ;AX:BX has the rt edge of the buffer
; compare the right edge of the buffer to the left edge of global memory
call CompareAXBXtoSIDI ;do the comparision
jc TMR_RetCase1or5 ;case 1.
jmp short TMR_RetCase2or4 ;case 2
TMR_Case3or4or5:
; get the right edge of global memory.
mov di,cs ;get CS
add di,cs:[WoaSwapAreaParaSize];add in size of the local memory
xor si,si ;SI:DI will have left edge of LocalMem
REPT 4
shl di,1 ;shift AX:BX left by 1
rcl si,1 ;SI:DI is one byte beyond right edge
ENDM
; figure out if it is case 5 or not. AX:BX is left edge of buffer and SI:DI
; is one byte beyond right edge of local memory.
call CompareAXBXtoSIDI ;do the comparision
jnc TMR_RetCase1or5 ;case 5.
; we have case 3 or 4. Get the right edge of buffer.
add bx,cx
adc ax,0 ;AX:BX has the rt edge of the buffer
; figure out whether it is case 3 or 4.
call CompareAXBXtoSIDI ;do the comparision
jnc TMR_RetCase2or4 ;case 4
TMR_RetCase3:
mov ax,2 ;buffer is totally local.
jmp short TMR_Ret ;done.
TMR_RetCase1or5:
xor ax,ax ;totally global
jmp short TMR_Ret ;done.
TMR_RetCase2or4:
mov ax,1 ;partially in local memory
TMR_Ret:
popem bx,cx,dx,si,di ;restore
ret
TestMemoryRegion endp
;----------------------------------------------------------------------------;
; SuspendSwitcher: ;
; ;
; Entry: ;
; AX = 2 ;
; ES:DI = Switcher call in of new task switcher, ;
; or 0:0 if not supported. ;
; Interrupts are enabled. ;
; DOS calls can be made. ;
; Exit: ;
; carry flag clear ;
; AX = 0 If the switcher is now suspended. ;
; AX = 1 If the switcher cannot be suspended. ;
; AX = 2 Not suspended, others may start. ;
;----------------------------------------------------------------------------;
SuspendSwitcher proc near
; set a flag bit to disabled the Switcher.
or cs:[SwitcherDisabled], SD_SWAPI_DISABLE
xor ax,ax ;switcher being disabled, clears carry
ret
SuspendSwitcher endp
;----------------------------------------------------------------------------;
; ResumeSwitcher: ;
; ;
; Entry: ;
; AX = 3 ;
; ES:DI = Switcher call in of new task switcher. ;
; Interrupts are enabled. ;
; DOS calls can be made. ;
; Exit: ;
; carry flag clear ;
; AX = 0 (required for future extensibility) ;
;----------------------------------------------------------------------------;
ResumeSwitcher proc near
; reset a flag bit which tells us that the switchet is disabled by another
; task switcher.
and cs:[SwitcherDisabled], NOT SD_SWAPI_DISABLE
xor ax,ax ;return code, clears carry
ret
ResumeSwitcher endp
;----------------------------------------------------------------------------;
; HookCallout: ;
; ;
; Entry: ;
; AX = 4 ;
; ES:DI = address of routine to add to call out chain. ;
; Interrupts are enabled. ;
; DOS calls can be made. ;
; Exit: ;
; carry flag clear ;
; AX = 0 (required for future extensibility) ;
;----------------------------------------------------------------------------;
HookCallOut proc near
xor ax,ax ;we generate INT 2f every time, carry clear
ret
HookCallOut endp
;----------------------------------------------------------------------------;
; UnHookCallout: ;
; ;
; Entry: ;
; AX = 5 ;
; ES:DI = address of routine to delete from call out chain;
; Interrupts are enabled. ;
; DOS calls can be made. ;
; Exit: ;
; carry flag clear ;
; AX = 0 (required for future extensibility) ;
;----------------------------------------------------------------------------;
UnHookCallOut proc near
xor ax,ax ;we generate INT 2f every time, carry clear
ret
UnHookCallOut endp
;----------------------------------------------------------------------------;
; QueryAPISupport: ;
; ;
; Entry: ;
; AX = 6 ;
; BX = API Code. ;
; Interrupts will not be enabled if the call is being from;
; within a call out from the switcher else they will be. ;
; DOS calls will not be made ;
; Exit: ;
; carry flag clear ;
; AX = 0 (required for future extensibility) ;
; ES:BX = address of the API_Info_Struc belonging to the ;
; respondent with the best level of support for ;
; this API. ;
;----------------------------------------------------------------------------;
QueryAPISupport proc near
pushem cx,si,ds ;save
mov cx,bx ;get the API code
; if the call back chain is still valid we whould not try to build the chain
; again.
les bx,cs:[lpCallBackChain] ;load it, in case it is vcalid
cmp cs:[CallBackAddrValid],0;is the call back address valid ?
jnz QAPIS_Walk_Chain ;it is valid
; will the chain again.
cCall BuildCallBackChain ;ES:BX points to start of chain
QAPIS_Walk_Chain:
xor si,si ;ds:si -> best handler's structure.
mov ds,si
QAPIS_WalkChainLoop:
push ax ;save
mov ax,es ;is es:bx 0 ?
or ax,bx ;end of chain ?
pop ax ;restore
jz QAPIS_DoneWithWalk ;yes, we have the results.
; get to the correct API node.
pushem es,bx,ax ;save
les bx,es:[bx.SCBI_API_Ptr] ;start of the pointer.
mov ax,es ;is it a valid node
or ax,bx ;NULL pointer ?
jz QAPIS_SameNode ;yes, skip this one.
QAPIS_SubLoop:
mov ax,es:[bx.AIS_Length] ;get the length
or ax,ax ;is this the end ?
jz QAPIS_SameNode ;have exhausted the list
cmp es:[bx.AIS_API],cx ;is it the right API
jz QAPIS_FoundAPINode ;yes, got it!
add bx,ax ;es:bx -> next API node
jmp short QAPIS_SubLoop ;keep looking for node
QAPIS_FoundAPINode:
; check to see if this is a betther handler.
call CompareAPILevels ;compare levels
jnc QAPIS_SameNode ;current best is still best
; es:bx points to a better node's structure. Save it in DS:SI.
smov ds,es ;ds:si = es:bx
mov si,bx
QAPIS_SameNode:
popem es,bx,ax ;restore
; continue walking down the line.
les bx,es:[bx.SCBI_Next] ;load the pointer to the next node.
jmp short QAPIS_WalkChainLoop;continue checking.
QAPIS_DoneWithWalk:
; ds:si -> API_Info_Struc of best handler. Compare this with ours and if the
; current one is better or equal retain it.
smov es,cs ;es:bx -> to our API info structure
mov bx,StubSegOFFSET Our_NB_API_Info
call CompareAPILevels ;see if DS:SI still points to best
jc QAPIS_Ret ;ES:BX -> best handler's API struc
; DS:SI points to the best, put it in ES:BX
smov es,ds
mov bx,si
QAPIS_Ret:
popem cx,si,ds ;save
ret
QueryAPISupport endp
;----------------------------------------------------------------------------;
; CompareAPILevels: ;
; ;
; Entry: ;
; ES:BX -> first API Info structure. ;
; DS:SI -> second API Info structure. ;
; Exit: ;
; Carry clear if the second structure is still the better handler. ;
; Uses: ;
; Flags. ;
;----------------------------------------------------------------------------;
CompareAPILevels proc near
push ax ;save
mov ax,ds ;is there a valid second guy ?
or ax,si
jz CAPIL_FirstBest ;first one is the best.
mov ax,[si.AIS_Major_Ver] ;major ver of second one
cmp ax,es:[bx.AIS_Major_Ver];major ver of first one
jb CAPIL_FirstBest ;we have a new node
ja CAPIL_Ret ;second is better, carry clear
mov ax,[si.AIS_Minor_Ver] ;minor ver of second one.
cmp ax,es:[bx.AIS_Minor_Ver];minor ver of first guy.
jb CAPIL_FirstBest ;we have a new node
ja CAPIL_Ret ;the current one is better
mov ax,[si.AIS_Support_Level];level of second guy
cmp ax,es:[bx.AIS_Support_Level]
jae CAPIL_Ret ;second guy is better
CAPIL_FirstBest:
stc ;first guy is better
CAPIL_Ret:
pop ax ;restore
ret
CompareAPILevels endp
;----------------------------------------------------------------------------;
; ComapareAXBXtoSIDI: ;
; ;
; Compare AX:BX (32 bits) to SI:DI (32 bits), the flags return the result of ;
; the comparision as would a CMP AX:BX,SI:DI would do. ;
;----------------------------------------------------------------------------;
CompareAXBXtoSIDI proc near
cmp ax,si ;compare high words
jne CABTSD_Ret ;either greater or less, flags tell
cmp bx,di ;compare low words, flags have result
CABTSD_Ret:
ret
CompareAXBXtoSIDI endp
;----------------------------------------------------------------------------;
; SWAPICreateSession: ;
; ;
; Makes a CREATE_SESSION SWAPI call out. ;
;----------------------------------------------------------------------------;
cProc SWAPICreateSession,<NEAR,PUBLIC,PASCAL>
cBegin
mov ax,SWAPI_CREATE ;create session call
mov dx,0ffffh ;call expects a return code
sti ;interrupts on for this call
call MakeSwitchAPICall ;make the Switch API call
; invalidate the call back address.
mov cs:[CallBackAddrValid],0;the address is invalid
cEnd
;----------------------------------------------------------------------------;
; SWAPIResumeSession: ;
; ;
; Makes a RESUME_SESSION SWAPI call out. ;
;----------------------------------------------------------------------------;
cProc SWAPIResumeSession,<NEAR,PUBLIC,PASCAL>
cBegin
mov ax,SWAPI_RESUME ;code for ResumeSession
xor dx,dx ;call expects no return code
mov cx,1 ;being run for the first time
cli ;interrupts off for this call.
call MakeSwitchAPICall ;make the Switch API call
; invalidate the call back address.
mov cs:[CallBackAddrValid],0;the address is invalid
cEnd
;----------------------------------------------------------------------------;
; SWAPISessionActive: ;
; ;
; Makes a SESSION_ACTIVE SWAPI call out. ;
;----------------------------------------------------------------------------;
cProc SWAPISessionActive,<NEAR,PUBLIC,PASCAL>
cBegin
mov ax,SWAPI_SESSION_ACTIVE ;code for SessionActive
xor dx,dx ;call expects no return code
mov cx,1 ;being run for the first time
sti ;interrupts on for this call
call MakeSwitchAPICall ;make the Switch API call
; invalidate the call back address.
mov cs:[CallBackAddrValid],0;the address is invalid
cEnd
;----------------------------------------------------------------------------;
; SWAPIDestroySession: ;
; ;
; Makes a DESTROY_SESSION SWAPI call out. ;
;----------------------------------------------------------------------------;
cProc SWAPIDestroySession,<NEAR,PUBLIC,PASCAL>
cBegin
mov ax,SWAPI_DESTROY ;code for DestroySession
xor dx,dx ;call expects no return code
sti ;interrupts on for this call
call MakeSwitchAPICall ;make the Switch API call
; invalidate the call back address.
mov cs:[CallBackAddrValid],0;the address is invalid
cEnd
;----------------------------------------------------------------------------;
sEnd StubSeg
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -