3

以下にこのコードがあり、Delphiでも使用できるようにASMに変換したいと思います。

var
    FunctionAddressList: Array of Integer;

type TFunction = function(parameter: Integer): Integer; cdecl;

function Function(parameter: Integer): Integer;
var
    ExternFunction: TFunction;
begin
    ExternFunction := TFunction(FunctionAddressList[5]);
    Result := ExternFunction(parameter);
end;

正常に動作しますが、アセンブリバージョンを試してみると:

function Function(parameter: Integer): Integer; cdecl;
asm
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;

C ++では次の両方の方法で機能するため、機能するはずです。

void *FunctionAddressList;

_declspec(naked) int Function(int parameter)
{
    _asm mov eax, FunctionAddressList;
    _asm jmp dword ptr [eax + 5 * 4];
}

typedef int (*TFunction)(int parameter);
int Function(int parameter)
{
    TFunction ExternFunction = ((TFunction *)FunctionAddressList)[5];
    return ExternFunction(parameter);
}

ただし、Delphiでは機能しません。

アセンブリバージョンでは、配列の各要素間のオフセットサイズであるため、配列を4に乗算します。したがって、両方のバージョンは同等です。

だから、なぜそれがDelphiで動作しないのか知りたいです。Delphiでは、配列内の整数値間のオフセットサイズはC ++とは異なりますか?

私はすでに1、2、4、6、8などの多くのオフセットを試しました。また、多くの種類の配列(ポインターの配列、ポインターのみ、整数の配列など)、および多くの呼び出し規約を試しました。非asmバージョンで機能したのはcdeclだけでしたが、ASMではすべてのテストが機能しませんでした。

ありがとう。

4

2 に答える 2

3

エラーを再現する最初のテストアプリ:

var
  FunctionAddressList: Array of Integer;

function Bar(parameter: Integer): Integer; cdecl;
begin
  ShowMessage('Bar '+IntToStr(parameter));
end;

function Foo(parameter: Integer): Integer; cdecl;
asm
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetLength(FunctionAddressList, 6);
  FunctionAddressList[5]:= Integer(@Bar);
  Foo(25);
end;

バーアドレスは正しく定義されていますが、問題はDelphiコンパイラがFooのプロローグとエピローグを生成するため、実際のFooコードは

0046CD30 55               push ebp
0046CD31 8BEC             mov ebp,esp
Unit1.pas.46:             mov eax, FunctionAddressList
Unit1.pas.47:             jmp dword ptr [eax + 5 * 4]
0046CD3B 5D               pop ebp
0046CD3C C3               ret

その結果、スタックが破損し、パラメータが間違っており、バーの差出人住所が間違っています。それでもトリックを実行したい場合は、

function Foo(parameter: Integer): Integer; cdecl;
asm
  pop ebp
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;
于 2010-01-31T23:35:39.103 に答える
1

Array of Integerあなたが思っていることではありません。これは、自動的に管理される動的配列です。

--を使用して同じことを試す必要FunctionAddressList: ^Pointer;がありますが、手動での割り当てと割り当て解除を行う必要があることに注意してください。

于 2010-01-31T22:24:41.117 に答える