Frage

Ich habe diesen Code unten, und ich mag es ASM zu übersetzen, auch in Delphi zu verwenden.

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;

Es funktioniert normal, aber wenn ich versuche, seine Montage Version:

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

Es soll an der Arbeit, weil in C ++ es in beiden Richtungen funktioniert:

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);
}

Aber es funktioniert nicht in Delphi.

In der Versammlung Version, es multipliziert das Array bis 4, weil es die Offset-Größe ist zwischen jedem Element des Arrays, so dass beide Versionen gleichwertig sind.

Also, ich möchte wissen, warum es nicht mit Delphi funktioniert. In Delphi, ist die Offset-Größe zwischen ganzzahligen Werten in einem Array anders als C ++?

Ich habe schon viele Versetzungen versuche, wie 1, 2, 4, 6, 8, etc. Und viele Arten von Array (Array of Pointer, nur Pointer; Array von Integer, etc), und ich habe viele versucht Aufrufkonventionen und cdecl war die einzige, die mit dem nicht-asm-Version gearbeitet, aber mit ASM, alle Tests funktionierte nicht.

Danke.

War es hilfreich?

Lösung

Erstes Test-App zu reproduzieren Fehler:

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;

Die Bar-Adresse definiert ist richtig, aber das Problem ist, dass Delphi-Compiler Prolog und Epilog für Foo erzeugt, so real Foo-Code ist

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

Als Ergebnis der Stapel beschädigt ist, ist der Parameter falsch und Bar Absenderadresse ist falsch. Wenn Sie wollen immer noch den Trick, die Verwendung

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

Andere Tipps

Array of Integer ist nicht das, was Sie denken, es ist. Es ist eine automatisch verwaltete dynamische Array.

Sie sollten versuchen, das gleiche mit FunctionAddressList: ^Pointer; - Anmerkung jedoch, dass Sie die manuelle Zuordnung und Aufhebung der Zuordnung zu tun haben

.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top