trap.asm

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

ASM
832
字号
                pop     BP                      ; restore BP
                mov     byte ptr CS:TrapType,TRAP_TERMINATE ; indicate program termintation
                jmp     DebugTask               ; enter the debugger



public          EndUser_
EndUser_        proc    near
                push    DS                      ; save registers
                push    ES
                push    SI
                push    DI
                push    DX
                push    CX
                push    BX
                push    AX
                push    BP
                mov     CS:OurSS,SS             ; mark stack level
                mov     CS:OurSP,SP             ; ...

                ; restore interrupt vectors
                mov     di,cs
                mov     ds,di
                sub     di,di
                mov     es,di
                mov     si,offset SaveVects
                mov     cx,1024/2
                cli
                rep     movsw
                sti

                ; DOS saves the the SS:SP value of a task in its PSP
                ; every time a task invokes int 21H. When a 4CH request
                ; is done DOS uses that stored value for a location to
                ; build the return interrupt frame to restart the parent
                ; task of the one that is being killed. since the
                ; last DOS call we've done might not be as deep in our
                ; stack as we currently are, we have to do a harmless, quick
                ; request so that DOS will set the proper values to restore
                ; SS:SP from (otherwise DOS will write over active stack
                ; locations).
                mov     AH,2CH                  ; get time
                int     21H

                call    near ptr SetUsrTask_    ; we're the user task

clearatask:
                mov     SS,CS:OurSS             ; get our stack back
                mov     SP,CS:OurSP             ; . . .
                call    GetPSP                  ; get current PSP
                cmp     AX,CS:DbgPSP            ; is it the debugger?
                je      allcleared              ; quit loop if so
                mov     DS,AX                   ; get access to PSP
                mov     DS:0AH,offset clearatask; set terminate offset
                mov     DS:0CH,CS               ; set terminate segment
                cli                             ; interrupts off
                mov     SS,AX                   ; set up a safe stack
                mov     SP,100H                 ; . . .
                sti                             ; interrupts on
                mov     AX,4C00H                ; terminate the task
                int     21H

allcleared:
                pop     BP                      ; restore registers
                pop     AX
                pop     BX
                pop     CX
                pop     DX
                pop     DI
                pop     SI
                pop     ES
                pop     DS
                cld
                ret
EndUser_        endp


;   DX:AX has program name, CX:BX has parm block
public          DOSLoadProg_
DOSLoadProg_    proc    near
                push    DS
                push    ES

                mov     CS:TaskPSP,0    ; assume we don't get a task
                mov     ES,CX           ; get parmblock in ES:BX
                mov     DS,DX           ; get file name in DS:DX
                mov     DX,AX           ; . . .
                mov     AX,4B01H        ; load program, maintain control
                int     21H             ; (internal DOS call)

                sbb     DX,DX           ; set DX based on carry

                jne     fini            ; if not equal then we have no task
                call    GetPSP          ; get current PSP
                mov     CS:TaskPSP,AX   ; save task PSP address
                mov     DS,AX           ; get access to new task
                mov     word ptr DS:0AH,offset debugprogend;set new terminate
                mov     DS:0CH,CS                          ; address
                mov     AH,25H          ; set up vectors
                mov     AL,23H          ; set Ctrl/C vector
                mov     DX,offset SetBreak
                push    CS
                pop     DS
                int     21H
                mov     AL,24H          ; set critical error vector
                mov     DX,CrtErrVec+0
                mov     DS,CrtErrVec+2
                int     21H

                call    ClrIntVecs_

                xor     ax,ax           ; get pointer to interrupt table
                mov     es,ax
                SetIntr 08H,TimerHandler

                xor     AX,AX           ; return zero
                xor     DX,DX           ; . . .
fini:
                pop     ES
                pop     DS
                ret
DOSLoadProg_    endp

debugprogend:
                mov     CS:TaskPSP,0            ; don't have a task anymore
                mov     byte ptr CS:TrapType,TRAP_TERMINATE ; program terminated
                jmp     DebugTask


