Tradurre un codice tramite puntatore, all'Assemblea in Pascal - Delphi
Domanda
Ho questo codice qui sotto, e voglio tradurlo ad ASM, da utilizzare in Delphi troppo.
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;
Si lavora normalmente, ma quando provo la sua versione Assembly:
function Function(parameter: Integer): Integer; cdecl;
asm
mov eax, FunctionAddressList
jmp dword ptr [eax + 5 * 4]
end;
Si suppone di lavoro, perché, in C ++ che funziona in entrambi i modi:
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);
}
Ma non funziona in Delphi.
Nella versione Assembly, moltiplica la matrice a 4, perché è la dimensione di offset tra ciascun elemento della matrice, quindi entrambe le versioni sono equivalenti.
Quindi, voglio sapere perché non funziona con Delphi. In Delphi, la dimensione offset tra valori interi in un array è diversa C ++?
Ho già provato molti offset, come 1, 2, 4, 6, 8, ecc e molti tipi di Array (Array di Pointer, solo Pointer; Array di Integer, ecc), e ho provato molti convenzioni di chiamata, e cdecl era l'unico che ha lavorato con la versione non-asm, ma con ASM, tutti i test non hanno funzionato.
Grazie.
Soluzione
Primo test app per errore riprodurre:
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;
La barra degli indirizzi è definito in modo corretto, ma il problema è che Delphi compilatore genera prologo e epilogo per Foo, quindi il codice Foo reale è
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
A seguito dello stack è danneggiato, il parametro è sbagliato e barra degli indirizzi di ritorno è sbagliato. Se si vuole ancora fare il trucco, uso
function Foo(parameter: Integer): Integer; cdecl;
asm
pop ebp
mov eax, FunctionAddressList
jmp dword ptr [eax + 5 * 4]
end;
Altri suggerimenti
Array of Integer
non è quello che si pensa che è. Si tratta di un array dinamico gestito automaticamente.
Si dovrebbe provare lo stesso con FunctionAddressList: ^Pointer;
- nota, tuttavia, che si dovrà fare l'assegnazione manuale e deallocazione