dosinite.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 301 行
ASM
301 行
;*****************************************************************************
;*
;* Open Watcom Project
;*
;* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
;*
;* ========================================================================
;*
;* This file contains Original Code and/or Modifications of Original
;* Code as defined in and that are subject to the Sybase Open Watcom
;* Public License version 1.0 (the 'License'). You may not use this file
;* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
;* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
;* provided with the Original Code and Modifications, and is also
;* available at www.sybase.com/developer/opensource.
;*
;* The Original Code and all software distributed under the License are
;* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
;* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
;* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
;* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
;* NON-INFRINGEMENT. Please see the License for the specific language
;* governing rights and limitations under the License.
;*
;* ========================================================================
;*
;* Description: Initialize extended DOS 387 emulation.
;*
;*****************************************************************************
include struct.inc
include extender.inc
.386p
.387
extrn __int7 : near
extrn __int7_pl3 : near
extrn __hook387 : near
extrn __unhook387 : near
_DATA segment dword public 'DATA'
extrn __8087 : byte
extrn __8087cw : word
extrn "C",_Extender : byte
extrn __X32VM : byte
extrn __D16Infoseg : word
extrn __x386_zero_base_selector : word
sysregs dd 14 dup(0) ; only need 12, but just in case
oldidt dd 0,0
old7off dd 0
old7seg dw 0
msw dw 0
hooked db 0
_DATA ends
DGROUP group _DATA
_TEXT segment word public 'CODE'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; void _sys_init_387_emulator( int )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
assume cs:_TEXT,ds:DGROUP
MP equ 02h
EM equ 04h
ET equ 10h
; ebp is not 0 if NO87 environment variable is present
public __sys_init_387_emulator
__sys_init_387_emulator proc near
push es ; save some registers
push ecx ; ...
push ebx ; ...
push edx ; ...
fninit ; initialize math coprocessor
push eax ; get some stack space
fnstcw [esp] ; store control word in memory
pop eax ; get CW into ax
cmp ah,03h ; coprocessor is present
_if ne ; if no coprocessor
inc ebp ; - pretend NO87 was set
_endif ; endif
or ebp,ebp ; if we want emulation
_if ne ; then
call hook_in_emulator ; - then hook in emulator
_endif ; endif
finit ; initialize the '80387'
fldcw word ptr __8087cw ; load control word
pop edx ; restore registers
pop ebx ; ...
pop ecx ; ...
pop es ; ...
ret ; return to caller
__sys_init_387_emulator endp
hook_in_emulator proc near
mov byte ptr __8087,3 ; pretend we have a 387
mov byte ptr hooked,1 ; indicate we hooked it
smsw msw ; save the EM and MP bits
and word ptr msw,EM or MP ; ...
sub esp,8 ; allocate temp
sidt fword ptr [esp] ; find out where IDT table is
mov ebx,2[esp] ; ...
add ebx,7*8 ; point to entry for int 7
add esp,8 ; deallocate temp
_guess ; guess: X-32VM
cmp byte ptr __X32VM,0 ; - quit if not X-32VM
_quif e ; - ...
call create_IDT_entry ; - create entry for IDT
mov es,__x386_zero_base_selector
mov es:[ebx],edx ; - set int 7
mov es:4[ebx],ecx ; - ...
call _set_EM_MP_bits ; - set EM and MP bits
_admit ; guess: DOS/4G or compatible
cmp byte ptr _Extender,X_RATIONAL ; - quit if not DOS/4G
_quif ne ; - ...
mov dx,__D16Infoseg ; - get segment address of _d16info
sub eax,eax ; - set offset to 0
call __hook387 ; - hook into int7
_admit ; admit: we're under Phar Lap
sub dx,dx ; - no info ptr
sub eax,eax
call __hook387 ; - try windows hookup
cmp al,1 ; - did it work?
_quif e ; - yes, done
call hook_pharlap ; - hook int7 under Phar Lap
_endguess ; endguess
ret ; return
hook_in_emulator endp
create_IDT_entry proc near
lea ecx,__int7 ; set new int7 handler
mov dx,cs ; get CS as our segment selector
shl edx,16 ; shift to top
mov dx,cx ; bottom word is low part of addr
mov cx,cs ; get CS for CPL bits
and cl,3 ; isolate CPL bits
shl cx,13 ; shift into place for DPL
or ch,8Eh ; set P=1, and INTERRUPT gate
ret ; return
create_IDT_entry endp
hook_pharlap proc near
_guess ; guess: version 4
if 0
cmp byte ptr _Extender,X_PHARLAP_V4 ; - chk for v4 or higher
_quif l ; - quit if not version 4 or higher
mov BL,7 ; - interrupt #7
mov ECX,0 ; - read IDT
lea EDX,oldidt ; - point to save area
mov AX,253Dh ; - code to read/write IDT
int 21h ; - read old value
_quif c ; - quit if error
call create_IDT_entry ; - create entry for IDT
push ECX ; - push new IDT onto stack
push EDX ; - ...
mov EDX,ESP ; - point to new IDT
mov ECX,1 ; - write IDT
mov AX,253Dh ; - code to read/write IDT
int 21h ; - write new value
pop ECX ; - clean up stack
pop ECX ; - ...
_quif c ; - quit if error
call _set_EM_MP_bits ; - set EM and MP bits
_admit ; guess: version 3
endif
mov cl,7 ; - get old int7 handler
mov ax,2502h ; - ...
int 21H ; - ...
mov old7off,ebx ; - save it
mov old7seg,es ; - ...
cmp byte ptr _Extender,X_PHARLAP_V3 ; - chk for v3 or higher
mov cl,7 ; - set new int7 handler
mov ax,2504h ; - ...
push ds ; - ...
push cs ; - ...
pop ds ; - ...
_quif l ; - quit if not version 3 or higher
lea edx,__int7_pl3 ; - set new int7 handler
int 21H ; - ...
pop ds ; - restore ds
call _set_EM_MP_bits ; - set EM and MP bits
_admit ; admit: Phar Lap version <= 2
lea edx,__int7 ; - set new int7 handler
int 21H ; - ...
pop ds ; - restore ds
mov ecx,cr0 ; - get cr0
or ecx,EM ; - flip on the EM bit
and ecx,not MP ; - don't want WAIT instructions
mov cr0,ecx ; - store it back
_endguess ; endguess
ret ; return
hook_pharlap endp
_set_EM_MP_bits proc near
xor ebx,ebx ; read system registers
lea edx,sysregs ; ...
mov ax,2535H ; ...
int 21h ; ...
or sysregs,EM ; flip on the EM bit
and sysregs,not MP ; don't want WAIT instructions
inc ebx ; write back system registers
int 21h ; ...
ret ; return
_set_EM_MP_bits endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; void _sys_fini_387_emulator( void )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public __sys_fini_387_emulator
__sys_fini_387_emulator proc near
cmp byte ptr hooked,1 ; if we have not hooked an interrupt
_if ne ; then
ret ; - return
_endif ; endif
push ecx ; save some regs
push ebx ; ...
push edx ; ...
mov al,_Extender ; get extender setting
_guess ; guess: X-32VM
cmp byte ptr __X32VM,0 ; - quit if not X-32VM
_quif e ; - ...
call _reset_EM_MP_bits ; - reset EM and MP bits
_admit ; guess: DOS/4G or compatible
cmp al,X_RATIONAL ; - quit if not DOS/4G
_quif ne ; - ...
mov dx,__D16Infoseg ; - get segment address of _d16info
sub eax,eax ; - set offset to 0
call __unhook387 ; - unhook from int7
_admit ; admit - we're under Phar Lap
sub edx,edx ; - null selector
sub eax,eax ; - set offset to 0
call __unhook387 ; - unhook from windows
cmp al,1 ; - did it work?
_quif e ; - yes, done
call unhook_pharlap ; - unhook emulator
_endguess ; endguess
mov byte ptr hooked,0 ; indicate not hooked anymore
pop edx ; restore regs
pop ebx ; ...
pop ecx ; ...
ret ; return
__sys_fini_387_emulator endp
unhook_pharlap proc near
_guess ; guess: version 4
if 0
cmp byte ptr _Extender,X_PHARLAP_V4 ; - chk for v4 or higher
_quif l ; - quit if not version 4 or higher
mov bl,7 ; - interrupt #7
mov ecx,1 ; - write IDT
lea edx,oldidt ; - point to save area
mov ax,253Dh ; - code to read/write IDT
int 21h ; - restore old value
_quif c ; - quit if error
call _reset_EM_MP_bits ; - reset EM and MP bits
_admit ; admit: not version 4
endif
mov cl,7 ; - restore int7 handler
mov ax,2504h ; - ...
mov edx,old7off ; - ...
push ds ; - save ds
mov ds,old7seg ; - ...
int 21H ; - ...
pop ds ; - restore ds
cmp byte ptr _Extender,X_PHARLAP_V3 ; - quit if version < 3
_quif l ; - ...
call _reset_EM_MP_bits ; - reset EM and MP bits
_admit ; admit: Pharlap V2
mov ecx,cr0 ; - get cr0
and ecx,not (EM or MP) ; - turn off EM and MP bits
mov dx,msw ; - restore to old values
or cx,dx ; - ...
mov cr0,ecx ; - store it back
_endguess ; endguess
ret ; return
unhook_pharlap endp
_reset_EM_MP_bits proc near
xor ebx,ebx ; read system registers
lea edx,sysregs ; ...
mov ax,2535H ; ...
int 21h ; ...
xor ecx,ecx ; restore EM and MP bits
mov cx,msw ; ...
mov sysregs,ecx ; ...
inc ebx ; write back system registers
int 21h ; ...
ret ; return
_reset_EM_MP_bits endp
_TEXT ends
end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?