C/C++函数调用规则

来源:互联网 发布:商务数据分析要学什么 编辑:程序博客网 时间:2024/05/17 20:23

 我们知道,调用函数时,计算机常用栈来存放函数执行需要的参数,由于栈的空间大小是有限的,在windows下栈是向低地址扩展的数据结构,是一块连续的内存区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,windows下栈的大小是2M(也有的说是1M),如果申请的空间超过栈的剩余空间时,将提示overflow.

    在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。

    在参数传递中,有两个重要的问题必须要明确说明:

    1. 当参数个数多于一个时,按照什么顺序把参数压入堆栈;

    2. 函数调用后,由谁来把堆栈恢复原状。

    在高级语言中,就是通过函数的调用方式来说明这两个问题的。常见的调用方式有:

    stdcall

    cdecl

    fastcall

    thiscall

    thiscall

    naked call

    下面就分别介绍这几种调用方式:

    1. stdcall

    stdcall调用方式又被称为Pascal调用方式。在Microsoft C++系列的C/C++编译器中,使用PASCAL宏,WINAPI宏和CALLBACK宏来指定函数的调用方式为stdcall.

    stdcall调用方式的函数声明为:

    int _stdcall function(int a, int b);

    stdcall的调用方式意味着:

    (1) 参数从右向左依次压入堆栈

    (2) 由被调用函数自己来恢复堆栈

    (3) 函数名自动加前导下划线,后面紧跟着一个@,其后紧跟着参数的尺寸

    上面那个函数翻译成汇编语言将变成:

    push b 先压入第二个参数

    push a 再压入第一个参数

    call function 调用函数

    在编译时,此函数的名字被翻译为<a href="mailto:_function@8</P><P>%C2%A0%C2%A0%C2%A0 2. cdecl</P><P>%C2%A0%C2%A0%C2%A0 cdecl%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%E5%8F%88%E7%A7%B0%E4%B8%BAC%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%EF%BC%8C%E6%98%AFC%E8%AF%AD%E8%A8%80%E7%BC%BA%E7%9C%81%E7%9A%84%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%AE%83%E7%9A%84%E8%AF%AD%E6%B3%95%E4%B8%BA%EF%BC%9A</P><P>%C2%A0%C2%A0%C2%A0 int function%EF%BC%88int a, int b%EF%BC%89 // %E4%B8%8D%E5%8A%A0%E4%BF%AE%E9%A5%B0%E7%AC%A6%E5%B0%B1%E6%98%AFC%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F</P><P>%C2%A0%C2%A0%C2%A0 int _cdecl function%EF%BC%88int a, int b%EF%BC%89 // %E6%98%8E%E7%A1%AE%E6%8C%87%E5%AE%9A%E7%94%A8C%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F</P><P>%C2%A0%C2%A0%C2%A0 cdecl%E7%9A%84%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%E5%86%B3%E5%AE%9A%E4%BA%86%EF%BC%9A</P><P>%C2%A0%C2%A0%C2%A0 %EF%BC%881%EF%BC%89 %E5%8F%82%E6%95%B0%E4%BB%8E%E5%8F%B3%E5%90%91%E5%B7%A6%E4%BE%9D%E6%AC%A1%E5%8E%8B%E5%85%A5%E5%A0%86%E6%A0%88</P><P>%C2%A0%C2%A0%C2%A0 %EF%BC%882%EF%BC%89 %E7%94%B1%E8%B0%83%E7%94%A8%E8%80%85%E6%81%A2%E5%A4%8D%E5%A0%86%E6%A0%88</P><P>%C2%A0%C2%A0%C2%A0 %EF%BC%883%EF%BC%89 %E5%87%BD%E6%95%B0%E5%90%8D%E8%87%AA%E5%8A%A8%E5%8A%A0%E5%89%8D%E5%AF%BC%E4%B8%8B%E5%88%92%E7%BA%BF</P><P>%C2%A0%C2%A0%C2%A0 %E7%94%B1%E4%BA%8E%E6%98%AF%E7%94%B1%E8%B0%83%E7%94%A8%E8%80%85%E6%9D%A5%E6%81%A2%E5%A4%8D%E5%A0%86%E6%A0%88%EF%BC%8C%E5%9B%A0%E6%AD%A4C%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%E5%85%81%E8%AE%B8%E5%87%BD%E6%95%B0%E7%9A%84%E5%8F%82%E6%95%B0%E4%B8%AA%E6%95%B0%E6%98%AF%E4%B8%8D%E5%9B%BA%E5%AE%9A%E7%9A%84%EF%BC%8C%E8%BF%99%E6%98%AFC%E8%AF%AD%E8%A8%80%E7%9A%84%E4%B8%80%E5%A4%A7%E7%89%B9%E8%89%B2%E3%80%82</P><P>%C2%A0%C2%A0%C2%A0 %E6%AD%A4%E6%96%B9%E5%BC%8F%E7%9A%84%E5%87%BD%E6%95%B0%E8%A2%AB%E7%BF%BB%E8%AF%91%E4%B8%BA%EF%BC%9A</P><P>%C2%A0%C2%A0%C2%A0 push b // %E5%85%88%E5%8E%8B%E5%85%A5%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%8F%82%E6%95%B0</P><P>%C2%A0%C2%A0%C2%A0 push a // %E5%9C%A8%E5%8E%8B%E5%85%A5%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0</P><P>%C2%A0%C2%A0%C2%A0 call funtion // %E8%B0%83%E7%94%A8%E5%87%BD%E6%95%B0</P><P>%C2%A0%C2%A0%C2%A0 add esp, 8 // %E6%B8%85%E7%90%86%E5%A0%86%E6%A0%88 %E2%80%A6%E2%80%A6%E9%9C%80%E8%A6%81%E7%86%9F%E6%82%89%E4%B8%80%E4%B8%8Besp%E5%AF%84%E5%AD%98%E5%99%A8%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%BB%BA%E8%AE%AE%E7%9C%8B%E4%B8%80%E4%B8%8B%E6%B1%87%E7%BC%96%E6%9C%89%E5%85%B3%E7%9A%84%E4%B9%A6%EF%BC%8C%E5%9F%BA%E6%9C%AC%E9%83%BD%E6%9C%89%E8%AE%B2</P><P>%C2%A0%C2%A0%C2%A0 %E5%9C%A8%E7%BC%96%E8%AF%91%E6%97%B6%EF%BC%8C%E6%AD%A4%E6%96%B9%E5%BC%8F%E7%9A%84%E5%87%BD%E6%95%B0%E8%A2%AB%E7%BF%BB%E8%AF%91%E6%88%90%EF%BC%9A_function</P><P>%C2%A0%C2%A0%C2%A0 3. fastcall</P><P>%C2%A0%C2%A0%C2%A0 fastcall %E6%8C%89%E7%85%A7%E5%90%8D%E5%AD%97%E4%B8%8A%E7%90%86%E8%A7%A3%E5%B0%B1%E5%8F%AF%E4%BB%A5%E7%9F%A5%E9%81%93%EF%BC%8C%E5%AE%83%E6%98%AF%E4%B8%80%E7%A7%8D%E5%BF%AB%E9%80%9F%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%E3%80%82%E6%AD%A4%E6%96%B9%E5%BC%8F%E7%9A%84%E5%87%BD%E6%95%B0%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%92%8C%E7%AC%AC%E4%BA%8C%E4%B8%AADWORD%E5%8F%82%E6%95%B0%E9%80%9A%E8%BF%87ecx%E5%92%8Cedx%E4%BC%A0%E9%80%92%EF%BC%8C%E5%90%8E%E9%9D%A2%E7%9A%84%E5%8F%82%E6%95%B0%E4%BB%8E%E5%8F%B3%E5%90%91%E5%B7%A6%E7%9A%84%E9%A1%BA%E5%BA%8F%E5%8E%8B%E5%85%A5%E6%A0%88%E3%80%82</P><P>%C2%A0%C2%A0%C2%A0 %E8%A2%AB%E8%B0%83%E7%94%A8%E5%87%BD%E6%95%B0%E6%B8%85%E7%90%86%E5%A0%86%E6%A0%88%E3%80%82</P><P>%C2%A0%C2%A0%C2%A0 %E5%87%BD%E6%95%B0%E5%90%8D%E4%BF%AE%E4%B8%AA%E8%A7%84%E5%88%99%E5%90%8Cstdcall</P><P>%C2%A0%C2%A0%C2%A0 %E5%85%B6%E5%A3%B0%E6%98%8E%E8%AF%AD%E6%B3%95%E4%B8%BA%EF%BC%9A</P><P>%C2%A0%C2%A0%C2%A0 int fastcall function%EF%BC%88int a, int b%EF%BC%89%EF%BC%9B</P><P>%C2%A0%C2%A0%C2%A0 4. thiscall</P><P>%C2%A0%C2%A0%C2%A0 thiscall %E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%E6%98%AF%E5%94%AF%E4%B8%80%E4%B8%80%E7%A7%8D%E4%B8%8D%E8%83%BD%E6%98%BE%E7%A4%BA%E6%8C%87%E5%AE%9A%E7%9A%84%E4%BF%AE%E9%A5%B0%E7%AC%A6%E3%80%82%E5%AE%83%E6%98%AFc++%E7%B1%BB%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E7%BC%BA%E7%9C%81%E7%9A%84%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%E3%80%82%E7%94%B1%E4%BA%8E%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8%E8%BF%98%E6%9C%89%E4%B8%80%E4%B8%AAthis%E6%8C%87%E9%92%88%EF%BC%8C%E5%9B%A0%E6%AD%A4%E5%BF%85%E9%A1%BB%E7%94%A8%E8%BF%99%E7%A7%8D%E7%89%B9%E6%AE%8A%E7%9A%84%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%E3%80%82</P><P>%C2%A0%C2%A0%C2%A0 thiscall%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%E6%84%8F%E5%91%B3%E7%9D%80%EF%BC%9A</P><P>%C2%A0%C2%A0%C2%A0 %E5%8F%82%E6%95%B0%E4%BB%8E%E5%8F%B3%E5%90%91%E5%B7%A6%E5%8E%8B%E5%85%A5%E6%A0%88%E3%80%82</P><P>%C2%A0%C2%A0%C2%A0 %E5%A6%82%E6%9E%9C%E5%8F%82%E6%95%B0%E4%B8%AA%E6%95%B0%E7%A1%AE%E5%AE%9A%EF%BC%8Cthis%E6%8C%87%E9%92%88%E9%80%9A%E8%BF%87ecx%E4%BC%A0%E9%80%92%E7%BB%99%E8%A2%AB%E8%B0%83%E7%94%A8%E8%80%85%EF%BC%9B%E5%A6%82%E6%9E%9C%E5%8F%82%E6%95%B0%E4%B8%AA%E6%95%B0%E4%B8%8D%E7%A1%AE%E5%AE%9A%EF%BC%8Cthis%E6%8C%87%E9%92%88%E5%9C%A8%E6%89%80%E6%9C%89%E5%8F%82%E6%95%B0%E5%8E%8B%E5%85%A5%E6%A0%88%E5%90%8E%E8%A2%AB%E5%8E%8B%E5%85%A5%E6%A0%88%E3%80%82</P><P>%C2%A0%C2%A0%C2%A0 %E5%8F%82%E6%95%B0%E4%B8%AA%E6%95%B0%E4%B8%8D%E5%AE%9A%E7%9A%84%EF%BC%8C%E7%94%B1%E8%B0%83%E7%94%A8%E8%80%85%E6%B8%85%E7%90%86%E5%A0%86%E6%A0%88%EF%BC%8C%E5%90%A6%E5%88%99%E7%94%B1%E5%87%BD%E6%95%B0%E8%87%AA%E5%B7%B1%E6%B8%85%E7%90%86%E5%A0%86%E6%A0%88%E3%80%82</P><P>%C2%A0%C2%A0%C2%A0 %E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%EF%BC%8C%E5%AF%B9%E4%BA%8E%E5%8F%82%E6%95%B0%E4%B8%AA%E6%95%B0%E5%9B%BA%E5%AE%9A%E7%9A%84%E6%83%85%E5%86%B5%EF%BC%8C%E5%AE%83%E7%B1%BB%E4%BC%BC%E4%BA%8Estdcall,%E4%B8%8D%E5%AE%9A%E6%97%B6%E5%88%99%E7%B1%BB%E4%BC%BC%E4%BA%8Ecdecl.</P><P>%C2%A0%C2%A0%C2%A0 5. naked call</P><P>%C2%A0%C2%A0%C2%A0 %E6%98%AF%E4%B8%80%E7%A7%8D%E6%AF%94%E8%BE%83%E5%B0%91%E8%A7%81%E7%9A%84%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%EF%BC%8C%E4%B8%80%E8%88%AC%E9%AB%98%E7%BA%A7%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80%E4%B8%AD%E4%B8%8D%E5%B8%B8%E8%A7%81%E3%80%82</P><P>%C2%A0%C2%A0%C2%A0 %E5%87%BD%E6%95%B0%E7%9A%84%E5%A3%B0%E6%98%8E%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%AE%9E%E9%99%85%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F%E5%BF%85%E9%A1%BB%E4%B8%80%E8%87%B4%EF%BC%8C%E5%BF%85%E7%84%B6%E7%BC%96%E8%AF%91%E5%99%A8%E4%BC%9A%E4%BA%A7%E7%94%9F%E6%B7%B7%E4%B9%B1%E3%80%82</P><P>%C2%A0%C2%A0%C2%A0 %E5%87%BD%E6%95%B0%E5%90%8D%E5%AD%97%E4%BF%AE%E6%94%B9%E8%A7%84%E5%88%99%EF%BC%9A</P><P>%C2%A0%C2%A0%C2%A0 1. C%E7%BC%96%E8%AF%91%E6%97%B6%E5%87%BD%E6%95%B0%E5%90%8D%E4%BF%AE%E9%A5%B0%E7%BA%A6%E5%AE%9A%E8%A7%84%E5%88%99%EF%BC%9A</P><P>%C2%A0%C2%A0%C2%A0 __stdcall%E8%B0%83%E7%94%A8%E7%BA%A6%E5%AE%9A%E5%9C%A8%E8%BE%93%E5%87%BA%E5%87%BD%E6%95%B0%E5%90%8D%E5%89%8D%E5%8A%A0%E4%B8%8A%E4%B8%80%E4%B8%AA%E4%B8%8B%E5%88%92%E7%BA%BF%E5%89%8D%E7%BC%80%EF%BC%8C%E5%90%8E%E9%9D%A2%E5%8A%A0%E4%B8%8A%E4%B8%80%E4%B8%AA" @"符号和其参数的字节数,格式为_function@8.

    __cdecl调用约定仅在输出函数名前加上一个下划线前缀,格式为_function.

    __fastcall调用约定在输出函数名前加上一个"@"符号,后面也是一个"@"符号和其参数的字节数,格式为@function@8.

    它们均不改变输出函数名中的字符大小写,这和PASCAL调用约定不同,PASCAL约定输出的函数名无任何修饰且全部大写。

    2. C++编译时函数名修饰约定规则:

    __stdcall调用约定:

    (1)以"?"标识函数名的开始,后跟函数名;

    (2)函数名后面以"@@YG"标识参数表的开始,后跟参数表;

    (3)参数表以代号表示:

    X--void ,

    D--char,

    E--unsigned char,

    F--short,

    H--int,

    I--unsigned int,

    J--long,

    K--unsigned long,

    M--float,

    N--double,

    _N--bool,

    …

    PA--表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以"0"代替,一个"0"代表一次重复;

    (4)参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前;

    (5)参数表后以"@Z"标识整个名字的结束,如果该函数无参数,则以"Z"标识结束。

    其格式为"?functionname@@YG*****@Z"或"?functionname@@YG*XZ",例如

    int Test1(char *var1,unsigned long)-----"?Test1@@YGHPADK@Z"

    void Test2() -----"?Test2@@YGXXZ"

    __cdecl调用约定:

    规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YA".

    __fastcall调用约定:

    规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YI".

    VC++对函数的省缺声明是"__cedcl",将只能被C/C++调用。

原创粉丝点击