; ; GRDP ; ; Copyright(c) LADsoft ; ; David Lindauer, gclind01@starbase.spd.louisville.edu ; ; ; EXEC.ASM ; ; Function: Handle T,G,P commands ; ;MASM MODE .model small .386 include prints.ase include input.ase include mtrap.ase include breaks.ase include dos.ase include ints.ase include regs.ase include swift.ase TRAPFLAG = 100h ; 80386 trap enable flag PUBLIC go,trap, proceed, ReTrap, TrapCount, callcheck, cmpstring, wadeprefix .data trapcount dd 0 pff dw 0 ; flag if 67h prefix found pretab db 0f0h,0f2h,0f3h,026h,02eh,036h,03eh,064h,065h,066h,067h stringtab db 0a6h,0a7h,6ch,6dh db 0ach,0adh,0a4h,0a5h db 06eh,06fh,0aeh,0afh db 0aah,0abh .code ; assume ds:nothing ; going to call from where DS is moot ; callcheck proc mov ah,fs:[bx] ; Load the first byte of the instruction cmp ah,0ceh ; into? mov al,1 jz chx cmp ah,0cdh ; Interrupt ? mov al,2 ; two bytes jz chx ; I do this because some int calls are ; misbehaved and won't restore the trap flag cmp ah,0e8h ; Near Call? mov al,3 ; Yes, this is 3 bytes jz chx ; And execute it cmp ah,09ah ; Far call mov al,5 ; This one is 5 bytes jz chx ; Not either of these, just trap mov ax,fs:[bx] and ax,038FFH cmp ax,010ffh jz gotind cmp ax,018ffh jz gotind ret gotind: mov al,2 ; two bytes base mov ah,fs:[bx+1] and ah,0c7h cmp ah,0c0h ; mod 3, through reg is 2 bytes jnc chx test [pff],0ffh ; check 16/32 address mode flag jnz call32 cmp ah,8 ; 16 bit, MOD=0 jnc chk16m1 cmp ah,6 ; yes, direct offset? jnz chx add al,2 ; yes 4 bytes total jmp chx chk16m1: and ah,0c0h ; check for mod 1 or 2 js is16m2 inc al ; mod 1, add a byte for offset jmp chx is16m2: add al,2 ; else mod 2, two byte offset jmp chx call32: cmp ah,6 ; 32 bit mode, check for 32-bit offset jnz ch32m0 add al,4 ; yep, add 4 jmp ch32sib ch32m0: cmp ah,8 ; MOD = 0? jc ch32sib ; yep, check for sib ch32m1: or ah,ah ; MOD = 1? js ch32m2 add al,1 ; yep, 1 byte offset jmp ch32sib ch32m2: add al,4 ; else mod 2 ch32sib: and ah,7 cmp ah,4 jnz chx inc al ; add in the SIB byte mov ah,byte ptr fs:[ebx+1] ; test for MOD 3 and ah,0c0h cmp ah,0c0h jz chx ; yep, no further bytes mov ah,byte ptr fs:[ebx+2] ; get SIB byte and ah,7 ; check for EBP special cases cmp ah,5 jnz chx inc al test byte ptr fs:[ebx+1],40h ; check if one or 4 bytes disp jz chx add al,3 ; MOD 1,3, need 4 bytes chx: sub ah,ah ; clear Z flag... ret callcheck endp ; used by P command to wade through prefixes to find out if ; we have a string instruction ; wadeprefix: mov [pff],0 sub dx,dx wp_lp: mov al,fs:[bx] mov di,offset dgroup:pretab mov cx,11 repnz scasb jnz wp_done inc bx inc dx cmp al,67h jnz wp_lp bts [pff],0 ; flag the addrsiz in case of call jmp wp_lp wp_done: ret cmpstring: mov al,fs:[bx] mov di,offset dgroup:stringtab mov cx,14 repnz scasb ret ; assume ds:dgroup ; DS ok again ; ; Execute program ; go PROC Call WadeSpace ; Wade till address jz dogo cmp al,'=' jnz checkbreak inc si call ReadAddress jc goerr mov word ptr [dreip],bx ; Fix CS:EIP for new routine or edx,edx ; jz short checkbreak; mov [drcs],dx ; checkbreak: call WadeSpace ; Wade jz short dogo ; call ReadAddress ; Read break address jc goerr ; Quit if errir dogo2: sub ax,ax ; Break 0 call SetBreak ; Set the break dogo: call EnableBreaks ; Enable breaks xor ax,ax ; Not trapping jmp gotrap ; Run the code go ENDP ; ; ; Limited and semi-buggy proced function ; PROCEED PROC call WadeSpace jz pok cmp al,'r' jnz goerr inc si call WadeSpace jnz goerr mov cs:[traceon],1 jmp gotrap pok: movzx ebx,word ptr [dreip] ; mov fs,[drcs] ; call wadeprefix ; wade through all prefixes call callcheck ; noew check for near & far calls jz short pgo ; and execute it cmp ah,0e0h ; Check for loop instructions jz short pgo cmp ah,0e1h jz short pgo cmp ah,0e2h jz short pgo call cmpstring ; see if is string instruction or loop jnz short dotrap ; Not either of these, just trap mov ax,dx inc ax pgo: sub ah,ah movzx ebx,word ptr [dreip] ; add bx,ax ; Ebx = breakpoint mov dx,[drcs] ; DX:EBX = position to break at sub ax,ax ; Use the scratch breakpoint call SetBreak ; Set a break call EnableBreaks ; Enable breakpoints sub ax,ax ; No trapping jmp gotrap ; Run the code PROCEED ENDP ; ; Trap command ; trap PROC call WadeSpace jz dotrap call ReadNumber jc goerr push eax call WadeSpace pop eax jnz goerr or eax,eax jz dotrap dec eax mov [trapcount],eax dotrap: mov fs,[drcs] ; mov bx,word ptr [dreip] ; mov ah,fs:[bx] ; Load the first byte of the instruction cmp BYTE PTR fs:[bx],0cdh jnz ReTrap mov al,byte ptr fs:[bx+1] cmp al,20h jz dosvec cmp al,21h jnz ReTrap mov ebx,cs:[int21adr] jmp gotadr dosvec: mov fs,[intpage] shl bx,2 mov ebx,fs:[bx] gotadr: movzx bx,al ; trying to trace through a DOS push es ; vector bypasses our hook mov es,[drss] mov di,word ptr [dresp] sub [dresp],6 std scasw mov ax,word ptr [reflags] stosw mov ax,[drcs] stosw mov ax,word ptr [dreip] add ax,2 stosw cld pop es mov word ptr [dreip],bx shr ebx,16 mov [drcs],bx call DisplayRegisters; Display registers clc ret ReTrap: mov ax,TRAPFLAG ; Are trapping on instruction gotrap: push ax mov si,offset dgroup : veclist ; enable ints call SetRMInts pop ax mov ss,[drss] mov esp,[dresp] ; Load toss or ax,word ptr [reflags] ; Fill stack frame with FLAGS , CS:EIP push ax ; call SetUserPSP push [drcs] push word ptr [dreip] push [drds] mov es,[dres] mov fs,[drfs] mov gs,[drgs] mov eax,[dreax] ; Load regs mov ebx,[drebx] ; mov ecx,[drecx] ; mov edx,[dredx] ; mov esi,[dresi] ; mov edi,[dredi] ; mov ebp,[drebp] ; pop ds ; Load DS test cs:[traceon],1 ; if PR go handle first instruction jz doiret call swiftrace call DisplayRegisters; if it was an int 3 come back clc ret doiret: iret goerr: stc ret TRAP ENDP end