使用Assembly的c中的异常自处理程序

时间:2013-04-13 06:48:06

标签: c visual-c++ assembly exception-handling

我通过以下代码在c文件中使用程序集创建一个自我异常处理程序:

__asm 
    {
        pushad
        mov esi, offset Handler 
        push esi 
        push dword ptr fs:[0] 
        mov dword ptr fs:[0], esp
        push u32Param
        call pFunc;
        jmp NoException

Handler:

        mov esp, [esp + 8]
        pop dword ptr fs:[0]
        add esp, 4
        popad
        mov eax, 0x80000000     
        jmp ExceptionHandled

NoException:

        pop dword ptr fs:[0]
        add esp, 40

ExceptionHandled:
    }

此代码是汇编中的简单异常处理 此代码适用于新创建的vc项目。
但是在我的项目中它会产生异常,vc表示存在无效的异常处理程序。

有任何建议吗?

1 个答案:

答案 0 :(得分:2)

如果您关注的是this article,那么为什么不正确恢复堆栈,如代码所示?

文章中的代码:

18  NoException&;Handler:                ;;No Exception Occured
19      pop dword ptr fs:[0]            ;;Restore Old Exception Handler
20      add esp, 32 + 4                 ;;ESP value before SEH was set. 32 for pushad and ...
21  ExceptionHandled&;Handler:           ;;...4 for push offset Handler. (No Restore State)
22                                      ;;Exception has been handled, or no exception occured

您的代码:

NoException:

        pop dword ptr fs:[0]
        add esp, 8

ExceptionHandled:
该代码中的

32是撤消pushad,4是撤消push esi。你为什么有8个? 32 + 4≠8。

如果您想从堆栈中删除u32Param(如果pFunc没有为您执行此操作),那么您应该在这两行之间执行此操作:

    call pFunc;
    add esp, 4
    jmp NoException

我的版本:

// file: tst.c
// compile with Open Watcom C/C++ 1.9: wcl386.exe /q /we /wx tst.c
// ditto with debug info: wcl386.exe /q /we /wx /d2 tst.c
#include <stdio.h>

unsigned __stdcall func(volatile unsigned* p)
{
  return *p;
}

unsigned blah(unsigned (__stdcall *pFunc)(volatile unsigned*), volatile unsigned* u32Param)
{
  unsigned result = 0;

  __asm 
  {
      pushad
//      mov esi, offset Handler // Open Watcom C/C++ says Handler is undefined
//      push esi 

//      lea eax, blah
//      add eax, Handler - blah // this difference doesn't come out correct with Open Watcom C/C++
//      add eax, 78 // 78 is Handler - blah // this is unreliable
//      push eax

      push 0xFDCB4321
      jmp GetHandlerAddr
  GotHandlerAddr:
      pop eax
      add esp, 4
      push eax

      push dword ptr fs:[0] 
      mov dword ptr fs:[0], esp
      push u32Param
      call dword ptr [pFunc]

      jmp NoException

  GetHandlerAddr:
      call Handler // this will place &Handler on the stack
  Handler:
      cmp dword ptr [esp + 4], 0xFDCB4321
      je GotHandlerAddr

      mov esp, [esp + 8]
      pop dword ptr fs:[0]
      add esp, 4
      popad
      mov eax, 0x80000000     
      jmp ExceptionHandled

  NoException:

      pop dword ptr fs:[0]
      add esp, 32 + 4

  ExceptionHandled:

      mov result, eax
  }

  return result;
}

int main(void)
{
  volatile unsigned n = 0x113355AA;
  printf("%08X\n", func(&n));
  printf("%08X\n", blah(&func, &n));
  printf("%08X\n", blah(&func, (volatile unsigned*)0));
  printf("%08X\n", blah(&func, (volatile unsigned*)0));
  return 0;
}

输出:

113355AA
113355AA
80000000
80000000