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.

È stato utile?

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

.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top