Delphi XE2: Convierta un método ASM para la plataforma Win64
-
28-10-2019 - |
Pregunta
Cuando intento compilar una unidad Pascal para la plataforma Win64, encuentro errores. Los métodos contienen bloque ASM. No tengo ideas sobre cómo hacer que funcione para la plataforma Win64:
Método 1:
Function TSparseList.ForAll( ApplyFunction: Pointer {TSPAApply} ): Integer; Assembler;
Asm
MOV EAX,[EAX].TSparseList.FList
JMP TSparsePointerArray.ForAll
End;
Método 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;
Solución
No estoy familiarizado con los detalles de las instrucciones X64, por lo que no puedo evitar reescribir el código de ensamblaje para admitir 64 bits, pero puedo decirle que el compilador de 64 bits de Embarcadero no es Actualmente le permite mezclar Pascal y ensamblaje en la misma función. Solo puede escribir funciones de All-Pascal o All-Ensembly, sin mezcla (una función Pascal puede llamar a una función de ensamblaje y viceversa, pero no pueden coexistir juntos como en x86). Entonces tendrá que reescribir sus métodos.
Otros consejos
Es posible que pueda reescribir todo el método en X64 ASM. Como Remy le dijo, deberá reescribir todo el método, ya que no puede anidar algunos asm .. end
bloques dentro begin .. end
.
El verdadero problema es que las convenciones de llamadas no son las mismas en el modo Win32 y Win64. Registros de cambios (es decir, son 64 bits y ahora incluirán registros SSE2), pero el problema principal es sobre el hecho de que su reinyector de llamadas sabrá el número de parámetros: se debe asignar algún espacio en la pila para cada parámetro.
Si tu TSPAApply
La función tiene varios parámetros fijos, puede convertirlo en una versión de Pascal simple, que es más segura que todo.
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;
Pero deberías confiar mejor en un TMethod
Lista, para una forma OOP más genérica de hacerlo. Alguna refactorización de código sería una buena idea, aquí.
Probar
Function TSparseList.ForAll( ApplyFunction: Pointer {TSPAApply} ): Integer; Assembler;
Asm
MOV RAX,[RAX].TSparseList.FList
JMP TSparsePointerArray.ForAll
End;
Los punteros tienen 64 bits en x64, por lo que ocupará un registro completo de 64 bits. El registro "A" es Al/AX/EAX/RAX para 8/16/32/64 bits respectivamente.
Para la segunda función, necesitaría saber más sobre la función que se llama en el bloque ASM.