![](/img/trans.png)
[英]How to make FastCodePatch work in Delphi XE2 Win64 platform?
[英]Delphi XE2: Convert a ASM method for Win64 platform
当我尝试为Win64平台编译Pascal单元时,遇到错误。 该方法包含ASM块。 我不知道如何使它适用于Win64平台:
方法1:
Function TSparseList.ForAll( ApplyFunction: Pointer {TSPAApply} ): Integer; Assembler;
Asm
MOV EAX,[EAX].TSparseList.FList
JMP TSparsePointerArray.ForAll
End;
方法2:
Function TSparsePointerArray.ForAll( ApplyFunction: Pointer {TSPAApply} ):
Integer;
Var
itemP: PAnsiChar; { Pointer to item in section } { patched by ccy }
item: Pointer;
i, callerBP: Cardinal;
j, index: Integer;
Begin
{ Scan section directory and scan each section that exists,
calling the apply function for each non-nil item.
The apply function must be a far local function in the scope of
the procedure P calling ForAll. The trick of setting up the stack
frame (taken from TurboVision's TCollection.ForEach) allows the
apply function access to P's arguments and local variables and,
if P is a method, the instance variables and methods of P's class '}
Result := 0;
i := 0;
Asm
mov eax,[ebp] { Set up stack frame for local }
mov callerBP,eax
End;
While ( i < slotsInDir ) And ( Result = 0 ) Do
Begin
itemP := secDir^[i];
If itemP <> Nil Then
Begin
j := 0;
index := i Shl SecShift;
While ( j < FSectionSize ) And ( Result = 0 ) Do
Begin
item := PPointer( itemP )^;
If item <> Nil Then
{ ret := ApplyFunction(index, item.Ptr); }
Asm
mov eax,index
mov edx,item
push callerBP
call ApplyFunction
pop ecx
mov @Result,eax
End;
Inc( itemP, SizeOf( Pointer ) );
Inc( j );
Inc( index )
End
End;
Inc( i )
End;
End;
我不熟悉的x64指令的细节,所以我不能重写汇编代码以支持64位的帮助,但我可以告诉你,Embarcadero公司的64位编译器目前不允许你混合Pascal和大会在相同的功能。 您只能编写全Pascal或所有Assembly函数,完全不能混合(Pascal函数可以调用Assembly函数,反之亦然,但是它们不能像x86中那样共存)。 因此,您将不得不重写您的方法。
您可能可以在x64 ASM中重写整个方法。 正如Remy所说,您将需要重写整个方法,因为您不能在begin .. end
嵌套一些asm .. end
块。
真正的问题是,在Win32和Win64模式下,调用约定不相同。 寄存器更改(即它们是64位,现在应包括SSE2寄存器),但主要问题在于以下事实:您的调用重新注入器应知道参数的数量:必须在堆栈上为每个参数分配一些空间。
如果您的TSPAApply
函数具有多个固定参数,则可以将其转换为纯Pascal版本-比所有版本都更安全。
type
TSPAApply = function(index: integer; item: pointer);
Function TSparseList.ForAll( ApplyFunction: Pointer {TSPAApply} ): Integer;
begin
result := FList.ForAll(ApplyFunction);
End;
Function TSparsePointerArray.ForAll( ApplyFunction: Pointer {TSPAApply} ):
Integer;
Var
itemP: PPointer;
i: Cardinal;
j, index: Integer;
Begin
Result := 0;
i := 0;
While ( i < slotsInDir ) And ( Result = 0 ) Do
Begin
itemP := secDir^[i];
If itemP <> Nil Then
Begin
j := 0;
index := i Shl SecShift;
While ( j < FSectionSize ) And ( Result = 0 ) Do
Begin
If itemP^ <> Nil Then
result := TSPAApply(ApplyFunction)(index,itemP^.Ptr);
Inc( itemP );
Inc( j );
Inc( index )
End
End;
Inc( i )
End;
End;
但是,您最好依靠TMethod
列表,以获得更通用的OOP方法。 在这里,一些代码重构将是一个好主意。
尝试
Function TSparseList.ForAll( ApplyFunction: Pointer {TSPAApply} ): Integer; Assembler;
Asm
MOV RAX,[RAX].TSparseList.FList
JMP TSparsePointerArray.ForAll
End;
指针是x64上的64位,因此将占用完整的64位寄存器。 “ A”寄存器分别是8/16/32/64位的AL / AX / EAX / RAX。
对于第二个功能,我需要更多地了解在asm块中被调用的功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.