函数调用约定

来源:互联网 发布:m1协同软件 编辑:程序博客网 时间:2024/05/18 02:10
函数调用约定 
  常见的函数调用约定[5]:cdecl,stdcall,fastcall,thiscall,naked call
  MFC调用约定(VS6:Project Settings->C/C++ Calling convention:) 
 
1, __cdecl(C调用约定.The C default calling convention)C/C++ 缺省调用方式 
  1)压栈顺序:函数参数从右到左 
  2)参数栈维护:由调用函数把参数弹出栈,传送参数的内存栈由调用函数来维护 
  (正因为如此,实现可变参数vararg的函数(如printf)只能使用该调用约定) 
  3)函数修饰名约定:VC将函数编译后会在函数名前面加上下划线前缀 
  4)每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大 
 
2, __stdcall (Pascal方式清理C方式压栈,通常用于Win32 Api中) 
  1)压栈顺序:函数参数从右到左的压栈顺序 
  2)参数栈维护:被调用函数把参数弹出栈(在退出时清空堆栈)
 3)函数修饰名约定:VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数
    ex. VC: int f(void *p) (编译后)-> _f@4(在外部汇编语言里可以用这个名字引用这个函数) 
 
3, __fastcall (快速调用约定,通过寄存器来传送参数) 
  1)压栈顺序:用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送 
  2)参数栈维护:被调用函数在返回前清理传送参数的内存栈 
  3)函数修饰名约定:VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数 
 
4, thiscall (本身调用,仅用于“C++”成员函数) 
  1)压栈顺序:this指针存放于CX/ECX寄存器中,参数从右到左的压栈顺序 
  2)thiscall不是关键词,因此不能被程序员指定 
 
5, naked call (裸调) 
  1)当采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来 
    保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容 
   (这些代码称作 prolog and epilog code,一般,ebp,esp的保存是必须的) 
  2)naked call不产生这样的代码。naked call不是类型修饰符,故必须和_declspec共同使用 
0 0
原创粉丝点击