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 + -
显示快捷键?