__stdcall、__cdcel、__fastcall 调用
常用的调用约定有stdcall,cdecl,fastcall,thiscall,naked call等,以下将 __stdcall、__cdecl和__fastcall三种函数调用协议加以比较,函数调用协议会影响函数参数的入栈方式、栈内数据的清除方式、编译器函数名的修饰规则等。
注: _stdcall是早期16位系统中使用的调用约定,本质是就是stdcall,现行的主要是__stdcall。
- 调用协议常用场合
- __stdcall:Windows API默认的函数调用协议。
- __cdecl:C/C++默认的函数调用协议。
- __fastcall:适用于对性能要求较高的场合。
- 函数参数入栈方式
- __stdcall:函数参数由右向左入栈。
- __cdecl:函数参数由右向左入栈。
- __fastcall:从左开始不大于4字节的参数放入CPU的ECX和EDX寄存器,其余参数从右向左入栈。
问题一:__fastcall在寄存器中放入不大于4字节的参数,故性能较高,适用于需要高性能的场合。
- 栈内数据清除方式
- __stdcall:函数调用结束后由被调用函数清除栈内数据。
- __cdecl:函数调用结束后由函数调用者清除栈内数据。
- __fastcall:函数调用结束后由被调用函数清除栈内数据。
问题一:不同编译器设定的栈结构不尽相同,跨开发平台时由函数调用者清除栈内数据不可行。
问题二:某些函数的参数是可变的,如printf函数,这样的函数只能由函数调用者清除栈内数据。
问题三:由调用者清除栈内数据时,每次调用都包含清除栈内数据的代码,故可执行文件较大。
- C语言编译器函数名称修饰规则
- __stdcall:编译后,函数名被修饰为“_functionname@number”。
- __cdecl:编译后,函数名被修饰为“_functionname”。
- __fastcall:编译后,函数名给修饰为“@functionname@nmuber”。
注:“functionname”为函数名,“number”为参数字节数。
注:函数实现和函数定义时如果使用了不同的函数调用协议,则无法实现函数调用。
- C++语言编译器函数名称修饰规则
- __stdcall:编译后,函数名被修饰为“?functionname@@YG******@Z”。
- __cdecl:编译后,函数名被修饰为“?functionname@@YA******@Z”。
- __fastcall:编译后,函数名被修饰为“?functionname@@YI******@Z”。
注:“******”为函数返回值类型和参数类型表。
注:函数实现和函数定义时如果使用了不同的函数调用协议,则无法实现函数调用。
C语言和C++语言间如果不进行特殊处理,也无法实现函数的互相调用。
__stdcall、__cdcel、__fastcall 调用的更多相关文章
- C调用约定__cdecl、__stdcall、__fastcall、__pascal分析
参考原文地址:https://www.cnblogs.com/yenyuloong/p/9626658.html C/C++ 中不同的函数调用规则会生成不同的机器代码,产生不同的微观效果,接下来让我们 ...
- __cdecl、__stdcall、__fastcall 与 __pascal 浅析
call 指令与 retn 指令 首先我们得了解 CALL 和 RETN 指令的作用,才能更好地理解调用规则,这也是先决条件. 实际上,CALL 指令就是先将下一条指令的 EIP 压栈,然后 JMP ...
- __stdcall,__cdecl,__fastcall的区别
__stdcall,__cdecl,__fastcall的区别 标签: dll编译器pascalclassimportinitialization 2009-12-09 15:07 10472人阅读 ...
- __cdecl、__stdcall、__fastcall、thiscall 进栈、出栈区别
https://en.wikipedia.org/wiki/X86_calling_conventions https://msdn.microsoft.com/en-us/library/984x0 ...
- __stdcall,__cdecl,__fastcall,_stdcall,_cdecl,_fastcall 区别简介[转]
今天写线程函数时,发现msdn中对ThreadProc的定义有要求: DWORD WINAPI ThreadProc(LPVOID lpParameter); 不解为什么要用WINAPI宏定义,查 ...
- 闲话__stdcall, __cdecl, __fastcall出现的历史背景以及各自解决的问题
可以认为最先由微软搞出来了__stdcall, 其实就是和WINAPI的声明是一样的,入栈顺序是从右到左,函数返回时,会进行出栈操作. PASCAL语言是非常古老的编程语言,在C语言之前,因此在当时的 ...
- 【C/C++开发】__stdcall,__cdecl,__fastcall的区别
__stdcall和__cdecl的区别 __stdcall和__cdecl是两种函数名字修饰.(注意是连续的两个下划线) Windows上 windows上不管是C还是C++,默认使用的都是__st ...
- 关于__stdcall和__cdecl调用方式的理解
__stdcall和__cdecl都是函数调用约定关键字,先给出这两者的区别,然后举实例分析: __stdcall:参数由右向左压入堆栈:堆栈由函数本身清理. __cdecl:参数也是由右向左压入堆栈 ...
- printf不定参数
title: printf不定参数 tags: C ARM date: 2018-10-21 12:14:58 --- 不定参数的传递 函数调用时参数传递是使用堆栈来实现的,参数入栈顺序是从右向左,在 ...
随机推荐
- so的封装和使用
背景 在linux平台下,要实现函数的封装,一般采用的是so动态库的形式 实现了函数的封装就意味着实现过程的隐藏 可以实现跨平台和跨语言的使用 实施步骤 生成so动态库 编写相应的c文件代码,实现函数 ...
- Redis高级主题
Redis高级主题 持久化 Redis 支持持久化, 其持久化数据有两种方式. 两种可以同时使用. 如果同时使用, Reids 在重启时将使用 AOF 方式来还原数据. RDB 按照一定策略定时同 ...
- docker端口映射和容器互相访问
端口映射 容器运行时如果没有指定端口,与外界是无法通信的,比如当前我们的有一台MySQL的docker container,当前容器正在运行mysql并提供3306端口 # docker ps CON ...
- FFmpeg4.0笔记:封装ffmpeg的视频帧转换功能类CSws
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CSws.h /************************* ...
- Ruby Rails正式学习:Ruby on Rails 做个演示项目吧,逐渐完善
项目开始 一. 新建Rails项目 1. 修改一下Gemfile文件(简单修改一下) source 'https://rubygems.org' git_source(:github) { |repo ...
- monggoDB添加到windows服务
----------------mongoDB安装------------------------------- 1.下载mongoDB安装包安装完毕后,配置环境变量 D:\Program Files ...
- AWS In Action
Core Services of AWS Elastic Cloud Compute(EC2) Simple Storage Service(S3) Relational Database Servi ...
- Hive编程指南读书笔记(1):
1.Mapreduce是一种计算模型,将计算任务分割成多个可以在服务器集群中并行执行的任务,然后分散到一群家用的或者服务器级别的硬件机器上,从而降低成本并提供水平可伸缩性. 2.mapreduce的两 ...
- js css3 固定点拖拽旋转
一.直接上效果图: 然后是代码: 一共两种实现方式: <!DOCTYPE html> <html lang="en"> <head> <m ...
- 07 Python中zip(),map(),filter(),reduce()用法
一. zip() zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表. 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 ...