Structured Exception Handling in Assembly Language
====

Overview

Windows 95 and Windows NT support a robust approach to handling exceptions, called Structured Exception Handling, which involves cooperation of the operating system but also has direct support in the programming language.

An “exception” is an event that is unexpected or disrupts the ability of the process to proceed normally. Exceptions can be detected by both hardware and software

You can write more reliable code with Structured Exception Handling. You can ensure that resources, such as memory blocks and files, are properly closed in the event of unexpected termination.

A distinctive feature of Structured Exception Handling is that after an exception handler is installed, it can handle the exception no matter how many other functions are called. Thus, function A can handle an exception raised inside a function called by A.

The following macros make it easy to include Structure Exception Handling in your Assembly programs. Each assembly statement has comments describing the operation being performed.
SEH Macros@TRY_BEGIN MACRO Handler
 	pushad	;;Save Current State
 	mov esi, offset Handler	;;Address of New Exception Handler
 	push esi	;;Save Old Exception Handler
 	push dword ptr fs:[0]	;;Install New Handler
 	mov dword ptr fs:[0], esp	 
ENDM
@TRY_EXCEPT MACRO Handler
 	jmp NoException&Handler	;;No Exception Occured, so jump over
Handler:	mov esp, [esp + 8]	;;Exception Occured, Get old ESP
 	pop dword ptr fs:[0]	;;Restore Old Exception Handler
 	add esp, 4	;;ESP value before SEH was set
 	popad	;;Restore Old State
ENDM
@TRY_END MACRO Handler
 	jmp ExceptionHandled&Handler	;;Exception was handled by @TRY_EXCEPT
NoException&Handler:	 	;;No Exception Occured
 	pop dword ptr fs:[0]	;;Restore Old Exception Handler
 	add esp, 32 + 4	;;ESP value before SEH was set. 32 for pushad and ...
ExceptionHandled&Handler:	 	;;...4 for push offset Handler. (No Restore State)
 	 	;;Exception has been handled, or no exception occured
ENDM

Using SEH Macros

The above macros are used in the following way@TRY_BEGIN HandlerName	 
 	;Code in this place will be checked for exceptions.
@TRY_EXCEPT HandlerName	 
 	;Code in this place will be executed if an exception occurs.
@TRY_END HandlerName	 
 	;Normal execution path

Sample Program;Structured Exception Handling in Assembly
;
;To Compile this program, you need the 32-bit version of Turbo Assembler
;
;TASM32 /ml SEH
;TLINK32 SEH,SEH,,IMPORT32.LIB

.386p
.model flat ,stdcall

EXTRN ExitProcess:PROC
EXTRN MessageBoxA:PROC

;Define the @TRY_BEGIN, @TRY_EXCEPT and @TRY_END Macros Here

.data 
 	szCaption	db	'SEH in Assembly', 0
 	szException	db	'Exception has been handled !!', 0dh, 0ah
 	 	db	'Press OK to terminate gracefully', 0
 	szNoException	db	'No Exception occured', 0

.code

WinMain:

@TRY_BEGIN Zero_Address_Access 
 	mov	ebx, 0	;Prepare to write to address 0
 	mov	[ebx], ebx	;Write to address 0 (Access Violation)
 	;Comment the above line if to remove the exception
@TRY_EXCEPT Zero_Address_Access
 	;This code will get executed if an exception occurs.
 	call	MessageBoxA, 0, offset szException, offset szCaption, 0
 	jmp	ExitProgram
@TRY_END Zero_Address_Access
 	;Normal Execution Path.
ExitProgram:	 
 	call	MessageBoxA, 0, offset szNoException, offset szCaption, 0
 	call	ExitProcess, 0
END WinMain