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;
¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top