Translate a code using pointer, to Assembly in Pascal - Delphi
I have this code below, and I want to translate it to ASM, to use in Delphi too.
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;
It works normaly, but when I try its Assembly version:
function Function(parameter: Integer): Integer; cdecl;
asm
mov eax, FunctionAddressList
jmp dword ptr [eax + 5 * 4]
end;
It is sup开发者_JAVA百科posed to work, because, in C++ it works in both ways:
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);
}
But it doesn't work in Delphi.
In the Assembly version, it multiplies the array to 4, because it's the offset size between each element of the array, so both versions are equivalent.
So, I want to know why it doesn't work with Delphi. In Delphi, the offset size between Integer values in a array is different than C++?
I've already tried many offsets, as 1, 2, 4, 6, 8, etc. And many types of Array (Array of Pointer; only Pointer; Array of Integer, etc), and I've tried many calling conventions, and cdecl was the only that worked with the non-asm version, but with ASM, all the tests didn't work.
Thanks.
First test app to reproduce 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;
The Bar address is defined correctly, but the problem is that Delphi compiler generates prologue and epilog for Foo, so real Foo code is
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
As a result the stack is corrupted, the parameter is wrong and Bar return address is wrong. If you still want to do the trick, use
function Foo(parameter: Integer): Integer; cdecl;
asm
pop ebp
mov eax, FunctionAddressList
jmp dword ptr [eax + 5 * 4]
end;
Array of Integer
is not what you think it is. It's an automatically managed dynamic array.
You should try the same using FunctionAddressList: ^Pointer;
-- note however that you will have to do manual allocation and deallocation.
精彩评论