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;
È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top