如何在asm块中引发异常?

时间:2015-07-23 17:19:19

标签: delphi exception assembly 64-bit

我想在X64 asm块中引发异常。

让我们假设我有这样的功能:

function Example(Values: array of integer): integer;
asm
  or rcx,rcx
  jz @error
  ....

我知道我可以只读取指针并获得AV,但是我想提出一个更具描述性的错误。

我可以创建一个额外的功能并调用它:

asm
  or rcx,rcx
  jz @error
  ....
@error:
  mov ecx, 1
  mov rdx, ErrorString
  jmp RaiseError
  ....

function RaiseError(code: integer; const Msg: string);
begin
  case code of
    1: raise EEmptyArrayError.Create(Msg);

然而,错误将在引起的函数之外发生。如何从(似乎)来自Example函数内部获取异常。

请注意,这是X64,因此适用于X86的所有SEH答案都不合适,因为X64使用VEH。

1 个答案:

答案 0 :(得分:4)

raise的完整语法是:

raise Exception at address  

您需要做的就是将当前IP作为参数传递,错误proc可以将其传递给异常。

您可以使用lea rax, [rip]获取RIP。

因此代码变为:

asm
  or rcx,rcx
  jz @error
  ....
@error:
  mov ecx, 1
  mov rdx, ErrorString
  lea r8,[rip]
  jmp RaiseError 
  ....

function RaiseError(code: integer; const Msg: string; address: pointer);
begin
  case code of
    1: raise EEmptyArrayError.Create(Msg) at address;

当然在这种情况下使用起来更容易

function RaiseError(code: integer; const Msg: string);
begin
  case code of
    1: raise EEmptyArrayError.Create(Msg) at ReturnAddress;

注意
在这种情况下,如果你保留jmp,错误似乎来自调用例程,在这种情况下实际上是正确的。如果您希望异常将有罪的手指指向您的asm代码,请使用呼叫。