这个是以前做的,发在了MASM32论坛上。现在转回到自己的博客上来。。适合32位windows。
这些宏的实现是利用了“函数嵌套函数”方式。在我知道的所有语言里,只有汇编语言里可以实现函数嵌套函数。
另外Linux也有类似的SEH方式,是通过sigsetjmp方式,先把我的旧文章发了再提下。。
==========================================
Hope these macors will help you.
Use these SEH macros,you can use C++ like syntax to catch and handling the exceptions.The syntax like this:
__try exceptionid ;code snippet which may cause exceptions __catch exceptionid ;code snippet will execute when the exception is caught __finally exceptionid ;end the exception caught
the exceptionid is programmer defined string and a __try-__catch-__finally block must use the same exceptionid.
The macros will use the exceptionid to define global labels,so different __try-__catch__finally block must use different exception ids.
The __try-__catch-__finally block can be nested like this:
__try e1 ;your code __catch e1 __try e2 ;your code __catch e2 ;your code __finally e2 __finally e1
if you want to throw an exception,the easiest way is read or write null pointer
———————————–SEH macros—————————————-
;SEH macros for masm32 ;by hoverlees 2009 ;email: me[at]hoverlees.com comment ~ Hope these macors will help you. Use these SEH macros,you can use C++ like syntax to catch and handling the exceptions.The syntax like this: ******************************************************************************** __try exceptionid ;code snippet which may cause exceptions __catch exceptionid ;code snippet will execute when the exception is caught __finally exceptionid ;end the exception caught ******************************************************************************** the exceptionid is programmer defined string and a __try-__catch-__finally block must use the same exceptionid. The macros will use the exceptionid to define global labels,so different __try-__catch__finally block must use different exception ids. The __try-__catch-__finally block can be nested like this: ******************************************************************************** __try e1 ;your code __catch e1 __try e2 ;your code __catch e2 ;your code __finally e2 __finally e1 ******************************************************************************** ~ IFNDEF IN_HOVERLEES_SEH IN_HOVERLEES_SEH equ 1 IFNDEF SEH SEH struct PrevLink dd ? CurrentHandler dd ? SafeOffset dd ? PrevEsp dd ? PrevEbp dd ? SEH ends ENDIF __try macro exceptionid assume fs:nothing push fs:[0] mov eax,esp push fs:[0] push ebp push eax push __finally_&exceptionid push __exception_&exceptionid push eax mov fs:[0],esp assume fs:ERROR endm __catch macro exceptionid add esp,sizeof SEH+4 jmp __finally_&exceptionid __exception_&exceptionid: push ebp mov ebp,esp mov edx,[ebp][12] assume edx:ptr SEH mov eax,[ebp][16] assume eax:ptr CONTEXT push [edx].SafeOffset pop [eax].regEip push [edx].PrevEsp pop [eax].regEsp push [edx].PrevEbp pop [eax].regEbp endm __finally macro exceptionid mov eax,ExceptionContinueExecution pop ebp retn 16+sizeof SEH __finally_&exceptionid: assume fs:nothing pop fs:[0] assume fs:error endm ENDIF
———————————————————————————————
===========================================
linux的SEH例子如下(C语言):
#include <stdio.h> #include <setjmp.h> #include <signal.h> static sigjmp_buf jmpbuf; void sig_fpe(int signo){ siglongjmp(jmpbuf,1); } int main(int argc, char *argv[]){ signal(SIGFPE, sig_fpe); if (sigsetjmp(jmpbuf,1) == 0){ int s=1/0; } else{ printf("catch exception\n"); } }
linux这种方式也是差不多的,按我的理解,signal注册回调函数那儿应该是维护一张全局表,sigsetjmp应该是按下面的步骤走的:
sigsetjmp{
1.保存CPU各寄存器状态,然后把第3步的程序起始地址到jmpbuf中。
2.返回0
3.恢复CPU寄存器状态
4.返回1
}
当CPU出现异常中断时,我们跳到jumpbuf指向的程序地址,恰好又回到了sigsetjump的第三步,然后我们恢复了寄存器状态后就返回1,所以会跳到else段里执行。
我觉得应该是这样,至少同样的接口让我来实现的话,我会设计成这样。呵呵。