翻译使用指针代码,大会帕斯卡尔 - 德尔福
题
我有下面这段代码,我想将它翻译成ASM,在Delphi中使用过。
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;
它的工作原理normaly,但是当我尝试它的程序集的版本:
function Function(parameter: Integer): Integer; cdecl;
asm
mov eax, FunctionAddressList
jmp dword ptr [eax + 5 * 4]
end;
它应该的工作,因为,在C ++它工作在两种方式:
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);
}
但是,它确实在Delphi不工作。
在大会版本,它乘以阵列4,因为它的阵列中的每个元件之间的偏移大小,因此这两个版本是等价的。
所以,我想知道为什么它不与德尔福工作。在Delphi,一个阵列中的整数值之间的偏移大小是比C ++不同?
我已经尝试了许多的偏移,如1,2,4,6,8,等等和许多类型的阵列(指针的数组;只有指针;整数的数组,等等),并且我已经试过许多调用约定,和CDECL是唯一的,与非ASM版本的工作,但与ASM,所有的测试都没有工作。
感谢。
解决方案
首先测试应用程序以再现错误:
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;
在酒吧地址正确定义,但问题是,Delphi编译器生成的Foo序幕和收尾,所以真正的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
其结果是,堆被损坏,则参数是错误的,酒吧返回地址是错误的。如果你仍然想要做的伎俩,使用
function Foo(parameter: Integer): Integer; cdecl;
asm
pop ebp
mov eax, FunctionAddressList
jmp dword ptr [eax + 5 * 4]
end;
其他提示
Array of Integer
是不是你认为它是。这是一个自动管理动态数组。
您应该尝试使用相同FunctionAddressList: ^Pointer;
- 不过请注意,你将不得不做手工分配和释放
不隶属于 StackOverflow