鱼C论坛

 找回密码
 立即注册
查看: 2185|回复: 0

[技术交流] 对四种调用约定的一些理解和不解

[复制链接]
发表于 2018-8-24 15:50:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 代号3 于 2018-8-24 15:48 编辑


本贴中依次测验不加关键字的VS编译器默认C++调用  __cdecl调用 __stdcall调用 __fastcall调用 __thiscall调用 共4种函数调用约定 6次实验
首先测验不加关键词情况下的默认函数调用
#include "stdafx.h"
int  fun(int num1, int num2)
{
        return printf("%d\n", num1 + num2);
}

int main()
{
        fun(3, 4);
    return 0;
}
        在main函数出设置断点 修改VS链接器设置 如下图
QQ截图20180823144543.png
        F10单步调试 ALT+8调出反汇编窗口记录mian函数基址如下图
QQ截图20180823144851.png
然后进入OD中 Ctrl+G输入main函数基址 在入口处右键设置新的EIP F8单步开始测试函数调用堆栈 在CALL出F7步入函数观察堆栈变化
aaa4d31b-8904-41e8-9913-501daa4b3731.png
可以观察到默认调用中main函数通过ADD ESP的方式对函数进行堆栈平衡 并可以推测函数中调用参数为2个  同样在__cdcel调用中依然如此
#include "stdafx.h"
int __cdecl fun(int num1, int num2)
{
        return num1 + num2;
}

int main()
{
        fun(3, 4);
    return 0;
}
cdcel.png
继续对stdcall调用进行实验,代码如下
#include "stdafx.h"
int __stdcall fun(int num1, int num2)
{
        return num1 + num2;
}

int main()
{
        fun(3, 5);
    return 0;
}
进入OD进行观察 如下
stdcall.png
可以观察到此时main函数不在使用ADD ESP的方式对函数调用后的堆栈进行平衡
在进入fun函数前的堆栈指针如下

std进入fun

std进入fun

fun函数结束的时候如下

stdfun结束

stdfun结束

可以观察到 进入前和进入后的ESP相差4 原因是因为在进入CALL的时候经过了一次JMP

JMP

JMP

同理可以推知 在进行RETN的时候也是默认进行了一次JMP
所以main函数结束的时候堆栈仍然平衡 如图

std main结束

std main结束

小结:stdcall调用函数的时候 参数入栈顺序从右往左依次入栈 函数堆栈由函数自身通过RET平衡 mian函数调用者不对其进行平衡

        对fastcall函数的实验
#include "stdafx.h"
int __fastcall fun(int num1, int num2)
{
        return num1 + num2;
}

int main()
{
        fun(100, 12);
    return 0;
}
[attachimg]
只有2个参数的时候
fast2参1.png
可以观察到在main函数中仍然不对函数进行堆栈平衡,由函数自行平衡。且在函数参数存储的时候使用了EDX 和ECX寄存器进行存储参数
fast2参2.png
        在fun函数运算的时候 将ECX的值入栈,然后和EDX存入的值一起置入局部变量区存储使用
#include "stdafx.h"

int __fastcall fun(int num1, int num2, int num3, int num4)
{
        return num1 + num2 + num3 + num4;
}

int main()
{
        fun(100, 12, 10, 11);
        return 0;
}

        在进行超过2个参数传入的时候 如下图



        顺序仍然是从右往左传参 但默认保留第一个和第二个参数传入ECX EDX中

        小结:fastcall调用约定特征 参数从右往左入栈 默认保留前2个存入EDX和ECX中  函数堆栈由自身平衡

对thiscall调用的一些疑问
#include "stdafx.h"
class ThisCall 
{
public:
        int Thiscall(int num1, int num3, int num4)
        {
                return num1 + num4 + num3;
        }
};

int main()
{
        ThisCall A;
        A.Thiscall(3, 4, 5);
   
Thiscall的一些理解.png thiscall fun函数.png
在汇编中 类的封装性是如何被实现或者破坏的?
汇编中ECX对类中this指针是如何使用的? 与C++中的相同之处有哪些?

fast多参存值堆栈展示.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-24 13:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表