C++程序的成员函数默认使用的调用约定是thiscall,这种约定是把this指针放到ECX寄存器中.This调用协定也是要求被调用函数负责清理栈,因此不支持可变数时的参数,当我们在C++类中定义了可变数量参数的成员函数时,偏译器会自动改为使用C调用约定,当这种调用时,编译器会将所有参数压入栈中,再将this指针压入栈:
关键两点:1.this时,是被调用函灵敏清理栈 2.如果可变参数,则使用C约定,由调用者来清理
写个小demo测试:
- #include "stdafx.h"
- #include <stdio.h>
- enum MEAL {BREAKFAST, LUNCH, SUPPER};
-
- class Cat
- {
- public:
- MEAL Fun0(MEAL i)
- {
- return i;
- }
- char* Fun1(MEAL i, ...)
- {
- return 0;
- }
- };
-
-
- int main(int argc, char* argv[])
- {
-
- Cat cat;
- cat.Fun0(BREAKFAST);
- cat.Fun1(BREAKFAST, "meat", "beaf", "rice");
-
- return 0;
- }
- 0:000> x ThisCall!Cat::*
- 00401060 ThisCall!Cat::Fun0 (MEAL)
- 00401090 ThisCall!Cat::Fun1 (MEAL)
- 0:000> x ThisCall!main
- 00401000 ThisCall!main (int, char **)
- 0:000> bp 00401000
先在main处下断点:
- ThisCall!main:
- 00401000 55 push ebp
- 00401001 8bec mov ebp,esp
- 00401003 83ec44 sub esp,44h
- 00401006 53 push ebx
- 00401007 56 push esi
- 00401008 57 push edi
- 00401009 8d7dbc lea edi,[ebp-44h]
- 0040100c b911000000 mov ecx,11h
- 00401011 b8cccccccc mov eax,0CCCCCCCCh
- 00401016 f3ab rep stos dword ptr es:[edi]
- 00401018 6a00 push 0
- 0040101a 8d4dfc lea ecx,[ebp-4]
- 0040101d e83e000000 call ThisCall!Cat::Fun0 (00401060)
- 00401022 68fce04000 push offset ThisCall!`string' (0040e0fc)
- 00401027 68f4e04000 push offset ThisCall!`string' (0040e0f4)
- 0040102c 68ece04000 push offset ThisCall!`string' (0040e0ec)
- 00401031 6a00 push 0
- 00401033 8d45fc lea eax,[ebp-4]
- 00401036 50 push eax
- 00401037 e854000000 call ThisCall!Cat::Fun1 (00401090)
- 0040103c 83c414 add esp,14h
这样就看得很清楚了.