前言

基础的类,默认调用成员函数使用的调用约定是_thiscall


正文

先随便写一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>

class Box{
int x;
public:
void Add(int a){
x += a;
std::cout << x << std::endl;
}
};

int main(){
Box b1;
b1.Add(10);

return 0;
}

然后反汇编看调用Add的时候

1
2
3
4
5
	Box b1;
b1.Add(10);
002119AF 6A 0A push 0Ah
002119B1 8D 4D F4 lea ecx,[b1]
002119B4 E8 8C F7 FF FF call Box::Add (0211145h)

像这种调用ecx寄存器存放实例化对象的指针的调用约定就是_thiscall

但是别人写的不一定就按照这个调用约定,之前学过的几种函数调用约定方式就可以套。

1
2
3
4
5
6
7
8
9
10
11
12
class Box{
int x;
public:
void Add(int a){
x += a;
std::cout << x << std::endl;
}
void _stdcall Add(int a, int b){
x += a + b;
std::cout << x << std::endl;
}
};
1
2
3
4
5
6
7
	Box b1;
b1.Add(100, 200);
000619AF 68 C8 00 00 00 push 0C8h
000619B4 6A 64 push 64h
000619B6 8D 45 F4 lea eax,[b1]
000619B9 50 push eax
000619BA E8 0B FA FF FF call Box::Add (0613CAh)

参数入栈而言,都是从右往左

不过这种调用约定就不用ecx了,而是把b1的地址传给eax,再把eax当初参数压入栈中。

还有就是_stdcall的堆栈平衡是由函数自己恢复
也就是函数结尾的时候ret 有一个值

另外还有几种函数调用也可以试下


结语

提一嘴,后面解读别的程序的时候不会显得太懵逼。