|
DLL中调用约定和名称修饰(二)
4、thiscall
thiscall调用约定是C++中的非静态类成员函数的默认调用约定。thiscall只能被编译器使用,没有相应的关键字,因此不能被程序员指定。采用thiscall约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,只是另外通过ECX寄存器传送一个额外的参数:this指针。
这次的例子中将定义一个类,并在类中定义一个成员函数,代码如下:
class CSum
{
public:
int Add(int a, int b)
{
return (a + b);
}
};
void main()
{
CSum sum;
sum.Add(1, 2);
}
函数调用部分汇编代码:
;CSum sum;
;sum.Add(1, 2);
push 2 ;参数从右到左入栈,先压入2
push 1 ;压入1
lea ecx,[ebp-4] ;ecx存放了this指针
call @ILT+5(CSum::Add) (0040100a) ;调用函数实现
函数实现部分汇编代码:
;int Add(int a, int b)
push ebp
mov ebp,esp
sub esp,44h ;多用了一个4bytes的空间用于存放this指针
push ebx
push esi
push edi
push ecx
lea edi,[ebp-44h]
mov ecx,11h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi]
pop ecx
mov dword ptr [ebp-4],ecx
;return (a + b);
mov eax,dword ptr [ebp+8]
add eax,dword ptr [ebp+0Ch]
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret 8 ;清栈
5、naked属性
采用上面所述的四种调用约定的函数在进入函数时,编译器会产生代码来保存ESI、EDI、EBX、EBP寄存器中的值,退出函数时则产生代码恢复这些寄存器的内容。对于定义了naked属性的函数,编译器不会自动产生这样的代码,需要你手工使用内嵌汇编来控制函数实现中的堆栈管理。由于naked属性并不是类型修饰符,故必须和__declspec共同使用。下面的这段代码定义了一个使用了naked属性的函数及其实现:
__declspec ( naked ) func()
{
int i;
int j;
_asm
{
[1] [2] 下一页 |