Microsoft函数调用约定

对于所有调用共有的约定:ebx、ebp、esi、edi都是calle-save,即由被调用的函数负责它们的保存(如果被调用函数用到了这些寄存器的话)

先看函数调用发生了什么:(win32下)
1、所有参数提升到4bytes的倍数
2、执行call指令
3、将ebx、ebp、esi、edi保存在栈上,这一步称为function prolog
4、将返回值放在eax中(返回int64放在edx:eax中,返回double放在浮点寄存器中。复杂的数据结构在caller的栈中分配空间,将首地址做为最后压栈的参数(我拿__cdecl试的),callee返回的时候将返回值放在这个指针指向的地址)
5、取出ebx、ebp、esi、edi,这一步称为function epilog
6、清空栈,保持堆栈平衡,这一步称为stack cleanup

具体的调用约定:
1、__cdecl
压栈顺序:从右至左
清栈:函数调用者负责清空,称为caller cleanup
名字修饰(name decoration):在函数名前加上下划线做前缀,比如_foo
注:c/c++函数的缺省调用约定

2、__stdcall
压栈顺序:从右至左
清栈:被调用函数负责清空,称为callee cleanup
名字修饰:在函数名前加上下划线做前缀,名字后用@加上函数参数大小做后缀,如_foo@8
注:WINAPI就是__stdcall的#define

3、__fastcall
压栈顺序:第一个参数放在ecx,第二个参数放在edx,其余从右至左
清栈:callee cleanup
名字修饰:在函数名前加上@做前缀,名字后用@加上函数参数大小做后缀,如@foo@8
注:名字叫fast实际就不一定了……

4、thiscall
压栈顺序:this指针(cpp非静态成员函数特有)放在ecx,其余从右至左
清栈:callee cleanup
注:cpp非静态成员函数默认的调用约定

5、naked
压栈顺序:从右至左
清栈:caller cleanup
注:VxDs用的调用约定,将__declspec(naked)写在函数定义处(注意,不是声明)

这篇文章把naked作为calling convention: http://www.cs.cornell.edu/courses/cs412/2001sp/resources/microsoft-calling-conventions.htm

但naked应该算不上调用约定了,只是单纯地将c/c++代码翻译成asm,连esp、ebp之间的保存、mov都没有就直接拿ebp来寻址了,函数结束后也不管ret,太naked了!

