Delphi XE2: converti un metodo ASM per la piattaforma Win64
-
28-10-2019 - |
Domanda
Quando provo a compilare un'unità Pascal per la piattaforma Win64, incontro errori. I metodi contengono un blocco ASM. Non ho idee su come farlo funzionare per la piattaforma Win64:
Metodo 1:
Function TSparseList.ForAll( ApplyFunction: Pointer {TSPAApply} ): Integer; Assembler;
Asm
MOV EAX,[EAX].TSparseList.FList
JMP TSparsePointerArray.ForAll
End;
Metodo 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;
Soluzione
Non ho familiarità con i dettagli delle istruzioni X64, quindi non posso fare a meno di riscrivere il codice di assemblaggio per supportare a 64 bit, ma posso dirti che il compilatore a 64 bit di Embarcadero non Attualmente consentire di mescolare Pascal e Assembly nella stessa funzione. Puoi solo scrivere funzioni all-pascal o all-assembly, nessuna miscelazione (una funzione Pascal può chiamare una funzione di assemblaggio e viceversa, ma non possono coesistere insieme come in x86). Quindi dovrai riscrivere i tuoi metodi.
Altri suggerimenti
Potresti essere in grado di riscrivere l'intero metodo in X64 ASM. Come ha detto Remy, dovrai riscrivere l'intero metodo, dal momento che non puoi nidificarne un po ' asm .. end
blocchi all'interno begin .. end
.
Il vero problema è che le convenzioni di chiamata non sono le stesse nella modalità Win32 e Win64. Le modifiche ai registri (cioè sono 64 bit e ora devono includere i registri SSE2), ma il problema principale riguarda il fatto che il re-iniettore della chiamata deve conoscere il numero di parametri: un po 'di spazio deve essere allocato sullo stack per ogni parametro.
Se tuo TSPAApply
La funzione ha una serie di parametri fissi, è possibile convertirla in una semplice versione Pascal - che è più sicura di tutto.
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;
Ma dovresti fare meglio con affidamento su un TMethod
Elenca, per un modo OOP più generico di farlo. Alcuni refactoring del codice sarebbero una buona idea, qui.
Provare
Function TSparseList.ForAll( ApplyFunction: Pointer {TSPAApply} ): Integer; Assembler;
Asm
MOV RAX,[RAX].TSparseList.FList
JMP TSparsePointerArray.ForAll
End;
I puntatori sono a 64 bit su X64, quindi occuperà un registro completo a 64 bit. Il registro "A" è Al/AX/EAX/RAX rispettivamente per 8/16/32/64-bit.
Per la seconda funzione, avrei bisogno di saperne di più sulla funzione chiamata nel blocco ASM.