zoukankan      html  css  js  c++  java
  • Calling Convention的总结

    因为经常需要和不同的Calling Convention打交道,前段时间整理了一下它们之间的区别,如下:

    清理堆栈

    参数压栈顺序

    命名规则 (MSVC++)

    备注

    Cdecl

    调用者 (Caller)

    从右往左 

    FuncName

    因为是调用者清理Stack,因此允许变参 (如printf)

    Pascal

    被调用者 (Callee)

    从左往右 

    已不再支持

    __pascal, __fortran, __syscall

    Stdcall

    被调用者 (Callee)

    从右往左

    _FuncName@N

    N表示所有参数大小字节数,如4

    一般在Windows API和COM中使用,也是.NET和Native代码调用的缺省Calling Convention。

    顺便提一下,Windows中API的Calling Convention所使用到的WINAPI宏在PC机上是__stdcall,而在WinCE上则是__cdecl,并非一成不变。

    Fastcall (Microsoft)

    被调用者 (Callee)

    从右往左

    @FuncName@N

    N表示参数大小字节数,如4

    和Stdcall类似,但是会选择两个从左往右数最先可以放在寄存器里面的参数放在ECX和EDX中

    Thiscall (Microsoft)

    被调用者 (Callee)

    从右往左

    编译器会将名字,类名,参数等编码到名字里面,具体方式和编译器相关,如:

    如?Func@MyClass@@QAEXPAX@Z

    基本上等价stdcall, 除了this指针用ECX传递

    稍微解释一下其中不是特别明显的几个列的意义:

    解释

    清理堆栈

    调用函数的时候,一般的参数都被调用者压栈(除了需要用寄存器传递的参数除外)。问题在于,谁来清理调用者压入堆栈的参数内容,是调用者还是被调用者。清理的意义是将压入的参数退栈,从机器的角度来讲则是调整堆栈指针ESP。当调用者也负责清理栈的时候,由于调用者知道实际参数的个数,因此可以正确处理变参的情况(如printf),就算是压入的参数和所期望的参数不一致也不会造成栈的不平衡,这正是printf可以很容易直接传入不同参数,而Windows API必须显式传入va_list参数(如FormatMessage)来获得变参能力的原因。

    压栈顺序

    参数被压栈的时候,如果有多个参数,参数可以以从左往右依次压入的顺序压入,也可以以从右往左的顺序,不同的Calling Convention之间存在区别。

  • 相关阅读:
    详细介绍C++STL:unordered_map
    NYOJ-626-intersection set(二分查找)
    hdoj-2141-Can you find it?(二分查找)
    HDU-1232-畅通工程(并查集)
    HDU-1213-How Many Tables(并查集)
    hdoj-2647-Reward(拓扑排序)
    hdoj-3342-Legal or Not(拓扑排序)
    hdoj-1285-确定比赛名次(拓扑排序)
    来一些方便的小操作:博客园(cnblog)自定义界面
    POJ--1094--Sorting It All Out||NYOJ--349--Sorting It All Out(拓扑排序)
  • 原文地址:https://www.cnblogs.com/Ph-one/p/8510776.html
Copyright © 2011-2022 走看看