异常的分发和处理时在线程范围内进行的异常处理器的注册也是相对线程而言的Windows系统中的每个用户态线程都拥有一个线程环境块(Thread Environment Block)TEB结构的具体定义TEB结构的起始处总有一个被称为线程信息块(Thread information Block)的结构简称TIBTIB的第一字段ExceptionList记录的就是用来登记结构化异常处理链表的表头地址在x系统中段寄存器FS总是指向线程的TEB/TIB结构FS[] 总是指向结构化异常处理链表的表头所以将这个链表称为FS[]链条可以把结构化异常处理看作是操作系统与用户代码软硬件异常的一种模型而FS[]链条便是这两者间协作的接口当有异常需要处理时操作系统通过FS[]链条来寻找异常处理器给用户代码异常情况的机会 可以手工编写代码来登记和注销异常处理器首先需要编写一个异常处理器函数它应该具有标准的sehHandler原型然后在栈上建立一个EXCEPTION_REGISTRATION_RECORD结构并把这个结构的地址注册到FS[]链表中 注册FS[]的代码如下所示 #include stdafxh #include <windowsh> // 定义一个符合sehHandler原型的异常处理函数如果该函数检测发生的是 // 除零异常然后将上下文结构中的ECX寄存器的值改为让其继续执行 // 导致异常的代码第二次执行时由于除数不再为所以可以顺利执行了 EXCEPTION_DISPOSITION __cdecl _raw_seh_handler( struct _EXCEPTION_RECORD *ExceptionRecord void * EstablisherFrame struct _CONTEXT * ContexRecord void * DispacherContext ) { printf(_raw_seh_handler codex%x flagsx%x\n ExceptionRecord>ExceptionCode ExceptionRecord>ExceptionFlags) if(ExceptionRecord>ExceptionCode == STATUS_INTEGER_DIVIDE_BY_ZERO) { ContexRecord>Ecx = return ExceptionContinueExecution } return ExceptionContinueSearch } int main(int argc char* argv[]) { __asm { // 手工方法将异常函数注册到FS[]链表中 push OFFSET _raw_seh_handler push FS[] mov FS[] ESP // 执行除零异常 xor edx edx mov eax xor ecx ecx idiv ecx mov eax [ESP] mov FS[] EAX add esp } printf(Hello World!\n) return } |