补充:c允许可变参数(例如printf),为了方便地使用这些函数,所以__cdecl要
1、从右至左压栈(这样才能知道第一个参数在堆栈中的地址)
2、caller cleanup(因为只有caller才知道这次调用push了多少参数

函数调用约定的历史——16位的世界:

对所有的调用约定:
1、用dx:ax或ax保存返回值
2、由于cx不能寻址,所以还需要一个bx来scratch(就是不需要callee-save的寄存器)

具体的调用约定
1、__cdecl
名字修饰在函数前加下划线可能是为了区别函数名和汇编语言的关键字

2、__pascal
自左至右传参、callee cleanup
比较有意思的是名字修饰把函数名转换为大写,嗯,pascal大小写无关……
几乎所有的win16函数都是用pascal调用约定,因为callee-clean的操作比caller-clean要节省3bytes的空间

3、__fortran
和pascal一样

4、__fastcall
和win32下一样,把ecx、edx换为cx、dx罢了
这个fast可是未必,如果函数中的计算要用到cx、dx就免不了把cx、dx压栈的操作了,所以这种调用约定仅仅可能对短小的leaf function(就是不调用其他函数的函数)快一些,甚至对这类函数都快不了……

 

Microsoft函数调用约定的更多相关文章

  1. C语言函数调用约定

    在C语言中,假设我们有这样的一个函数: int function(int a,int b) 调用时只要用result = function(1,2)这样的方式就可以使用这个函数.但是,当高级语言被编译 ...

  2. 函数调用约定_stdcall[转]

    关键字 清理堆栈 参数入栈顺序 函数名称修饰(C) __cdecl 调用函数 右 à 左 _函数名 __stdcall 被调用函数 右 à 左 _函数名@数字 __fastcall 被调用函数 右 à ...

  3. Windows x64汇编函数调用约定

    最近在写一些字符串函数的优化,用到x64汇编,我也是第一次接触,故跟大家分享一下. x86:又名 x32 ,表示 Intel x86 架构,即 Intel 的32位 80386 汇编指令集. x64: ...

  4. 【黑客免杀攻防】读书笔记7 - 软件逆向工程基础1(函数调用约定、Main函数查找)

    0x1 准备工作 1.1.准备工具 IDA:交互式反汇编工具 OllyDbg:用户层调试工具 Visual Studio:微软开发工具 1.2.基础知识 C++开发 汇编语言 0x2 查找真正的mai ...

  5. 汇编  cdecl 函数调用约定,stdcall 函数调用约定

    知识点:  cdecl 函数调用约定  stdcall 函数调用约定  CALL堆栈平衡 配置属性--> c/c++ -->高级-->调用约定 一.cdecl调用约定 VC++ ...

  6. 关于函数调用约定-thiscall调用约定

    函数调用约定描述了如何以正确的方式调用某些特定类型的函数.包括了函数参数在栈上的分配顺序.有哪些参数将通过寄存器传入,以及在函数返回时函数栈的回收方式等. 函数调用约定的几种类型 stdcall,cd ...

  7. C/C++函数调用约定与this指针

    关于 C/C++ 函数调用约定,大多数时候并不会影响程序逻辑,但遇到跨语言编程时,了解一下还是有好处的. VC 中默认调用是 __cdecl 方式,Windows API 使用 __stdcall 调 ...

  8. c++中的几种函数调用约定(转)

    C++中的函数调用约定(调用惯例)主要针对三个问题: 1.参数传递的方式(是否采用寄存器传递参数.采用哪个寄存器传递参数.参数压桟的顺序等): 参数的传递方式,最常见的是通过栈传递.函数的调用方将参数 ...

  9. 关于 C/C++ 函数调用约定

    关于 C/C++ 函数调用约定,大多数时候并不会影响程序逻辑,但遇到跨语言编程时,了解一下还是有好处的. VC 中默认调用是 __cdecl 方式,Windows API 使用 __stdcall 调 ...

随机推荐

  1. 洛谷 P1731 [NOI1999]生日蛋糕

    P1731 [NOI1999]生日蛋糕 题目背景 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层 生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M ...

  2. 使用uncss去除无用的CSS

    1.安装nodejs,gulp,gulp_uncss 1.1.说明:gulp-uncss 是gulp的一个插件.gulp是基于nodejs,理所当然需要安装nodejs: 1.2.安装:打开nodej ...

  3. ArcGIS Server启动服务报:ERROR: Unable to start Xvfb on any port in the range 6600 - 6619

    http://blog.csdn.net/linghe301/article/details/10094421 今天尝试在Linux环境下安装ArcGIS Server10.2,启动服务碰到一个错误: ...

  4. 每天一个JavaScript实例-获取元素当前高度

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  5. 一个有意思的Ruby Webdriver超时问题的解决过程

    rescue in receive 由于写ruby的时候感觉混身上下都拽起来了,所以比較喜欢用ruby写代码. 今天遇到了一个webdriver timeout的问题,问题本身还是由于我对webdri ...

  6. SQL Server 存储过程具体解释

    SQL Server 存储过程具体解释 存储过程的优缺点 ◆长处: 运行速度更快. 存储过程仅仅在创造时进行编译,而一般SQL语句每运行一次就编译一次,所以使用存储过程运行速度更快. 存储过程用于处理 ...

  7. mac上为nginx打开防火墙

    1 nginx的路径必须是物理路径,不能是链接 2 执行下面的两个命令后重启电脑 命令 sudo /usr/libexec/ApplicationFirewall/socketfilterfw --a ...

  8. linux driver开发

    1 开发linux driver时的调试思路 基本上是打印调试,原因很简单,方便.或者使用工具挂住cpu.

  9. 【Linux 内核网络协议栈源码剖析】网络栈主要结构介绍(socket、sock、sk_buff,etc)

    原文:http://blog.csdn.net/wenqian1991/article/details/46700177 通过前面的分析,可以发现,网络协议栈中的数据处理,都是基于各类结构体,所有有关 ...

  10. Ubuntu 16.04安装JDK/JRE并配置环境变量【转】

    本文转载自:http://www.linuxdiyf.com/linux/30302.html 作为一个Linux新手,在写这篇文章之前,安装了几次jdk,好多次都是环境变量配置错误,导致无法登录系统 ...