public          SetDbgTask_
SetDbgTask_     proc    near
                push    BX              ; save BX
                mov     BX,CS:DbgPSP    ; tell DOS we're the debugger
                jmp     short SetPSP
SetDbgTask_     endp


DbgDOSCall      macro
                ; do a DOS request, but make sure to use the debugger's
                ; int 21 vector and NOT the program's
                pushf
                call    dword ptr CS:SaveVects+21H*4
                endm

public          SetUsrTask_
SetUsrTask_     proc    near
                push    BX              ; save BX
                mov     BX,CS:CurrPSP   ; tell DOS we're the current task
SetPSP:
                pushf                   ; save flags
                push    AX              ; save AX
                mov     AH,50H          ; set PSP request (internal DOS call)
                DbgDOSCall              ; do the call
                pop     AX              ; restore AX
                popf                    ; restore flags
                pop     BX              ; restore BX
                ret                     ; return
SetUsrTask_     endp


GetPSP          proc    near
                pushf                   ; save flags
                push    BX              ; save BX
                mov     AH,51H          ; get PSP request (internal DOS call)
                DbgDOSCall              ; do the call
                mov     AX,BX           ; put PSP in proper return register
                pop     BX              ; restore BX
                popf                    ; restore flags
                ret                     ; return
GetPSP          endp


public          DOSTaskPSP_
DOSTaskPSP_     proc    near
                mov     AX,CS:TaskPSP
                ret
DOSTaskPSP_     endp


public          DbgPSP_
DbgPSP_         proc    near
                mov     AX,CS:DbgPSP
                ret
DbgPSP_         endp


; return with carry set if we don't want to watch this interrupt
public          ChkInt
ChkInt          proc    near
                cmp     BL,8FH
                jbe     ms_overlay
watch_it:       clc
                ret
ms_overlay:
                cmp     BL,3FH
                je      watch_it
                stc
                ret
ChkInt          endp

EMU_OTHER   equ 3cH
EMU_INT     equ 39H

public          Null87Emu_
Null87Emu_      proc    near
                push    es
                mov     ax,0
                mov     es,ax
                mov     es:[EMU_INT*4+0],ax  ; null out emulator interrupt
                mov     es:[EMU_INT*4+2],ax  ; ...
                pop     es
                ret
Null87Emu_      endp

        public  Read87EmuState_
Read87EmuState_ proc near
        push    ds
        push    bx
        mov     ds,dx
        mov     bx,ax
check_byte label byte
        db      0cdH, 039H, 037H ;fsave   ds:[bx]
        pop     bx
        pop     ds
        call    FPUExpand
        ret
Read87EmuState_ endp

        public  Write87EmuState_
Write87EmuState_ proc near
        call    FPUContract
        push    ds
        push    bx
        mov     ds,dx
        mov     bx,ax
        db      0cdH, 039H, 027H ;frstor  ds:[bx]
        pop     bx
        pop     ds
        ret
Write87EmuState_ endp

public          Have87Emu_
Have87Emu_      proc    near
                push    es
                push    bx
                xor     ax,ax
                mov     es,ax
                les     bx,es:[EMU_INT*4]  ; get emulator interrupt
                _guess
                mov     ax,es
                or      ax,bx           ; is interrupt NULL?
                _quif   e               ; quit if it is
                cmp     byte ptr es:[bx], 0cfH; is it pointing at an iret?
                _quif   e               ; quit if it is
                xor     ax,ax
                push    ax
                mov     ax,es
                pop     es
                cmp     bx,es:[EMU_OTHER*4+0]; are both emu interrupts
                _if     e                   ; pointing at the same thing?
                cmp     ax,es:[EMU_OTHER*4+2]
                _endif
                _quif   e               ; quit if so
                cmp     byte ptr cs:check_byte, 0cdH; has emu fsave been patched?
                _quif   ne              ; quit if so
                mov     ax,1            ; have emulator
                _admit
                xor     ax,ax           ; no emulator
                _endguess
                pop     bx
                pop     es
                ret
Have87Emu_      endp

_TEXT           ends

⌨️ 快捷键说明

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