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.

Était-ce utile?

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top