6

我正在开发一个 JIT 编译器,并试图弄清楚如何为托管类型(如字符串)输出正确的清理块。

对于具有一个局部变量类型的函数,清理块的反汇编string如下所示:

0044333C 648910           mov fs:[eax],edx
0044333F 6854334400       push $00443354
00443344 8D45FC           lea eax,[ebp-$04]
00443347 E81834FCFF       call @UStrClr
0044334C C3               ret 
0044334D E9062BFCFF       jmp @HandleFinally
00443352 EBF0             jmp $00443344

不幸的是,我没有任何好的方法来获取地址,@UStrClr所以@HandleFinally我的 JITter 可以插入它们。它们在 System.Pas 中声明为_UStrClrand _HandleFinally,在interface部分,但显然有一些“魔法”正在发生,因为尝试使用这些标识符会导致编译器错误。

所以我尝试了一个 ASM 例程,我在其中声明了一个全局指针并说mov func_ustr_clear, @UStrClear. 这次我没有收到未声明的标识符错误;我得到了更奇怪的东西:

[DCC Error]: E2107 Operand size mismatch

那么有人知道如何正确地做到这一点吗?

4

1 回答 1

8

尝试这些函数来获取 和 的UStrClr地址HandleFinally

function GetUStrClrAddress: Pointer;
asm
{$IFDEF CPUX64}
  mov rcx, offset System.@UStrClr;
  mov @Result, rcx;
{$ELSE}
  mov @Result, offset System.@UStrClr;
{$ENDIF}
end;

function GetHandleFinallyAddress: Pointer;
asm
{$IFDEF CPUX64}
  mov rcx, offset System.@HandleFinally;
  mov @Result, rcx;
{$ELSE}
  mov @Result, offset System.@HandleFinally;
{$ENDIF}
end;

编辑:

@ArnaudBouchez 还建议进行一些进一步的优化。通过直接将值放入函数返回寄存器,函数会快一点。

function GetUStrClrAddress: Pointer; 
asm 
  {$ifdef CPU64} 
    mov rax,offset System.@UStrClr 
  {$else} 
    mov eax,offset System.@UStrClr 
  {$endif} 
end;

可以在此处找到对 Delphi 中汇编程序使用的进一步阅读(以及OFFSET关键字的使用)Assembly Expressions, Expression Classes,.

于 2014-01-20T06:28:25.673 回答