2010-01-31 63 views
3

我有下面的代码,我想将它翻译成ASM,也可以在Delphi中使用。使用指针转换代码,以汇编在Pascal中 - Delphi

​​

它的工作原理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中不起作用。

在Assembly版本中,它将数组乘以4,因为它是数组每个元素之间的偏移量,所以两个版本都是等价的。

所以,我想知道为什么它不适用于Delphi。在Delphi中,数组中Integer值之间的偏移量大小与C++不同?

我已经尝试了许多偏移量,例如1,2,4,6,8等。还有很多类型的Array(指针数组;仅指针;整数数组等等),并且我试过了许多调用约定,并且cdecl是唯一与非asm版本一起工作的,但对于ASM,所有测试都不起作用。

谢谢。

回答

3

首先测试应用程序以再现错误:

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 

因此堆栈损坏,参数错误,Bar返回地址错误。如果你仍然想要做的伎俩,使用

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

我现在没有使用C++,但我认为你的C++(我认为你使用Visual C++)裸函数的代码也假设栈上的参数。您必须自己编写序言和epilog(以asm的形式)以使用cdecl调用约定的裸函数中的参数。你不这样做,因为你不需要这里的参数,并把它传递给地址列表中的函数。 – kludg 2010-02-01 01:11:22

1

Array of Integer是不是你认为它是。这是一个自动管理的动态数组。

您应该尝试使用FunctionAddressList: ^Pointer; - 但请注意,您将不得不手动分配和取消分配。

+0

我已经分配FunctionAddressList,但它仍然无法正常工作,我必须将'* 4'值更改为另一个? – 2010-01-31 22:49:39

+0

@Edward - 不要使用4,使用SizeOf(指针)。如果你在64位系统上,它不会是4. – 2010-01-31 23:15:12