746 lines
13 KiB
NASM
746 lines
13 KiB
NASM
|
page ,132
|
||
|
subttl emwin.asm - Initialization and Termination for Windows
|
||
|
;***
|
||
|
;emwin.asm - Initialization and Termination for Windows
|
||
|
;
|
||
|
; Copyright (c) 1987-89, Microsoft Corporation
|
||
|
;
|
||
|
;Purpose:
|
||
|
; Initialization and Termination for Windows
|
||
|
;
|
||
|
; This Module contains Proprietary Information of Microsoft
|
||
|
; Corporation and should be treated as Confidential.
|
||
|
;
|
||
|
;Revision History:
|
||
|
; See emulator.hst
|
||
|
;
|
||
|
;*******************************************************************************
|
||
|
|
||
|
|
||
|
comment !
|
||
|
|
||
|
Windows/DOS interfaces to emulator/8087 functions
|
||
|
|
||
|
Certain emulator/8087 functions are performed by calling __fpmath
|
||
|
with an function code and arguments.
|
||
|
|
||
|
__fpmath general floating point math package interface used
|
||
|
by the emulator/8087 and float calls interfaces. This
|
||
|
is a far routine and must be far called.
|
||
|
|
||
|
entry:
|
||
|
|
||
|
bx = 0 initialize floating point math (program startup)
|
||
|
dx, ax, si input values ignored in WINDOWS emulator
|
||
|
returns:
|
||
|
ax = 0 if successful and using software floating point
|
||
|
1 if successful and using 8087
|
||
|
just terminates process if error
|
||
|
|
||
|
bx = 1 reset (FINIT) - finit ok even under WINDOWS;
|
||
|
typical usage will load control word afterward
|
||
|
so other tasks won't be hindered (as with _fpreset() call)
|
||
|
|
||
|
bx = 2 terminate floating point math (program termination)
|
||
|
|
||
|
bx = 3 set error signal address
|
||
|
dx:ax = segment:offset of user error handler
|
||
|
|
||
|
bx = 4 load user control word
|
||
|
(user should not use FLDCW instruction directly)
|
||
|
ax = user control word value
|
||
|
|
||
|
bx = 5 store user control word
|
||
|
returns:
|
||
|
ax = user control word value
|
||
|
|
||
|
bx = 6 truncate TOS to integer TOS
|
||
|
ax = user control word (only use round mode)
|
||
|
|
||
|
bx = 7 truncate TOS to 32-bit integer in DX:AX
|
||
|
ax = user control word (only use round mode)
|
||
|
|
||
|
bx = 8 store user status word
|
||
|
returns:
|
||
|
ax = user status word value
|
||
|
|
||
|
bx = 9 clear exceptions
|
||
|
|
||
|
bx = 10 return number of stack elements in ax
|
||
|
|
||
|
bx = 11 returns 1 if using 80x87, 0 if not
|
||
|
|
||
|
bx = 12 if ax = 0, turn off extended stack. if ax = 1, turn on e.s.
|
||
|
|
||
|
!
|
||
|
|
||
|
|
||
|
glb <functab>
|
||
|
|
||
|
functab label word
|
||
|
|
||
|
dw initialization ; 0 - initialize emulator/8087
|
||
|
dw reset ; 1 - reset emulator/8087 stack
|
||
|
dw termination ; 2 - terminate emulator/8087
|
||
|
dw setsignal ; 3 - set error signal address
|
||
|
dw loadcontrolword ; 4 - load user control word
|
||
|
dw storecontrolword ; 5 - store user control word
|
||
|
dw truncateTOS ; 6 - truncate TOS to integer TOS
|
||
|
dw truncateTOSto32int ; 7 - truncate TOS to integer in DX:AX
|
||
|
dw storestatusword ; 8 - store user status word
|
||
|
dw clearexceptions ; 9 - clear execeptions
|
||
|
dw NumStack ; 10 - report number of elements in stack
|
||
|
dw ReturnHave8087 ; 11 - report if using coprocessor
|
||
|
dw SetExtendedStack ; 12 - turn on or off extended stack
|
||
|
endfunc label word
|
||
|
|
||
|
SizeJmpTab equ 12
|
||
|
|
||
|
sEnd ecode
|
||
|
|
||
|
|
||
|
sBegin ecode
|
||
|
|
||
|
assumes cs, ecode
|
||
|
assumes ds, edata
|
||
|
|
||
|
|
||
|
|
||
|
public __fpmath
|
||
|
|
||
|
__fpmath proc far
|
||
|
|
||
|
cmp bx, SizeJmpTab
|
||
|
ja RetFPErr
|
||
|
|
||
|
shl bx, 1
|
||
|
push ds ; save DS
|
||
|
|
||
|
mov cx, EMULATOR_DATA
|
||
|
mov ds, cx
|
||
|
|
||
|
call functab[bx]
|
||
|
|
||
|
pop ds ; restore DS
|
||
|
|
||
|
EmuRet:
|
||
|
ret
|
||
|
|
||
|
|
||
|
RetFPErr:
|
||
|
or ax, -1
|
||
|
cwd
|
||
|
jmp EmuRet
|
||
|
|
||
|
__fpmath endp
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
subttl emwin.asm - Initialization and Termination
|
||
|
page
|
||
|
;*********************************************************************;
|
||
|
; ;
|
||
|
; Initialization and Termination ;
|
||
|
; ;
|
||
|
;*********************************************************************;
|
||
|
|
||
|
wastetime macro
|
||
|
push cx
|
||
|
mov cx,20 ;; wait for a short time
|
||
|
loop $
|
||
|
pop cx
|
||
|
endm
|
||
|
|
||
|
|
||
|
|
||
|
; program initialization
|
||
|
;
|
||
|
; entry dx:ax = task data area (segment and size) for standalone
|
||
|
; si = DOS environment segment for NO87 lookup ???
|
||
|
; DX,AX,SI - ignored in WINDOWS case
|
||
|
; these register inputs are ignored for Windows app
|
||
|
; program-time initialization
|
||
|
|
||
|
pub initialization ; all initialization is done when loaded
|
||
|
|
||
|
ifdef WF
|
||
|
cmp [Installed],0
|
||
|
jnz @F
|
||
|
.286p
|
||
|
push 0
|
||
|
call AllocSelector
|
||
|
mov [wfSel], ax ; Error checking??
|
||
|
mov ax, __WINFLAGS
|
||
|
; int 3
|
||
|
test ax, WF_WIN386
|
||
|
jz wfSlow1
|
||
|
cmp [Have8087], 0
|
||
|
je wfSlow1
|
||
|
or [wfGoFast], 1 ; We can use fast if Enh Mode & FPU
|
||
|
wfSlow1:
|
||
|
@@:
|
||
|
endif
|
||
|
inc [Installed] ; Installed will count number of apps
|
||
|
; using the emulator.
|
||
|
|
||
|
cmp [Have8087], 0 ; check for 8087/80287
|
||
|
je NoInstall87
|
||
|
|
||
|
extrn __FPINSTALL87:near
|
||
|
call __FPINSTALL87 ; set NMI (int 2) for this instance
|
||
|
NoInstall87:
|
||
|
|
||
|
call reset
|
||
|
xor ax, ax
|
||
|
|
||
|
ret
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
ifdef standalone
|
||
|
mov di,offset BEGstk ; di = base of register stack
|
||
|
mov [BASstk],di ; initialize stack base
|
||
|
mov cx,Reg87Len ; cx = register length
|
||
|
xchg ax,dx ; ax = task data segment size
|
||
|
sub ax,di ; ax = number bytes for stack
|
||
|
cwd ; dx:ax = number of bytes
|
||
|
div cx ; ax = number of entries
|
||
|
mul cx ; ax = number of bytes
|
||
|
add ax,di ; ax = top of stack
|
||
|
sub ax,cx ; Leave room for one on overflow
|
||
|
mov [LIMstk],ax ; set top of stack
|
||
|
endif ;standalone
|
||
|
|
||
|
|
||
|
|
||
|
; check if floating point emulator/8087 already installed (device driver)
|
||
|
|
||
|
|
||
|
|
||
|
; load time initialization
|
||
|
|
||
|
pub LoadTimeInit
|
||
|
|
||
|
push di
|
||
|
push si
|
||
|
push ds
|
||
|
mov ax,EMULATOR_DATA
|
||
|
mov ds,ax
|
||
|
|
||
|
mov ax, __WINFLAGS
|
||
|
and ax, WF_80x87
|
||
|
cmp ax, WF_80x87
|
||
|
jz WinHave87
|
||
|
|
||
|
ifdef only87
|
||
|
jmp loadiniterrorret
|
||
|
endif
|
||
|
jmp WinSet87
|
||
|
|
||
|
pub WinHave87
|
||
|
mov al,1
|
||
|
|
||
|
pub WinSet87
|
||
|
mov [Have8087],al
|
||
|
|
||
|
; real mode emulation and fixup on the fly vector setup
|
||
|
|
||
|
pub initvec
|
||
|
call SaveVectors
|
||
|
call SetVectors
|
||
|
|
||
|
|
||
|
pub loadinitfinish
|
||
|
|
||
|
|
||
|
; finish initialization
|
||
|
|
||
|
pub initfinish
|
||
|
|
||
|
mov [Installed], 0 ; Installed will count number of apps
|
||
|
|
||
|
call reset ; reset (0), FINIT if 8087 present and
|
||
|
; set up default control word
|
||
|
|
||
|
mov ax, 1 ; return non zero result
|
||
|
|
||
|
pub loadiniterrorret
|
||
|
|
||
|
pop ds
|
||
|
pop si
|
||
|
pop di
|
||
|
retf ; far return for dynalink lib entry pt.
|
||
|
|
||
|
|
||
|
;*
|
||
|
;* DLL termination routine.
|
||
|
;*
|
||
|
|
||
|
public WEP
|
||
|
WEP label far
|
||
|
|
||
|
push ds
|
||
|
push ax
|
||
|
|
||
|
push si
|
||
|
push di
|
||
|
|
||
|
mov ax,EMULATOR_DATA
|
||
|
mov ds,ax
|
||
|
|
||
|
call reset
|
||
|
call RestoreVectors
|
||
|
|
||
|
pop di
|
||
|
pop si
|
||
|
pop ax
|
||
|
pop ds
|
||
|
|
||
|
retf 2 ; WEP functions are called with a word paramater.
|
||
|
|
||
|
|
||
|
;------ program termination ----------------------------------------------------
|
||
|
|
||
|
pub termination
|
||
|
|
||
|
call reset ; reset chip for other apps
|
||
|
|
||
|
dec [Installed] ; if Installed is not 0, someone is
|
||
|
jnz termrealdone ; still using the emulator.
|
||
|
|
||
|
ifdef WF
|
||
|
xor ax, ax
|
||
|
xchg ax, [wfSel]
|
||
|
or ax, ax
|
||
|
jz @F
|
||
|
push ax
|
||
|
call FreeSelector
|
||
|
@@:
|
||
|
endif
|
||
|
|
||
|
ifndef only87
|
||
|
cmp [Have8087],0 ; Non zero if 8087 chip exists
|
||
|
je termrealdone
|
||
|
endif ;only87
|
||
|
|
||
|
extrn __FPTERMINATE87:near ; reset NMI (int 2) for this instance
|
||
|
call __FPTERMINATE87
|
||
|
|
||
|
pub termrealdone
|
||
|
ret
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
subttl emwin.asm - reset and clearexceptions
|
||
|
page
|
||
|
;*********************************************************************;
|
||
|
; ;
|
||
|
; Reset and Clearexceptions ;
|
||
|
; ;
|
||
|
;*********************************************************************;
|
||
|
|
||
|
pub reset
|
||
|
|
||
|
ifndef only87
|
||
|
cmp [Have8087],0 ; Nonzero if 8087 chip exists
|
||
|
je NoFINIT
|
||
|
endif ;only87
|
||
|
fninit
|
||
|
fwait ; Workaround for 80387 bug.
|
||
|
fninit
|
||
|
|
||
|
pub NoFINIT
|
||
|
mov ax, [BASstk]
|
||
|
mov [CURstk], ax ; reset stack to bottom
|
||
|
|
||
|
mov ax, InitControlWord ; setup initial control word
|
||
|
call loadcontrolword
|
||
|
|
||
|
|
||
|
; fall into clearexceptions
|
||
|
|
||
|
|
||
|
pub clearexceptions
|
||
|
|
||
|
xor ax, ax
|
||
|
ifndef only87
|
||
|
cmp al, [Have8087] ; Nonzero if 8087 chip exists
|
||
|
je NoFCLEX
|
||
|
endif ;only87
|
||
|
fclex ; clear exceptions
|
||
|
|
||
|
pub NoFCLEX
|
||
|
ifndef only87
|
||
|
mov [StatusWord], ax ; clear status word
|
||
|
endif ;only87
|
||
|
mov [UserStatusWord], ax ; clear exception status word
|
||
|
|
||
|
ret
|
||
|
|
||
|
|
||
|
|
||
|
subttl emwin.asm - setsignal ---------------------------------
|
||
|
page
|
||
|
;*********************************************************************;
|
||
|
; ;
|
||
|
; Setsignal ;
|
||
|
; ;
|
||
|
;*********************************************************************;
|
||
|
|
||
|
|
||
|
pub setsignal
|
||
|
|
||
|
push ds
|
||
|
|
||
|
mov ds, dx ; set TSKINT to SignalAddress
|
||
|
mov dx, ax
|
||
|
mov ax, 25h*256 + TSKINT
|
||
|
IntDOS
|
||
|
|
||
|
pop ds
|
||
|
ret
|
||
|
|
||
|
|
||
|
pub SaveVectors
|
||
|
|
||
|
mov cx, NUMVEC ; save old vectors under DOS 3
|
||
|
mov ax, 35h*256 + BEGINT ; get vector
|
||
|
mov di, offset oldvec ; di = old vector table
|
||
|
|
||
|
pub getvecs
|
||
|
IntDOS
|
||
|
inc ax
|
||
|
mov [di], bx ; save old vector
|
||
|
mov [di+2], es
|
||
|
add di, 4
|
||
|
loop getvecs
|
||
|
|
||
|
ret
|
||
|
|
||
|
pub SetVectors
|
||
|
|
||
|
ifndef only87
|
||
|
mov dx, offset DStrap ; assume emulator
|
||
|
mov si, offset SOtrap
|
||
|
mov di, offset FWtrap
|
||
|
ifdef WINDOWS
|
||
|
mov ax, __WINFLAGS ; if we are in PMODE & win386 increment all of
|
||
|
and ax, WF_PMODE or WF_WIN386 ; the handler address past the "sti".
|
||
|
cmp ax, WF_PMODE or WF_WIN386
|
||
|
jne NotPmode1
|
||
|
|
||
|
inc dx
|
||
|
inc si
|
||
|
inc di
|
||
|
lab NotPmode1
|
||
|
endif ;WINDOWS
|
||
|
|
||
|
cmp [Have8087], 0 ; are we using 8087 ?
|
||
|
jz SetEmVecs ; no - go ahead and set them
|
||
|
endif ;only87
|
||
|
|
||
|
mov dx, offset DSFixUpOnFly ; set up for fixup-on-the-fly
|
||
|
mov si, offset SOFixUpOnFly
|
||
|
mov di, offset FWFixUpOnFly
|
||
|
ifdef WINDOWS
|
||
|
mov ax, __WINFLAGS ; if we are in PMODE & win386 increment all of
|
||
|
and ax, WF_PMODE or WF_WIN386 ; the handler address past the "sti".
|
||
|
cmp ax, WF_PMODE or WF_WIN386
|
||
|
jne NotPmode2
|
||
|
|
||
|
inc dx
|
||
|
inc si
|
||
|
inc di
|
||
|
lab NotPmode2
|
||
|
endif ;WINDOWS
|
||
|
|
||
|
pub SetEmVecs
|
||
|
push ds
|
||
|
|
||
|
push cs
|
||
|
pop ds
|
||
|
mov ax, 25h*256 + BEGINT
|
||
|
mov cx, 8 ; 8 vectors for DStrap
|
||
|
|
||
|
pub SetDSLoop
|
||
|
IntDOS ; set vector
|
||
|
inc ax ; bump to next one
|
||
|
loop SetDSLoop
|
||
|
|
||
|
mov dx, si ; set Segtrap
|
||
|
IntDOS
|
||
|
inc ax
|
||
|
mov dx, di ; set FWtrap
|
||
|
IntDOS
|
||
|
|
||
|
pop ds ; restore task data area
|
||
|
|
||
|
ret
|
||
|
|
||
|
|
||
|
pub RestoreVectors
|
||
|
|
||
|
mov cx, NUMVEC
|
||
|
mov ax, 25h*256 + BEGINT ; Dos set vector.
|
||
|
mov di, offset oldvec ; di = old vector table
|
||
|
|
||
|
pub ResetVecLoop
|
||
|
push ds
|
||
|
lds dx, [di] ; get old vector value
|
||
|
IntDOS
|
||
|
pop ds
|
||
|
inc ax
|
||
|
add di,4
|
||
|
|
||
|
loop ResetVecLoop
|
||
|
|
||
|
ret
|
||
|
|
||
|
|
||
|
|
||
|
pub NumStack ; returns the number of stack elements in ax
|
||
|
|
||
|
xor dx, dx ; dx will count nonzero elements
|
||
|
|
||
|
ifndef only87
|
||
|
cmp Have8087, 0
|
||
|
je CountEmulatorStack
|
||
|
endif ;only87
|
||
|
|
||
|
sub sp, 14 ; need 14 bytes for fstenv
|
||
|
mov bx, sp
|
||
|
fstenv ss:[bx]
|
||
|
fldcw ss:[bx] ; reset control word
|
||
|
mov ax, ss:[bx+4] ; put tag word in ax
|
||
|
add sp, 14 ; reset stack
|
||
|
|
||
|
mov cx, 8
|
||
|
pub NotEmptyLoop
|
||
|
mov bx, ax
|
||
|
|
||
|
shr ax, 1
|
||
|
shr ax, 1
|
||
|
|
||
|
and bx, 3
|
||
|
cmp bx, 3
|
||
|
je StackEntryEmpty
|
||
|
|
||
|
inc dx ; stack element was not empty
|
||
|
pub StackEntryEmpty
|
||
|
loop NotEmptyLoop
|
||
|
|
||
|
|
||
|
pub CountEmulatorStack
|
||
|
|
||
|
mov ax, CURstk
|
||
|
sub ax, BASstk
|
||
|
|
||
|
mov bl, Reg87Len
|
||
|
|
||
|
div bl
|
||
|
|
||
|
add ax, dx ; add elements on 80x87 stack
|
||
|
|
||
|
ret
|
||
|
|
||
|
|
||
|
ReturnHave8087 proc near
|
||
|
|
||
|
mov al, [Have8087]
|
||
|
cbw
|
||
|
|
||
|
ret
|
||
|
ReturnHave8087 endp
|
||
|
|
||
|
|
||
|
SetExtendedStack proc near
|
||
|
|
||
|
mov [ExtendStack], ax
|
||
|
|
||
|
ret
|
||
|
SetExtendedStack endp
|
||
|
|
||
|
|
||
|
|
||
|
;***
|
||
|
;int far pascal __Win87EmInfo( WinInfoStruct far * p, int cb );
|
||
|
;
|
||
|
;Purpose:
|
||
|
; returns information about win87em.exe to CodeView
|
||
|
;
|
||
|
;Entry:
|
||
|
; WinInfoStruct far * p
|
||
|
; int cb - size of WinInfoStruct
|
||
|
;
|
||
|
;Exit:
|
||
|
; returns non zero if error.
|
||
|
;
|
||
|
;
|
||
|
;Uses:
|
||
|
;
|
||
|
;Exceptions:
|
||
|
;
|
||
|
;*******************************************************************************
|
||
|
|
||
|
|
||
|
cProc __WIN87EMINFO,<PUBLIC,FAR,PLM>,<ds>
|
||
|
|
||
|
parmD p
|
||
|
parmW cb
|
||
|
|
||
|
cBegin
|
||
|
or ax, -1
|
||
|
cmp [cb], size WinInfoStruct
|
||
|
jb WIDone
|
||
|
|
||
|
mov ax, edataBASE
|
||
|
mov es, ax
|
||
|
assumes es, edata
|
||
|
|
||
|
lds bx, [p]
|
||
|
assumes ds, nothing
|
||
|
|
||
|
mov [bx.WI_Version], (major_ver shl 8) + minor_ver
|
||
|
mov [bx.WI_SizeSaveArea], Size80x87Area + edataOFFSET __fptaskdata
|
||
|
mov [bx.WI_WinDataSeg], es
|
||
|
mov [bx.WI_WinCodeSeg], cs
|
||
|
|
||
|
mov al, [Have8087]
|
||
|
cbw
|
||
|
mov [bx.WI_Have80x87], ax
|
||
|
assumes es, nothing
|
||
|
|
||
|
xor ax, ax ; return 0 if no error
|
||
|
mov [bx.WI_Unused], ax
|
||
|
WIDone:
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
;***
|
||
|
;int far pascal __Win87EmSave( void far * p, int cb );
|
||
|
;
|
||
|
;Purpose:
|
||
|
; saves win87em.exe info in p
|
||
|
;
|
||
|
;Entry:
|
||
|
; void far * p - pointer to save area.
|
||
|
; int cb - size of save area.
|
||
|
;
|
||
|
;Exit:
|
||
|
; returns non zero if error.
|
||
|
;
|
||
|
;Uses:
|
||
|
;
|
||
|
;Exceptions:
|
||
|
;
|
||
|
;*******************************************************************************
|
||
|
|
||
|
|
||
|
cProc __WIN87EMSAVE,<PUBLIC,FAR,PLM>,<ds,si,di>
|
||
|
|
||
|
parmD p
|
||
|
parmW cb
|
||
|
|
||
|
cBegin
|
||
|
or ax, -1
|
||
|
cmp [cb], Size80x87Area + edataOFFSET __fptaskdata
|
||
|
jb WSDone
|
||
|
|
||
|
mov ax, edataBASE
|
||
|
mov ds, ax
|
||
|
assumes ds, edata
|
||
|
|
||
|
les di, [p]
|
||
|
assumes es, nothing
|
||
|
|
||
|
cmp [Have8087], 0
|
||
|
je NoSave80x87
|
||
|
|
||
|
fsave es:[di.WSA_Save80x87]
|
||
|
NoSave80x87:
|
||
|
|
||
|
add di, (WSA_SaveEm - WSA_Save80x87)
|
||
|
xor si, si
|
||
|
mov cx, edataOFFSET __fptaskdata
|
||
|
shr cx, 1
|
||
|
|
||
|
rep movsw
|
||
|
|
||
|
jnc NoSaveLastByte
|
||
|
movsb
|
||
|
NoSaveLastByte:
|
||
|
|
||
|
xor ax, ax ; return 0 if no error.
|
||
|
|
||
|
WSDone:
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
|
||
|
;***
|
||
|
;int far pascal __Win87EmRestore( void far * p, int cb );
|
||
|
;
|
||
|
;Purpose:
|
||
|
; retores win87em.exe info from p
|
||
|
;
|
||
|
;Entry:
|
||
|
; void far * p - pointer to save area.
|
||
|
; int cb - size of save area.
|
||
|
;
|
||
|
;Exit:
|
||
|
; returns non zero if error.
|
||
|
;
|
||
|
;Uses:
|
||
|
;
|
||
|
;Exceptions:
|
||
|
;
|
||
|
;*******************************************************************************
|
||
|
|
||
|
|
||
|
cProc __WIN87EMRESTORE,<PUBLIC,FAR,PLM>,<ds,si,di>
|
||
|
|
||
|
parmD p
|
||
|
parmW cb
|
||
|
|
||
|
cBegin
|
||
|
or ax, -1
|
||
|
cmp [cb], Size80x87Area + edataOFFSET __fptaskdata
|
||
|
jb WRDone
|
||
|
|
||
|
mov ax, edataBASE
|
||
|
mov es, ax
|
||
|
assumes es, edata
|
||
|
|
||
|
lds si, [p]
|
||
|
assumes ds, nothing
|
||
|
|
||
|
add si, (WSA_SaveEm - WSA_Save80x87)
|
||
|
xor di, di
|
||
|
mov cx, edataOFFSET __fptaskdata
|
||
|
shr cx, 1
|
||
|
|
||
|
rep movsw
|
||
|
|
||
|
jnc NoRestoreLastByte
|
||
|
movsb
|
||
|
NoRestoreLastByte:
|
||
|
|
||
|
mov si, [OFF_p] ; reset source pointer.
|
||
|
|
||
|
cmp [Have8087], 0
|
||
|
je NoRestore80x87
|
||
|
|
||
|
frstor [si.WSA_Save80x87]
|
||
|
NoRestore80x87:
|
||
|
|
||
|
xor ax, ax ; return 0 if no error.
|
||
|
|
||
|
WRDone:
|
||
|
cEnd
|
||
|
|
||
|
assumes ds, edata
|
||
|
assumes es, nothing
|