"Use of GoBug" demonstrations
Exceptions

These tests demonstrate what happens when the debuggee causes an exception (either intentionally or unintentionally).

To run a test, start Testbug as the debuggee and press F9 (run in background) from "MAIN". Then choose one of Testbug's menu items in "Use of GoBug, exceptions ..".

The unintentional exceptions (usually memory page faults or divide by zero) make GoBug's exception dialog appear, and details also appear in the log. With these exceptions the instruction has not been carried out, and the system gives the debugger an early chance to deal with the matter. The exception dialog gives you a choice of jumping over the exception (the instruction causing the exception is not executed at all), ignoring the exception (the instruction is executed), or time to think (GoBug just waits in the debug loop for the next action key).
Other types of exceptions are deliberate, for example, an INT3 in the code, or DebugBreak which is the system's own equivalent (it just calls code with an INT3!). These exceptions act as breakpoints - the code just stops at the breakpoint and the debuggee goes into the debug loop.
Another deliberate exception is RaiseException, which can be used by an application to call its own exception handling code or a debugger. Note that in this case the exception occurs after RaiseException has returned.
Note that Testbug does not have an exception handler, so these tests do not cover what happens if an application's own handler deals with an exception. For that, see my article in Except.zip available for download from my web site.
   Exception 80000005h (memory read/write)
   Exception 0C0000094h (divide by zero)
   Exception 0C0000095h (divide resulting in overflow)
   INT3 in code (probably put in intentionally)
   Calling RaiseException (definitely put in intentionally)
   Calling DebugBreak (definitely put in intentionally)
   Own single-stepping test (using an INT3 and handler combination)
   Output string sent by calling OutputDebugString (definitely put intentionally)

Exception 80000005h (memory read/write)
This test uses this code which is self-explanatory:-

EXCEPTION_MEM:
MOV ESI,-1
MOV EAX,[ESI]
RET

Exception 0C0000094h (divide by zero)
This test uses this code which is self-explanatory:-

EXCEPTION_DIV:
XOR ECX,ECX
XOR ECX,ECX
XOR ECX,ECX
DIV ECX                 ;divide by zero exception
RET
Avoid such exceptions by always testing the divisor for zero before the DIV:-
JECXZ >L4
DIV ECX
L4:

Exception 0C0000095h (divide resulting in overflow)
This test uses this code. There is an overflow because you are trying to divide an enormous number in edx:eax by 10 and the result will not fit into a single 32-bit register.

EXCEPTION_DIVOVER:
MOV EDX,-1
MOV EAX,-1
MOV ECX,10D
DIV ECX                 ;overflow exception
RET
Avoiding these exceptions is more difficult, but when the divisor is known you should always check the dividend immediately prior to the divide to make sure there will be no overflow. Also don't forget to clear edx if you are doing a 32-bit divide. Remember when using DIV ECX, the dividend is edx:eax not eax.

INT3 in code (probably put in intentionally)
This simply stops the debuggee in its tracks. It comes into GoBug's debug loop immediately after the INT3.

INT3_TEST:
INT 3
MOV ECX,3
L10:
CMP EAX,EAX
LOOP L10
RET

Calling RaiseException
This API is normally used to send a private exception to the calling application's own handler. For example the handler might be in charge of allocating more memory if required. RaiseException could be called to ask the handler to establish memory in the first place. Under debuggee control, the exception comes into GoBug on the return from the API call.

RAISE_EXCEPTION:
PUSH 0,0,0,22222h
CALL RaiseException
RET

Calling DebugBreak (definitely put in intentionally)
This is the system's version of INT3. In this case there is an INT3 actually within the API. GoBug will therefore show the break in shared code, inside the API. You will have to single-step out of the API to get back to Testbug's code.

DEBUGBREAK_TEST:
CALL DebugBreak
MOV ECX,3
L12:
CMP EAX,EAX
LOOP L12
RET

Own single-stepping test (using an INT3 and handler combination)
Thanks to Bill Welhelm, Jr (May 1999) for this idea. Using this code you don't need a debugger at all to make your code single-step. This works by establishing an exception handler and inserting an INT3 at the beginning of the code you wish to check. The system calls the handler when the INT3 is reached. The handler then sets the trap flag in the register context and returns to the system. Since the trap flag is now set, the next instruction also comes into the handler. And so on until the correct number of instructions have past. Here the handler's output is drawn to the screen using a tester window (details of this tester code are in GoBug's help "other techniques to try"). For more information about exception handlers see my paper Except.zip.

SS_HANDLER:
PUSH EBP
MOV EBP,ESP
PUSH EBX,EDI,ESI        ;save registers as required by Windows
MOV EBX,[EBP+8]         ;get exception record in ebx
TEST D[EBX+4],01h       ;see if its a non-continuable exception
JNZ >L14                ;yes
TEST D[EBX+4],02h       ;see if EH_UNWINDING
JNZ >L14                ;yes
MOV ESI,[EBP+10h]       ;get context record in esi
MOV EAX,[EBX]           ;get ExceptionCode
CMP EAX,80000004h       ;see if here because trap flag set
JZ >L10                 ;yes
CMP EAX,80000003h       ;see if its own INT 3 inserted to single-step
JNZ >L14                ;no
;***** note eip is now one after INT 3 - so may just continue ...
L10:
DEC SSCOUNT             ;stop when correct number done
JZ >L12
OR D[ESI+0C0h],100h     ;set trap flag in context
L12:
MOV EAX,[ESI+0B8h]      ;get eip
CALL TESTER             ;write eip to the screen
XOR EAX,EAX             ;eax=0 reload context and return to system
JMP >L17
L14:
MOV EAX,1               ;eax=1 system to go to next handler
L17:
POP ESI,EDI,EBX
MOV ESP,EBP
POP EBP
RET
;
SINGLE_STEPTEST:
PUSH EBP,0,0            ;save ebp, area for flags, no safe place message pointer required
PUSH OFFSET SAFE_PLACE
PUSH OFFSET SS_HANDLER
PUSH FS:0
MOV FS:0,ESP            ;point to structure just established on the stack
;******************* 
MOV SSCOUNT,5           ;do 5 visits to the handler
INT 3                   ;cause visit to the handler now
MOV EAX,4444h           ;
MOV ECX,EAX             ;  here is the code
SHL ECX,2               ;  which will be
PUSH ECX                ;  single-stepped  
POP ECX                 ;  by the handler
;*******************
SAFE_PLACE:
POP FS:0                ;restore original exception handler from stack
ADD ESP,14h             ;throw away remainder of ERR structure made earlier
RET

Output string sent by calling OutputDebugString (definitely put intentionally)
I suppose this might be useful if you wanted quickly to receive some information from the debuggee during testing that was difficult to obtain in other ways.

OUTPUT_STRING:
PUSHS 'Hello from debuggee! (ansi string)',
CALL OutputDebugStringA
RET