开发者社区> 流楚丶格念> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

函数调用约定:__stdcall、__cdecl和__fastcall介绍

简介: 函数调用约定:__stdcall、__cdecl和__fastcall介绍
+关注继续查看

想深入了解可学习汇编语言去了解内存机制


一、问题引导:C语言中函数参数的入栈顺序


C程序栈底为高地址,栈顶为低地址。


C方式参数入栈顺序(从右至左)的好处就是可以动态变化参数个数。通过栈堆分析可知,自左向右的入栈方式,最前面的参数被压在栈底。除非知道参数个数,否则是无法通过栈指针的相对位移求得最左边的参数。这样就变成了左边参数的个数不确定,正好和动态参数个数的方向相反。


因此,C语言函数参数采用自右向左的入栈顺序,主要原因是为了支持可变长参数形式。


二、、函数调用约定(Calling Convention)


函数调用约定不仅决定了发生函数调用时函数参数的入栈顺序,还决定了是由调用者函数还是被调用函数负责清除栈中的参数,还原堆栈。函数调用约定有很多方式,除了常见的__cdecl,__fastcall和__stdcall之外,C++的编译器还支持thiscall方式,不少C/C++编译器还支持 naked call方式。这么多函数调用约定常常令许多程序员很迷惑,到底它们是怎么回事,都是在什么情况下使用呢?下面就分别介绍这几种函数调用约定。


1.__cdecl


编译器的命令行参数是/Gd.__cdecl方式是C/C++编译器默认的函数调用约定,所有非C++成员函数和那些没有用__stdcall或__fastcall声明的函数都默认是__cdecl方式,它使用C函数调用方式,函数参数按照从右向左的顺序入栈,函数调用者负责清除栈中的参数,由于每次函数调用都要由编译器产生清除(还原)堆栈的代码,所以使用__cdecl方式编译的程序比使用__stdcall方式编译的程序要大很多,但是 __cdecl调用方式是由函数调用者负责清除栈中的函数参数,所以这种方式支持可变参数,比如printf和windows的API wsprintf就是__cdecl调用方式。对于C函数,__cdecl方式的名字修饰约定是在函数名称前添加一个下划线;对于C++函数,除非特别使用extern “C”,C++函数使用不同的名字修饰方式。


2.__fastcall


编译器的命令行参数是/Gr.__fastcall函数调用约定在可能的情况下使用寄存器传递参数,通常是前两个 DWORD类型的参数或较小的参数使用ECX和EDX寄存器传递,其余参数按照从右向左的顺序入栈,被调用函数在返回之前负责清除栈中的参数。编译器使用两个@修饰函数名字,后跟十进制数表示的函数参数列表大小,例如:@function_name@number.需要注意的是__fastcall函数调用约定在不同的编译器上可能有不同的实现,比如16位的编译器和32位的编译器,另外,在使用内嵌汇编代码时,还要注意不能和编译器使用的寄存器有冲突。


3.__stdcall


编译器的命令行参数是/Gz,__stdcall是Pascal程序的缺省调用方式,大多数Windows的API也是__stdcall调用约定。__stdcall函数调用约定将函数参数从右向左入栈,除非使用指针或引用类型的参数,所有参数采用传值方式传递,由被调用函数负责清除栈中的参数。对于C函数,__stdcall的名称修饰方式是在函数名字前添加下划线,在函数名字后添加@和函数参数的大小,例如:_functionname@number


三、三者区别


__stdcall、__cdecl和__fastcall是三种函数调用协议,函数调用协议会影响函数参数的入栈方式、栈内数据的清除方式、编译器函数名的修饰规则等。


1、调用协议常用场合


__stdcall:Windows API默认的函数调用协议。


__cdecl:C/C++默认的函数调用协议。


__fastcall:适用于对性能要求较高的场合。


2、函数参数入栈方式


__stdcall:函数参数由右向左入栈。


__cdecl:函数参数由右向左入栈。


__fastcall:从左开始不大于4字节的参数放入CPU的ECX和EDX寄存器,其余参数从右向左入栈。


问题一:__fastcall在寄存器中放入不大于4字节的参数,故性能较高,适用于需要高性能的场合。


3、栈内数据清除方式


__stdcall:函数调用结束后由被调用函数清除栈内数据。


__cdecl:函数调用结束后由函数调用者清除栈内数据。


__fastcall:函数调用结束后由被调用函数清除栈内数据。


问题一:不同编译器设定的栈结构不尽相同,跨开发平台时由函数调用者清除栈内数据不可行。


问题二:某些函数的参数是可变的,如printf函数,这样的函数只能由函数调用者清除栈内数据。


问题三:由调用者清除栈内数据时,每次调用都包含清除栈内数据的代码,故可执行文件较大。


4、C语言编译器函数名称修饰规则


__stdcall:编译后,函数名被修饰为“_functionname@number”。


__cdecl:编译后,函数名被修饰为“_functionname”。


__fastcall:编译后,函数名给修饰为“@functionname@nmuber”。


注:“functionname”为函数名,“number”为参数字节数。


注:函数实现和函数定义时如果使用了不同的函数调用协议,则无法实现函数调用。


5、C++语言编译器函数名称修饰规则


__stdcall:编译后,函数名被修饰为“?functionname@@YG******@Z”。


__cdecl:编译后,函数名被修饰为“?functionname@@YA******@Z”。


__fastcall:编译后,函数名被修饰为“?functionname@@YI******@Z”。


注:“******”为函数返回值类型和参数类型表。


注:函数实现和函数定义时如果使用了不同的函数调用协议,则无法实现函数调用。

C语言和C++语言间如果不进行特殊处理,也无法实现函数的互相调用。


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
DL之R-FCN:R-FCN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
DL之R-FCN:R-FCN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
59 0
DL之GCN:GCN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
DL之GCN:GCN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
88 0
DL之DeconvNet:DeconvNet算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
DL之DeconvNet:DeconvNet算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
64 0
DL之FastR-CNN:Fast R-CNN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
DL之FastR-CNN:Fast R-CNN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
118 0
DL之FasterR-CNN:Faster R-CNN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略(一)
DL之FasterR-CNN:Faster R-CNN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
81 0
DL之FasterR-CNN:Faster R-CNN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略(二)
DL之FasterR-CNN:Faster R-CNN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
97 0
DL之LeNet-5:LeNet-5算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
DL之LeNet-5:LeNet-5算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
128 0
PowerDesigner16工具学习笔记-工具介绍
原文:PowerDesigner16工具学习笔记-工具介绍 1、初始界面 1.1 、浏览窗口:本地(Local)浏览窗口、知识库(Repository)浏览窗口       Local:用于显示本地模型       Repository:用于显示知识库模型 1.2 、输出窗口:用于显示操作过程中的相关信息。
1227 0
stdcall、cdecl 和pascal简介 .
这三个参数都是告诉编译器参数的传递约定,参数的传递约定是指参数的传递顺序(从左到右还是从右到左)和由谁来恢复堆栈指针(调用者或者是被调用者),在 Win16下有两种约定: C 和 PASCAL。     C约定规定参数传递顺序是从右到左,即最右边的参数最先压栈,由调用者恢复堆栈指针。
959 0
+关注
流楚丶格念
csdn平台优质创作者,51cto TOP博主,360图书馆科技博主,燕山大学目前大三在读,日拱一卒,功不唐捐,加油!!!
1010
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载