interc.asm

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

ASM
523
字号
        ASSUME  ds:DGROUP

        xor     ax,ax
        xchg    ax,_Save_Request; clears _Save_Request (StopAndSave needs this)
        test    ax,ax           ; any requests?
        je      XL1             ; 0 - NO
        call    StopAndSave_
XL1     LABEL   near
        ASSUME  ds:nothing
        pop     ax
        pop     ds
        popf
        jmp    cs:_old_int28
int28_handler_  endp

;
; *** INT XX Handlers *** (used by /i option)
;
        public  intx0_handler_
intx0_handler_ proc far
        call    intxx_splice
        jmp     cs:_old_intx0
intx0_handler_ endp

        public  intx1_handler_
intx1_handler_ proc far
        call    intxx_splice
        jmp     cs:_old_intx1
intx1_handler_ endp

        public  intx2_handler_
intx2_handler_ proc far
        call    intxx_splice
        jmp     cs:_old_intx2
intx2_handler_ endp

        public  intx3_handler_
intx3_handler_ proc far
        call    intxx_splice
        jmp     cs:_old_intx3
intx3_handler_ endp

        public  intx4_handler_
intx4_handler_ proc far
        call    intxx_splice
        jmp     cs:_old_intx4
intx4_handler_ endp

        public  intx5_handler_
intx5_handler_ proc far
        call    intxx_splice
        jmp     cs:_old_intx5
intx5_handler_ endp

        public  intx6_handler_
intx6_handler_ proc far
        call    intxx_splice
        jmp     cs:_old_intx6
intx6_handler_ endp

        public  intx7_handler_
intx7_handler_ proc far
        call    intxx_splice
        jmp     cs:_old_intx7
intx7_handler_ endp

;
; intxx_splice -- an INT XX has occurred; check whether an application
;                 return address is stored already (will be set if it isn't)
;
public intxx_splice
intxx_splice proc near
        pushf
        cmp     cs:_sysCaller,0
        jne     intxx_go
        push    bp
        mov     bp,sp
        push    ax
        mov     ax,cs:intxx_retoff      ; replace seg:off of caller with
        xchg    ax,6[bp]                ;  intxx_return address
        mov     word ptr cs:_SysCallerAddr,ax
        mov     ax,cs:intxx_retseg
        xchg    ax,8[bp]
        mov     word ptr cs:_SysCallerAddr+2,ax
        mov     cs:_sysCaller,1
        mov     cs:_SysCaught,1
        pop     ax
        pop     bp
intxx_go LABEL  near
        popf
        ret
intxx_splice endp

;
; *** INT XX return interceptor ***
;
intxx_return proc far
        push    word ptr cs:_SysCallerAddr+2 ; push seg:off of caller
        push    word ptr cs:_SysCallerAddr   ; (without changing flags)
        mov     cs:_SysCaught,0 ; no more samples assigned to application now
        mov     cs:_sysCaller,0
        ret                     ; return to application
intxx_return endp

;
; InDOS_ -- returns non-zero if DOS cannot be entered
;
        public  InDOS_
InDOS_  proc    near
        call    DOSState        ; sets carry if DOS is unavailable
        sbb     ax,ax           ; 0 - OK, -1 - DOS unavailable
        ret
InDOS_  endp

;
; VersionCheck -- initializes the addresses for internal DOS flags
;                 (InDOSAddr & ErrorModeAddr)
;
        public  VersionCheck_
VersionCheck_ proc near
        push    bx
        push    cx
        push    es
        push    di
        push    ds

        push    ss
        pop     ds
        ASSUME  ds:DGROUP

        mov     ah,34h
        int     21h             ; &InDOS -> es:bx
        mov     word ptr cs:InDOSAddr,bx
        mov     word ptr cs:InDOSAddr+2,es

        mov     ah,30h          ; Get MS-DOS Version Number
        int     21h             ; sets bx=0, cx=0
        xchg    ah,al           ; original order is major:al minor:ah
        cmp     ah,02h          ; less than V2.xx?
        jb      Verror

        cmp     ax,030ah        ; less than V3.10? (0ah = 10 decimal)
        jb      tough_search
        cmp     ax,0a00h        ; OS/2 DOS box?
        jae     tough_search

;
; V3.10 and higher have the flags right beside each other
; (one byte below INDOS flag)
;
        mov     bx,word ptr cs:InDOSAddr
        dec     bx
        jmp     Vsuccess

tough_search:
        mov     cx,0ffffh
        xor     di,di           ; ES is set to correct seg from 34h function

find_int28 LABEL near
        mov     ax,word ptr cs:LF2      ; scan for INT 28
try_again LABEL near
        repne   scasb
        jne     Verror
        cmp     ah,es:[di]              ; check second byte for 28h
        jne     try_again

        mov     ax,word ptr cs:LF1+1    ; CMP opcode (+1 skips SS override)
        cmp     ax,es:[di][LF1-LF2]
        jne     try_test_op             ; if it's not CMP

        mov     bx,es:[di][(LF1-LF2)+2] ; found offset
        jmp     VSuccess

try_test_op LABEL near
        mov     ax,word ptr cs:LF3+1    ; TEST opcode (+1 skips SS override)
        cmp     ax,es:[di][LF3-LF4]
        jne     find_int28

        mov     bx, es:[di][(LF3-LF4)+2]; found offset
        jmp     Vsuccess

Vsuccess LABEL  near
        mov     word ptr cs:ErrorModeAddr,bx
        mov     word ptr cs:ErrorModeAddr+2,es
        mov     ax,1
Vexit   LABEL   near
        pop     ds
        pop     di
        pop     es
        pop     cx
        pop     bx
        ret

Verror: xor     ax,ax
        jmp     short Vexit

;
; the following are DOS code fragments that are used to find the code within
; DOS that checks the flags in question (see MSDOS encyclopedia)
;
LFnear      LABEL   near
LFbyte      LABEL   byte
LFword      LABEL   word

;
; *** PATTERN 1 ***
;
LF1:    cmp     ss:LFbyte,0     ; cmp    ErrorMode,0
        jne     LFnear
LF2:    int     28h

;
; *** PATTERN 2 ***
;
LF3:    test    ss:LFbyte, 0ffH ; test   ErrorMode,0ffH
        jne     LFnear
        push    ss:LFword
LF4:    int     28h

VersionCheck_ endp

;
; DOSState -- set carry if DOS cannot be called yet
;
DOSState proc   near
        push    ax
        push    bx
        push    es
        xor     bx,bx
        cmp     bx,cs:InBIOS    ; carry set if InBIOS != 0
        jc      bad
        les     bx,cs:ErrorModeAddr
        mov     ah,es:[bx]
        les     bx,cs:InDOSAddr
        mov     al,es:[bx]
        xor     bx,bx
        cmp     bx,ax           ; carry set if ax != 0
bad:    pop     es
        pop     bx
        pop     ax
        ret
DOSState endp

;
; DOSVer -- get DOS version number in ah:al (major:minor)
;
DOSVer  proc    near
        push    bx
        push    cx
        mov     ah,30h          ; Get MS-DOS Version Number
        int     21h             ; sets bx=0, cx=0
        xchg    ah,al           ; original order is major:al minor:ah
        pop     cx
        pop     bx
        ret                     ; major:ah minor:al
DOSVer  endp

_TEXT   ends

        end

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?