Übersetzen Sie einen Code mit Zeiger, um Assembly in Pascal - Delphi
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.
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
tunfunction 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