前言 基础的类,默认调用成员函数使用的调用约定是_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 ); 002119 AF 6 A 0 A push 0 Ah 002119B 1 8 D 4 D F4 lea ecx,[b1] 002119B 4 E8 8 C F7 FF FF call Box::Add (0211145 h)
像这种调用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 ); 000619 AF 68 C8 00 00 00 push 0 C8h 000619B 4 6 A 64 push 64 h 000619B 6 8 D 45 F4 lea eax,[b1] 000619B 9 50 push eax 000619B A E8 0B FA FF FF call Box::Add (0613 CAh)
参数入栈而言,都是从右往左
不过这种调用约定就不用ecx了,而是把b1的地址传给eax,再把eax当初参数压入栈中。
还有就是_stdcall
的堆栈平衡是由函数自己恢复 也就是函数结尾的时候ret 有一个值
另外还有几种函数调用也可以试下
结语 提一嘴,后面解读别的程序的时候不会显得太懵逼。