Delphi XE2: преобразование метода ASM для платформы Win64 - PullRequest
1 голос
/ 06 декабря 2011

Когда я пытаюсь скомпилировать паскаль для платформы Win64, я сталкиваюсь с ошибками.Методы содержат блок ASM.У меня нет идей, как заставить это работать на платформе Win64:

Метод 1:

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

Метод 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;

Ответы [ 3 ]

8 голосов
/ 06 декабря 2011

Я не знаком с подробностями инструкций x64, поэтому я не могу помочь с переписыванием кода ассемблера для поддержки 64-битной версии, но могу вам сказать, что 64-битный компилятор Embarcadero не в настоящее время позволяет смешивать Паскаль и Ассемблер в одной и той же функции.Вы можете писать только все-Паскаль или все-Сборочные функции, не смешивая их вообще (функция Паскаля может вызывать функцию Сборки и наоборот, но они не могут сосуществовать вместе, как в x86).Так что вам придется переписать ваши методы.

6 голосов
/ 06 декабря 2011

Вы можете переписать весь метод в x64 ASM.Как сказал Реми, вам нужно переписать весь метод, так как вы не можете вложить несколько asm .. end блоков в begin .. end.

. Реальная проблема заключается в том, что соглашения о вызовах не совпадают в Win32 иРежим Win64.Изменения регистров (т. Е. Они являются 64-битными и теперь должны включать регистры SSE2), но основная проблема заключается в том, что ваш инжектор вызовов должен знать количество параметров: в стеке должно быть определенное пространство для каждого параметра.

Если ваша функция TSPAApply имеет несколько фиксированных параметров, вы можете преобразовать ее в простую версию на Паскале - что безопаснее всего.

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;

Но вам лучше полагаться наTMethod список, для более общего ООП способа сделать это.Здесь неплохо было бы выполнить рефакторинг кода.

1 голос
/ 18 января 2012

Попробуйте

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

Указатели являются 64-разрядными на x64, поэтому занимают полный 64-разрядный регистр.Регистр «A» - это AL / AX / EAX / RAX для 8/16/32/64-бит соответственно.

Для второй функции мне нужно знать больше о функции, вызываемой вблок asm.

...