質問

Win64プラットフォームのPascalユニットをコンパイルしようとすると、エラーが発生します。メソッドには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;
役に立ちましたか?

解決

私はX64の指示の詳細に精通していないので、64ビットをサポートするためにアセンブリコードを書き換えるのを手伝うことはできませんが、Embarcaderoの64ビットコンパイラを伝えることができます ではない 現在、同じ機能でPascalとAssemblyを混ぜることができます。すべてのパスカルまたは全アセンブリ機能のみを記述することができますが、混合はまったくありません(パスカル関数はアセンブリ関数を呼び出すことができ、その逆も同様ですが、x86のように一緒に共存することはできません)。したがって、メソッドを書き直す必要があります。

他のヒント

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 リスト、それを行うより一般的なOOPの方法。ここでは、いくつかのコードリファクタリングが良い考えです。

試す

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

ポインターはx64で64ビットであるため、64ビットの完全なレジスタが占められます。 「A」レジスタは、それぞれ8/16/32/64ビットのAL/AX/EAX/RAXです。

2番目の関数については、ASMブロックで呼び出されている関数についてもっと知る必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top