Structured Exception Handling
2007-01-14 20:14:46 来源:WEB开发网把目前这一小点儿东西凑到一起,我写了一个小程序来演示所讲到的这个非常简单的OS级的结构化异常处理。Figure3所示的就是MYSEH.CPP,它只有两个函数。main函数使用了三个内嵌的ASM块。第一个块使用两条PUSH指令(“PUSHhandler”和“PUSHFS:[0]”)在堆栈上构建了一个EXCEPTION_REGISTRATION结构体。PUSHFS:[0]将FS:[0]的上一个值保存为结构体的一部分,但是目前并不重要。重要的是堆栈上有一个8字节的EXCEPTION_REGISTRATION结构体。下一条指令(MOVFS:[0],ESP)将线程信息块的第一个DWORD指向新的EXCEPTION_REGISTRATION结构体。
在堆栈上构建EXCEPTION_REGISTRATION结构体而不是使用全局变量是由原因的。当使用编译器的_try/_except语义时,编译器也会在堆栈上构建EXCEPTION_REGISTRATION结构体。我只是要说明使用_try/_except后编译器所做的最起码的工作。回到main函数,下一个__asm块清零了EAX寄存器(MOVEAX,0)然后将寄存器的值作为内存地址,而下一条指令就向这个地址进行写入(MOV[EAX],1),这就引发了异常。最后的__asm块移除这个简单的异常处理:首先恢复以前的FS:[0]的内容,然后从堆栈中弹出EXCEPTION_REGISTRATION记录(ADDESP,8)。
现在假设正在运行MYSEH.EXE,看一下程序的执行情况。MOV[EAX],1指令的执行引发了一个accessviolation。系统察看TIB的FS:[0]并找到指向EXCEPTION_REGISTRATION结构体的指针。结构体中有一个指向MYSEH.CPP文件中的_except_handler函数的指针。系统将所需的四个参数入栈并调用_except_handler函数。一进入_except_handler,代码首先用一条printf语句打印“Yo!Imadeithere!”。然后,_except_handler修复引起异常的问题。问题在于EAX指向了不可写内存的地址(地址0)。所做的修复就是修改CONTEXT中EAX的值,使其指向一个可写的内存单元。在这个简单的程序里,一个DWORD类型变量(scratch)就是用于此目的的。_except_handler函数的最后的动作就是返回ExceptionContinueExecution类型的值,这个结构体定义在标准的EXCPT.H文件中。
Tags:Structured Exception Handling
编辑录入:爽爽 [复制链接] [打 印]更多精彩
赞助商链接