#include #a simple demo of how you can use the structured exception handling facilities #of Windows in your application #seh is complex and I dont claim to fully understand it. If you are interested #the MSDN website has some articles on seh topics (A Crash Course on the Depths of Win32 Structured Exception Handling, MSJ January 1997.htm) #The exception handler is setup at the beginning of the winmain function; #when an exception occurs this function is called by the system #It gives a chance to somehow gracefully handle the exception and recover #if possible, without crashing or freezing the program or system. #these examples are a bit deceptive because the problem they are going #to create is known. Instead of using seh maybe some protective coding #like checking for 0 before dividing, would have done the job. #the solution shown for the divide error is to sort of skip over the instruction #This maybe saves the embarassment of your program being rudely shunted out #of memory by the system with the 'illegal action' box. But in a real world program #this kind of skipping over may not be desirable as it could lead to #other subtle errors. It would perhaps be better to know the exceptions #your program generates and do some protective coding #Please drop me an email for any clarifications,suggestions,comments begin imports [Kernel32.dll] RaiseException GetModuleHandleA GetCommandLineA ExitProcess [user32.dll] MessageBoxA RegisterClassExA CreateWindowExA ShowWindow UpdateWindow DefWindowProcA GetMessageA TranslateMessage DispatchMessageA SendMessageA LoadCursorA LoadIconA BeginPaint EndPaint PostQuitMessage [crtdll.dll] memcpy memset _itoa malloc end imports #-----------------Constants---------------------------------------------- begin const #many of these constants are not used in this app SW_HIDE 0 SW_SHOW 5 WS_CHILD 1073741824 WS_VISIBLE 268435456 WS_BORDER 8388608 WS_HSCROLL 1048576 WS_VSCROLL 2097152 WS_CAPTION 12582912 WS_CHILDWINDOW 1073741824 WS_OVERLAPPEDWINDOW 13565952 WS_POPUPWINDOW 2156396544 ES_MULTILINE 4 WM_CREATE 1 WM_COPY 769 WM_CUT 768 WM_PASTE 770 WM_CLOSE 16 WM_COMMAND 273 WM_DESTROY 2 WM_ENABLE 10 WM_GETTEXT 13 WM_GETTEXTLENGTH 14 WM_INITDIALOG 272 WM_INITMENU 278 WM_KEYDOWN 256 WM_KEYUP 257 WM_KILLFOCUS 8 WM_LBUTTONDBLCLK 515 WM_LBUTTONDOWN 513 WM_LBUTTONUP 514 WM_MOVE 3 WM_NOTIFY 78 WM_PAINT 15 WM_ACTIVATE 6 WM_QUIT 18 WM_RBUTTONDBLCLK 518 WM_RBUTTONDOWN 516 WM_RBUTTONUP 517 WM_SETFOCUS 7 WM_SETFONT 48 WM_SETTEXT 12 WM_SIZE 5 WM_TIMER 275 WM_UNDO 772 WS_SYSMENU 524288 IDI_APPLICATION 32512 IDC_CROSS 32515 WS_CLIENTEDGE 512 WS_MINIMIZEBOX 131072 WS_MAXIMIZEBOX 65536 end const #-----------------Data Section------------------------------------------- begin data dword hwndMain 0 string Class Window dword hInstance 0 string ClassName WinClass string AppName SEH ! string WindowCaption Basic Structured Exception Handling ! string hextable 0123456789ABCDEF sequence asci 24 dword CommandLine 0 sequence msg 28 dword sesp 0 dword sebp 0 sequence ibuf 24 string btext1 Divide by 0 string btext2 Memory access violation dword fault 0 string btn button dword hbtn1 0 string ok Recovered from exception ! dword mem 0 string crlf 00 string Excep Exception : string atip at IP: dword sedi 0 dword hbtn2 0 dword dataend 4294967295 end data #------------------------------------------------------------------- begin code jmp exit proc NumToHex dword n dword num 0 push ebp mov ebp esp add esp -12 #fill with string 0's invoke memset asci 0 32 mov edi asci mov al 48 mov [num] 0 nhex_beg: mov [edi] al inc edi inc [num] cmp [num] 8 jne nhex_beg mov ecx 16 mov edi asci add edi 7 mov eax [n] nhex: xor edx edx div ecx mov esi hextable add esi edx mov bl [esi] mov [edi] bl dec edi cmp eax 16 jg nhex if eax=16 eax=1 endif mov esi hextable add esi eax mov bl [esi] mov [edi] bl mov eax asci leave ret 4 endp #------------------------------------------------------------------------ proc strlen dword q push ebp mov ebp esp mov edi [q] mov eax 0 mov ecx 0 cld search_loop: inc ecx scasb jne search_loop dec ecx mov eax ecx leave ret 4 endp #------------------------------------------------------------------------ proc strcat dword s1 dword s2 dword len1 0 dword len2 0 dword addr 0 dword len 0 push ebp mov ebp esp add esp -48 invoke strlen [s1] mov [len1] eax invoke strlen [s2] mov [len2] eax add eax [len1] inc eax len = eax invoke [malloc] eax invoke memset eax 0 len mov [addr] eax mov edi eax mov ecx [len1] mov esi [s1] rep_movsb mov ecx [len2] mov esi [s2] rep_movsb mov eax [addr] leave ret 8 endp #------------------------------------------------------------------------ proc ExceptHandler dword er dword ef dword cr dword dc #this function is called by Windows when there is an exception. #it is setup with windows in winmain dword st 0 push ebp mov ebp esp add esp -24 fault=1 eax=[ebp+8] #get address of exception record ebx=[eax] # the first member gives the exception code invoke NumToHex ebx st=strcat Excep eax st=strcat st atip eax=[ebp+8] add eax 12 ebx=[eax] # this member gives the address of the instruction invoke NumToHex ebx # at which the exception occured st=strcat st eax invoke MessageBoxA hwndMain st AppName 0 #go to a safe place to continue execution.These values have been previously stored eax=[ebp+16] add eax 180 ebx=sebp [eax]=ebx add eax 4 [eax]=4198400 #the first instruction after 'begin code' address 401000 hex add eax 12 #beginning of code section ebx=sesp [eax]=ebx eax=[ebp+16] add eax 156 ebx=sedi [eax]=ebx eax=0 #reload context & continue execution leave #ret 16 endp #------------------------------------------------------------------------- proc WndProc dword hwnd dword msg dword wparam dword lparam #the window procedure dword hdc 4 sequence ps 64 sequence rect 16 dword ordata 0 dword n 0 dword m 0 dword x 0 dword y 0 push ebp mov ebp esp add esp -180 cmp msg {WM_CREATE} je wmcreate cmp msg {WM_PAINT} je wmpaint cmp msg {WM_COMMAND} je wmcommand cmp msg {WM_DESTROY} jne default push 0 call PostQuitMessage jmp exit wmcreate: mov eax {WS_CHILD} or eax {WS_BORDER} or eax {WS_VISIBLE} ordata= eax invoke CreateWindowExA 0 btn btext1 ordata 20 40 200 25 hwnd 0 hInstance 0 mov hbtn1 eax #invoke SendMessageA [____] {WM_SETFONT} hfont_ 0 invoke CreateWindowExA 0 btn btext2 ordata 20 70 200 25 hwnd 0 hInstance 0 mov hbtn2 eax jmp exit wmpaint: lea eax ps invoke BeginPaint hwnd eax mov hdc eax lea eax ps invoke EndPaint hwnd eax jmp exit wmcommand: sebp=ebp #the safe ebp,esp and edi to return to sesp=esp sedi=edi btn1: mov eax [hbtn1] cmp [lparam] eax jne btn2 eax=10 #div by 0 error ecx=0 #invoke memcpy esi edi 256 div ecx jmp exit btn2: mov eax [hbtn2] cmp [lparam] eax jne default #invoke RaiseException 48 1 0 0 eax=0 #creation of memory access violation error [eax]=0 jmp exit default: invoke DefWindowProcA hwnd msg wparam lparam leave ret 16 exit: if fault=1 invoke MessageBoxA hwnd ok AppName 0 fault=0 endif xor eax eax leave ret 16 endp #------------------------------------------------------------------------ proc WinMain dword hinst dword previnst dword comline dword cmdshow #the first called procedure of a Windows program sequence wc 48 dword ordata 0 dword len 0 push ebp mov ebp esp add esp -80 sebp=ebp sesp=esp #sedi=edi #these instructions install the exception handler push ExceptHandler installH [wc]= 48 [wc+4] =3 [wc+8]= WndProc #the address of the window procedure [wc+12]= 0 [wc+16] =0 eax =[hInstance] [wc+20]= eax push 1 push [hInstance] call [LoadIconA] [wc+24]= eax [wc+44]= eax push {IDC_CROSS} push 0 call [LoadCursorA] [wc+28] =eax [wc+32]= 16 [wc+36]= 0 [wc+40]= ClassName lea eax wc invoke RegisterClassExA eax eax={WS_CAPTION} or eax {WS_SYSMENU} or eax {WS_MINIMIZEBOX} #or eax {WS_MAXIMIZEBOX} ordata=eax invoke CreateWindowExA {WS_CLIENTEDGE} ClassName WindowCaption ordata 50 50 250 200 0 0 hInstance 0 hwndMain= eax push 1 push hwndMain call ShowWindow push hwndMain call UpdateWindow MsgLoop: #setting up the message loop invoke GetMessageA msg 0 0 0 cmp eax 0 je exitprocess invoke TranslateMessage msg invoke DispatchMessageA msg jmp MsgLoop exitprocess: mov eax [msg+8] leave ret 16 endp #------------------------------------------------------------------------ EntryPoint push 0 call GetModuleHandleA mov hInstance eax call GetCommandLineA #not really necessary if there's no command line mov CommandLine eax invoke WinMain hInstance 0 CommandLine 10 push eax #return from winmain when program closes call ExitProcess end code #-----------------Resources--------------------------------------- begin resources icon win32app.ico end resources