; ; GRDB ; ; Copyright(c) LADsoft ; ; David Lindauer, gclind01@starbase.spd.louisville.edu ; ; ; mtrap.asm ; ; Function: handle the all traps. Int 3 and Int 1 are debug traps and ; are handled specially ;MASM MODE .model small .386 include version.asi include prints.ase include regs.ase include input.ase include breaks.ase include env.ase include loader.ase include logging.ase include dos.ase include Memory.ase include ints.ase include exec.ase include options.ase include loader.ase include history.ase include swift.ase include fp.ase public entry3,indos,entry1 PUBLIC reflags,dreax,drebx,drecx,dredx PUBLIC dresi,dredi,drebp PUBLIC dresp,dreip PUBLIC drcs,dres,drds,drss,drfs,drgs PUBLIC TrapHandler, _exit, psp PUBLIC reentry, grdbname, veclist, entry1 PUBLIC stackseg,stackofs, dosver extrn checkcpu : PROC, FileLoadErr : PROC, trapcount : dword extrn ReTrap : PROC ; ; CPU instruction trap enable flag ; TRAPFLAG = 100h ustack segment para PUBLIC use16 STACK 'STACK' db 2048 DUP (?) ustack ends .data stackofs dw 0 stackseg dw 0 ; ; Register image ; veclist db 00h dw entry0 db 1 dw entry1 db 3 dw entry3 db 1bh dw int1bh db 20h dw int20handle db 21h dw int21handle db 0ffh ; trailer reflags dd 0 dreax dd 0 drebx dd 0 drecx dd 0 dredx dd 0 dresi dd 0 dredi dd 0 drebp dd 0 dresp dd 0 dreip dd 0 drcs dw 0 dres dw 0 drds dw 0 drss dw 0 drfs dw 0 drgs dw 0 ; dosver dw 0 haserr dw 0 ; If there is an error# on stack errnum dw 0 ; The error# trapnum dw 0 ; The trap# indos dd 0 ; pointer to indos flag grdbname db '********',0 psp dw 0 neederr db 0 trappop dd 6790h .code cpuerr db "GRDB requires a 386 or better processor",0 memerr db "not enough memory/corrupt arena",0 vererr db "GRDB requires MSDOS 4.0 or better" nomsg db 0 entry macro num entry&num: if num EQ 1 call swiftrace endif if num EQ 3 call swiftrace endif push gs push fs push es push ds pushad mov al,num jmp traphandler endm entry 0 entry 1 entry 3 ; ; Save an image of the regs ; This MUST BE the first thing the trap handler calls; it assumes ; there is ONE PUSH (return address) followed by the DS at the time ; of interrupt followed by the interrupt data ; saveregs PROC pop cx pop [dredi] pop [dresi] pop [drebp] pop eax pop [drebx] pop [dredx] pop [drecx] pop [dreax] pop [drds] pop [dres] pop [drfs] pop [drgs] bt [haserr],0 ; See if an error jnc short noerr ; pop eax ; Get the error # mov [errnum],ax ; noerr: pop word ptr [dreip] pop [drcs] pop word ptr [reflags] mov ax,ss ; Otherwise just save the current mov [drss],ax ; stack pointer before we started pushing mov [dresp],esp ; jmp cx saveregs ENDP ; ; Adjust EIP to the trap if it's not int 3 ; adjusteip PROC cmp [trapnum],3 ; See if int 3 jnz short noadj ; No, get out mov ebx,[dreip] ; mov fs,[drcs] ; cmp BYTE PTR fs:[bx-1],0cch ; See if is an INT 3 jz short nodecrement ; Get out if so dec word ptr [dreip] ; Else point at trap nodecrement: noadj: ret adjusteip ENDP ; ; Generic trap handler ; traphandler PROC cld sti mov bx,dgroup mov ds,bx mov es,bx mov [dxbrk],0 movzx eax,al mov [trapnum],ax bt [trappop],eax jnc noerr2 inc [haserr] ; Set the error flag noerr2: mov si,offset dgroup : veclist call ReleaseRMInts call saveregs ; Save Regs and [reflags],NOT TRAPFLAG ; reset trap flag in flags image mov ss,[stackseg] ; load our stack movzx esp,[stackofs] ; clear top of ESP just in case... call disableBreaks ; Disable breakpoints if not call adjusteip ; Adjust the EIP to point to the breakpoint call SetDebugPSP call crlf cmp [trapnum],3 ; No stats if it is int 3 jz short reentry ; cmp [trapnum],1 ; Or int 1 jz short reentry ; Msg <'Trap: '> mov ax,[trapnum] ; Say which one call printbyte ; call crlf btr [haserr],0 ; If has error jnc reentry ; Msg <'Error: '> mov ax,[errnum] ; Say which one call printword call crlf reentry: call DisplayRegisters; Display registers test [trapcount],-1 jz noretrace dec [trapcount] jmp ReTrap noretrace: test [neederr],-1 jz InputHandler mov ah,[neederr] mov [neederr],0 sahf call FileLoadErr jmp InputHandler ; Go do input traphandler ENDP ; ; Monitor init routine, point all traps to point to the monitor handler ; start: mov bx,dgroup ; setup mov ds,bx mov [psp],es ; our PSP mov es,bx mov ax,ss ; have to adjust stack to be DS-relative sub ax,bx ; the disassembler requires it shl ax,4 add ax,sp mov ss,bx mov sp,ax mov [stackseg],ss mov [stackofs],sp Msg <"GRDB version ",30h +VERID/10,'.',30h + VERID MOD 10, " Copyright (c) LADsoft",13,10,13,10> mov ah,30h ; dos version check int 21h cmp al,4 mov dx,offset _text : vererr jc errx xchg ah,al mov [dosver],ax push es ; get indos flag mov ah,34h int 21h mov word ptr [indos],bx mov word ptr [indos+2],es pop es call checkcpu ; validate CPU mov dx,offset _text : cpuerr jc errx call ResizeMem ; cut mem back mov dx,offset _text:memerr jc errx call InitHandles ; make us an extended handle ; table... I think we do this ; because DOS won't copy an ; extended table during ; PSP creation but I forget call IntSnapshot ; grab the ints so we can ; restoire context later mov dx,offset _text : memerr jc errx2 mov si,offset dgroup:grdbname ; create data spaces for call MakeEmptyProg ; empty prog mov dx,offset _text : memerr jc errx2 call ReadOptions ; read the options disk file call FloatCheck ; check for an FP coprocessor push ds ; parse command line params mov ds,[psp] mov si,81h call ParseProgName pop ds test [opthist],0ffh ; init history jz nohist call LoadHistory nohist: test [loadfile],-1 ; load program jz reentry sub ax,ax call LoadProgram lahf mov [neederr],ah jmp reentry ; get us started ; ; program exit ; _exit: call KillFiles ; close files they opened call CloseLogFile ; close our log file mov dx,offset _text : nomsg errx2: push dx call UnLoadInts ; unload int vects call ReleaseMemory ; release any memory tagged ; to them call ReleaseDebugMem ; release any memory tagged ; to us call WriteOptions ; write options file pop dx errx: mov bx,dx call olMessage mov ax,4c00h int 21h END start