Traduire un code à l'aide pointeur, à l'Assemblée dans Pascal - Delphi
Question
Je le code ci-dessous, et je veux traduire en ASM, à utiliser dans Delphi aussi.
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;
Il fonctionne normalement, mais lorsque je tente sa version Assemblée:
function Function(parameter: Integer): Integer; cdecl;
asm
mov eax, FunctionAddressList
jmp dword ptr [eax + 5 * 4]
end;
Il est censé fonctionner, parce que, en C ++ cela fonctionne dans les deux sens:
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);
}
Mais il ne fonctionne pas dans Delphi.
Dans la version de l'Assemblée, il multiplie le tableau 4, parce qu'il est la taille de décalage entre chaque élément du tableau, afin que les deux versions sont équivalentes.
Alors, je veux savoir pourquoi il ne fonctionne pas avec Delphi. Dans Delphi, la taille de décalage entre les valeurs entières dans un réseau est différent de C ++?
Je l'ai déjà essayé beaucoup de compensations, 1, 2, 4, 6, 8, etc. Et de nombreux types de Array (Array of pointeur; Pointeur; Array of Integer, etc.), et je l'ai essayé beaucoup les conventions d'appel et cdecl était le seul qui a travaillé avec la version non-asm, mais avec ASM, tous les tests ne fonctionne pas.
Merci.
La solution
application du premier test pour reproduire l'erreur:
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;
L'adresse Bar est correctement défini, mais le problème est que le compilateur Delphi génère prologue et épilogue pour Foo, si réel le code Foo est
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
En conséquence, la pile est corrompu, le paramètre est erroné et l'adresse de retour Bar est erroné. Si vous voulez toujours faire l'affaire, utilisez
function Foo(parameter: Integer): Integer; cdecl;
asm
pop ebp
mov eax, FunctionAddressList
jmp dword ptr [eax + 5 * 4]
end;
Autres conseils
Array of Integer
est pas ce que vous pensez qu'il est. Il est un tableau dynamique géré automatiquement.
Vous devriez essayer la même chose en utilisant FunctionAddressList: ^Pointer;
-. Notez toutefois que vous devrez faire l'allocation et désallocation manuelle