常用的调用约定有stdcall,cdecl,fastcall,thiscall,naked call等,以下将 __stdcall、__cdecl和__fastcall三种函数调用协议加以比较,函数调用协议会影响函数参数的入栈方式、栈内数据的清除方式、编译器函数名的修饰规则等。

注: _stdcall是早期16位系统中使用的调用约定,本质是就是stdcall,现行的主要是__stdcall。

  • 调用协议常用场合
    1. __stdcall:Windows API默认的函数调用协议。
    2. __cdecl:C/C++默认的函数调用协议。
    3. __fastcall:适用于对性能要求较高的场合。
  • 函数参数入栈方式
    1. __stdcall:函数参数由右向左入栈。
    2. __cdecl:函数参数由右向左入栈。
    3. __fastcall:从左开始不大于4字节的参数放入CPU的ECX和EDX寄存器,其余参数从右向左入栈。

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

  • 栈内数据清除方式
    1. __stdcall:函数调用结束后由被调用函数清除栈内数据。
    2. __cdecl:函数调用结束后由函数调用者清除栈内数据。
    3. __fastcall:函数调用结束后由被调用函数清除栈内数据。

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

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

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

  • C语言编译器函数名称修饰规则
    1. __stdcall:编译后,函数名被修饰为“_functionname@number”。
    2. __cdecl:编译后,函数名被修饰为“_functionname”。
    3. __fastcall:编译后,函数名给修饰为“@functionname@nmuber”。

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

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

  • C++语言编译器函数名称修饰规则
    1. __stdcall:编译后,函数名被修饰为“?functionname@@YG******@Z”。
    2. __cdecl:编译后,函数名被修饰为“?functionname@@YA******@Z”。
    3. __fastcall:编译后,函数名被修饰为“?functionname@@YI******@Z”。

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

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

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

__stdcall、__cdcel、__fastcall 调用的更多相关文章

  1. C调用约定__cdecl、__stdcall、__fastcall、__pascal分析

    参考原文地址:https://www.cnblogs.com/yenyuloong/p/9626658.html C/C++ 中不同的函数调用规则会生成不同的机器代码,产生不同的微观效果,接下来让我们 ...

  2. __cdecl、__stdcall、__fastcall 与 __pascal 浅析

    call 指令与 retn 指令 首先我们得了解 CALL 和 RETN 指令的作用,才能更好地理解调用规则,这也是先决条件. 实际上,CALL 指令就是先将下一条指令的 EIP 压栈,然后 JMP ...

  3. __stdcall,__cdecl,__fastcall的区别

    __stdcall,__cdecl,__fastcall的区别 标签: dll编译器pascalclassimportinitialization 2009-12-09 15:07 10472人阅读  ...

  4. __cdecl、__stdcall、__fastcall、thiscall 进栈、出栈区别

    https://en.wikipedia.org/wiki/X86_calling_conventions https://msdn.microsoft.com/en-us/library/984x0 ...

  5. __stdcall,__cdecl,__fastcall,_stdcall,_cdecl,_fastcall 区别简介[转]

    今天写线程函数时,发现msdn中对ThreadProc的定义有要求: DWORD WINAPI ThreadProc(LPVOID lpParameter);   不解为什么要用WINAPI宏定义,查 ...

  6. 闲话__stdcall, __cdecl, __fastcall出现的历史背景以及各自解决的问题

    可以认为最先由微软搞出来了__stdcall, 其实就是和WINAPI的声明是一样的,入栈顺序是从右到左,函数返回时,会进行出栈操作. PASCAL语言是非常古老的编程语言,在C语言之前,因此在当时的 ...

  7. 【C/C++开发】__stdcall,__cdecl,__fastcall的区别

    __stdcall和__cdecl的区别 __stdcall和__cdecl是两种函数名字修饰.(注意是连续的两个下划线) Windows上 windows上不管是C还是C++,默认使用的都是__st ...

  8. 关于__stdcall和__cdecl调用方式的理解

    __stdcall和__cdecl都是函数调用约定关键字,先给出这两者的区别,然后举实例分析: __stdcall:参数由右向左压入堆栈:堆栈由函数本身清理. __cdecl:参数也是由右向左压入堆栈 ...

  9. printf不定参数

    title: printf不定参数 tags: C ARM date: 2018-10-21 12:14:58 --- 不定参数的传递 函数调用时参数传递是使用堆栈来实现的,参数入栈顺序是从右向左,在 ...

随机推荐

  1. so的封装和使用

    背景 在linux平台下,要实现函数的封装,一般采用的是so动态库的形式 实现了函数的封装就意味着实现过程的隐藏 可以实现跨平台和跨语言的使用 实施步骤 生成so动态库 编写相应的c文件代码,实现函数 ...

  2. Redis高级主题

    Redis高级主题   持久化 Redis 支持持久化, 其持久化数据有两种方式. 两种可以同时使用. 如果同时使用, Reids 在重启时将使用 AOF 方式来还原数据. RDB 按照一定策略定时同 ...

  3. docker端口映射和容器互相访问

    端口映射 容器运行时如果没有指定端口,与外界是无法通信的,比如当前我们的有一台MySQL的docker container,当前容器正在运行mysql并提供3306端口 # docker ps CON ...

  4. FFmpeg4.0笔记:封装ffmpeg的视频帧转换功能类CSws

    Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CSws.h /************************* ...

  5. Ruby Rails正式学习:Ruby on Rails 做个演示项目吧,逐渐完善

    项目开始 一. 新建Rails项目 1. 修改一下Gemfile文件(简单修改一下) source 'https://rubygems.org' git_source(:github) { |repo ...

  6. monggoDB添加到windows服务

    ----------------mongoDB安装------------------------------- 1.下载mongoDB安装包安装完毕后,配置环境变量 D:\Program Files ...

  7. AWS In Action

    Core Services of AWS Elastic Cloud Compute(EC2) Simple Storage Service(S3) Relational Database Servi ...

  8. Hive编程指南读书笔记(1):

    1.Mapreduce是一种计算模型,将计算任务分割成多个可以在服务器集群中并行执行的任务,然后分散到一群家用的或者服务器级别的硬件机器上,从而降低成本并提供水平可伸缩性. 2.mapreduce的两 ...

  9. js css3 固定点拖拽旋转

    一.直接上效果图: 然后是代码: 一共两种实现方式: <!DOCTYPE html> <html lang="en"> <head> <m ...

  10. 07 Python中zip(),map(),filter(),reduce()用法

    一. zip() zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表. 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 ...