2010-01-31 60 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