Pregunta

Tengo este código de abajo, y quiero traducirlo a ASM, para su uso en Delphi también.

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;

Funciona normaly, pero cuando trato de su versión Asamblea:

function Function(parameter: Integer): Integer; cdecl;
asm
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;

Se supone que es el trabajo, ya que, en C ++ funciona en ambos sentidos:

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);
}

Sin embargo, no funciona en Delphi.

En la versión Asamblea, se multiplica la matriz a 4, porque es el tamaño de desplazamiento entre cada elemento de la matriz, por lo que ambas versiones son equivalentes.

Por lo tanto, me gustaría saber por qué no funciona con Delphi. En Delphi, el tamaño de desplazamiento entre los valores de número entero en una matriz es diferente de C ++?

He intentado ya muchas compensaciones, como 1, 2, 4, 6, 8, etc, y muchos tipos de matriz (matriz de puntero, sólo Pointer; matriz de enteros, etc.), y he probado muchos convenciones de llamada, y cdecl fue el único que trabajó con la versión no asm, pero con ASM, todas las pruebas no funcionaba.

Gracias.

¿Fue útil?

Solución

En primer aplicación de prueba para reproducir el error:

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 de direcciones se define correctamente, pero el problema es que Delphi compilador genera prólogo y epílogo de Foo, por lo que el código real es Foo

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

Como resultado se corrompe la pila, el parámetro es incorrecta y la dirección de retorno Bar está mal. Si todavía quiere hacer el truco, el uso

function Foo(parameter: Integer): Integer; cdecl;
asm
  pop ebp
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;

Otros consejos

Array of Integer no es lo que piensa que es. Es una matriz dinámica gestionada automáticamente.

Se debe tratar de la misma utilizando FunctionAddressList: ^Pointer; - Nota sin embargo que va a tener que hacer la asignación manual y cancelación de asignación

.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top