WEB开发网
开发学院软件开发VC 通用Thunk 阅读

通用Thunk

 2010-07-15 20:45:23 来源:WEB开发网   
核心提示:原理原理中最重要的是函数的调用约定(Calling Convention) ,调用者和被调者之间的约定,通用Thunk(2),普通C函数通常使用3种调用约定 : “__cdecl” “__stdcall” “__fastcall” 成员函数通常使用

原理

原理中最重要的是函数的调用约定(Calling Convention) ,调用者和被调者之间的约定。普通C函数通常使用3种调用约定 : “__cdecl” “__stdcall” “__fastcall” 成员函数通常使用 “__thiscall””__stdcall” “__cdecl”

我们需要着重关注以下3点:

调用者(普通C函数)怎么准备参数和返回地址?

被调用者(成员函数)希望并且要求的参数和返回地址是什么?它如何取得它们?

平衡堆栈是谁的责任?

调用者准备的参数和返回地址总不是被调用者所期待的那样,因为被调用者还需要一个this指针。平衡堆栈的方式也许也会不同。我们的工作就是以被调用者期望的方式,准备好this指针,同时弥补2者在平衡堆栈上的差异。

为了简单起见,我们以 “ void func(int); void C::func(int); ”为例,首先,我们来看看当使用__stdcall 约定的func被调用的时候,会发生什么。

func(1212); 编译器会像这样准备参数和返回地址 :

PUSH 1212 ; 使得堆栈增加4

CALL func; 使得堆栈也增加4(因为返回地址也被压入堆栈)

0x50000:...;被调用者返回这里,我们假设这里的地址是0x50000

调用者希望被调用者使用 RET 4 (使得堆栈减少8:参数1212使用4,返回地址0x50000也使用4)来平衡堆栈,所以在这之后没有多余的机器码。所以,在这之后,堆栈是这个样子:

...
1212
0x50000 <- ESP

然后,我们来看看使用__thiscall 的被调用者所希望的参数和返回地址。一个真正的成员函数被调用时。

C obj;
obj.func(1212);

编译器以这样的方式准备参数:

PUSH 1212;
MOV ECX,obj;
CALL C::func

所以,在这之后,堆栈是这个样子:


1212
0x50000 <- ESP

ECX 保存着 this 指针。

这也就是被调用者(void __thiscall C::func(int); ) 需要的形式。

上一页  1 2 3 4 5 6 7  下一页

Tags:通用 Thunk

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接