【发布时间】:2016-01-20 18:21:27
【问题描述】:
我必须实现一个基于 SEH 的异常处理程序。 首先,我编写了以下示例代码,我尝试使用 fs register 注册异常处理程序。
#include <iostream>
#include <exception>
#include <windows.h>
using namespace std;
EXCEPTION_DISPOSITION myHandler(
_EXCEPTION_RECORD *ExcRecord,
void * EstablisherFrame,
_CONTEXT *ContextRecord,
void * DispatcherContext)
{
cout << "In the exception handler" << endl;
cout << "Just a demo. exiting..." << endl;
return ExceptionContinueExecution;
}
int main()
{
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
EXCEPTION_REGISTRATION myExceptReg;
EXCEPTION_REGISTRATION *pReg = &myExceptReg;
myExceptReg.handler = myHandler;
DWORD prev;
asm("movl %fs:0 , %eax");
asm("movl %%eax , %0": "=r" (prev));
myExceptReg.prev = (EXCEPTION_REGISTRATION*) prev;
asm ("movl %0, %%eax" : "=m" (pReg));
asm("movl %eax , %fs:0");
// int* ptr = 0;
// exception e;
return 0;
}
当我调试代码时,我看到 fs 寄存器的值是 zero。执行 asm("movl %fs:0 , %eax");
后程序崩溃以下是与此代码等效的程序集示例。
000000000000401626: mov %rax,%rcx
000000000000401629: callq 0x44d7a0 <std::ostream::operator<<(std::ostream& (*)(std::ostream&))>
32 EXCEPTION_REGISTRATION *pReg = &myExceptReg;
00000000000040162e: lea 0x20(%rbp),%rax
000000000000401632: mov %rax,0x18(%rbp)
33 myExceptReg.handler = myHandler;
000000000000401636: lea -0x13d(%rip),%rax # 0x401500 <myHandler(_EXCEPTION_RECORD*, void*, _CONTEXT*, void*)>
00000000000040163d: mov %rax,0x28(%rbp)
36 asm("movl %fs:0 , %eax");
000000000000401641: mov %fs:0x0,%eax
37 asm("movl %%eax , %0": "=r" (prev));
000000000000401649: mov %eax,%ebx
00000000000040164b: mov %ebx,0x3c(%rbp)
39 myExceptReg.prev = (EXCEPTION_REGISTRATION*) prev;
00000000000040164e: mov 0x3c(%rbp),%eax
000000000000401651: mov %rax,0x20(%rbp)
41 asm ("movl %0, %%eax" : "=m" (pReg));
000000000000401655: mov 0x18(%rbp),%eax
42 asm("movl %eax , %fs:0");
000000000000401658: mov %eax,%fs:0x0
50 return 0;
可能是什么问题?
【问题讨论】:
-
这种异常处理方式仅在 32 位代码中有效。 64 位代码必须遵循 x64 ABI,异常处理是其中的一部分。它是基于表格的。
-
@Hans Passant,我正在尝试使用 32 位代码,但这里的 32 位代码有问题吗?这段代码中的什么使它看起来像是 64 位的?
-
如果您的寄存器被命名为 rax、rbp 和 rcx 而不是 eax、ebp 和 ecx,那么您使用的是 64 位。
-
我正在使用 mingw 4.6.2 编译 32 位 exe 的代码。汇编代码是我在调试时在反汇编窗口中找到的。
-
构建时是否明确传递了 -m32 ?或者只是假设编译器默认生成 32 位?一个 64 位的可执行文件也可能解释为什么使用 fs 不起作用,因为 64 位通常使用 gs。