C-函数调用惯例(Calling Convention)

来源:互联网 发布:淘宝号在哪买 编辑:程序博客网 时间:2024/05/16 10:22

调用惯例一般包括以下三方面的内容:

·         函数参数的传递顺序和方式

·         栈的维护方式

·         名字修饰(Name-mangling)的策略

在C语言里,存在着多个调用惯例,而默认的调用惯例是:cdecl。任何一个没有显示指定调用惯例的函数都默认是cdecl惯例。对于函数:int foo(int n, float m)而言,它的完整形式是:

    int _cdecl foo(int n, float m)  (MSVC编译器)

此外,还存在很多别的调用惯例:cdecl,stdcall,fastcall,pascal四种调用惯例,之间的具体区别如下表:

调用惯例

出栈方

参数传递

名字修饰

cdecl

函数调用方

从右至左的顺序压参数入栈

下划线+函数名

stdcall

函数本身

从右至左的顺序压参数入栈

下划线+函数名+@+参数的字节数,如函数int func(int a, double b)的修饰名是_func@12

fastcall

函数本身

头两个DWORD4字节)类型或占更少字节的参数被放入寄存器,其他剩下的参数按从右到左的顺序压入栈

@+函数名+@+参数的字节数

pascal

函数本身

从左至右的顺序压参数入栈

较为复杂, 参见pascal文档

 

    此外,不少编译器还提供一种称为naked call的调用惯例, 这种调用惯例在特殊的场合,其特点是编译器不产生任何保护寄存器的代码,故称故称为naked call。

    对于C++语言,以上几种调用惯例的名字修饰策略都有所改变(C++有自己更加复杂的名字修饰策略)。