dosinite.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 555 行 · 第 1/2 页

ASM
555
字号
;       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
        fldz                            ; put 387 into 4 empty / 4 full state
        fldz                            ; ...
        fldz                            ; ...
        fldz                            ; ...
        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: Ergo (OS/386)
          cmp   byte ptr __Extender,X_ERGO ; - quit if not Ergo
          _quif ne                      ; - ...
          mov   ax,2507h                ; - hook int7
          push  ds                      ; - ...
          mov   cx,cs                   ; - ...
          mov   ds,cx                   ; - ...
          lea   edx,__int7              ; - ...
          int   21h                     ; - ...
          pop   ds                      ; - restore ds
          mov   al,EM                   ; - ...
          mov   ah,0f3H                 ; - set EM bit in cr0 (turn off MP)
          int   21h                     ; - ...
        _admit                          ; guess: Intel Code Builder
          cmp   byte ptr __Extender,X_INTEL ; - quit if not Intel
          _quif ne                      ; - ...
          call  create_IDT_entry        ; - create entry for IDT
          mov   [ebx],edx               ; - fill in entry
          mov   4[ebx],ecx              ; - ...
;         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
          mov   eax,00000E02h           ; - "set cr0" function
          mov   ebx,EM                  ; - want EM bit turned on
          mov   ecx,__GDAptr            ; - get address of GDA
          call  dword ptr [ecx+GDA_SERV]          ; - call extender service routine
        _admit                          ; guess: Rational DOS/4G
          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: Intel Code Builder
          cmp   al,X_INTEL              ; - quit if not Intel
          _quif ne                      ; - ...
;         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
          mov   eax,00000E02h           ; - "set cr0" function
          mov   ebx,0                   ; - want EM bit turned off
          mov   ecx,__GDAptr            ; - get address of GDA
          call  dword ptr [ecx+GDA_SERV]          ; - call extender service routine
        _admit                          ; guess: Ergo DOS extender (OS/386)
          cmp   al,X_ERGO               ; - quit if not OS/386
          _quif ne                      ; - ...
          mov   ax,msw                  ; - get old EM and MP bits
          mov   ah,0f3h                 ; - reset EM/MP request
          int   21h                     ; - ...
        _admit                          ; guess: Rational DOS/4G
          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
          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 + -
显示快捷键?