Question

Lorsque j'essaye de compiler une unité pascal pour la plate-forme Win64, je rencontre des erreurs.Les méthodes contiennent un bloc ASM.Je n'ai aucune idée de comment le faire fonctionner pour la plate-forme Win64:

Méthode 1:

Function TSparseList.ForAll( ApplyFunction: Pointer {TSPAApply} ): Integer; Assembler;
Asm
        MOV     EAX,[EAX].TSparseList.FList
        JMP     TSparsePointerArray.ForAll
End;

Méthode 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;
Était-ce utile?

La solution

Je ne connais pas les particularités des instructions x64, je ne peux donc pas m'empêcher de réécrire le code d'assemblage pour prendre en charge 64 bits, mais je peux vous dire que le compilateur 64 bits d'Embarcadero ne le fait pas vous permet actuellement de mélanger Pascal et Assembly dans la même fonction.Vous ne pouvez écrire que des fonctions tout-Pascal ou tout-assemblage, pas de mixage du tout (une fonction Pascal peut appeler une fonction Assembly et vice versa, mais elles ne peuvent pas coexister ensemble comme dans x86).Vous devrez donc réécrire vos méthodes.

Autres conseils

Vous pourrez peut-être réécrire toute la méthode en ASM x64.Comme Rémy l'a dit, vous devrez réécrire toute la méthode, car vous ne pouvez pas imbriquer certains blocs asm .. end dans begin .. end.

Le vrai problème est que les conventions d'appel ne sont pas les mêmes en mode Win32 et Win64.Les registres changent (c'est-à-dire qu'ils sont 64 bits et doivent maintenant inclure les registres SSE2), mais le problème principal est lié au fait que votre ré-injecteur d'appel connaîtra le nombre de paramètres: un espace doit être alloué sur la pile pour chaque paramètre.

Si votre fonction TSPAApply a un certain nombre de paramètres fixes, vous pouvez la convertir en une version pascal simple - ce qui est plus sûr que tout.

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;

Mais vous devriez mieux vous fier à une liste TMethod, pour une manière OOP plus générique de le faire.Une refactorisation du code serait une bonne idée, ici.

Essayez

Function TSparseList.ForAll( ApplyFunction: Pointer {TSPAApply} ): Integer; Assembler;
Asm
        MOV     RAX,[RAX].TSparseList.FList
        JMP     TSparsePointerArray.ForAll
End;

Les pointeurs sont 64 bits sur x64, ils occuperont donc un registre 64 bits complet. Le registre "A" est AL / AX / EAX / RAX pour 8/16/32/64 bits respectivement.

Pour la deuxième fonction, j'aurais besoin d'en savoir plus sur la fonction appelée dans le bloc asm.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top