代号3 发表于 2018-8-24 15:50:42

对四种调用约定的一些理解和不解

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


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

int main()
{
        fun(3, 4);
    return 0;
}
        在main函数出设置断点 修改VS链接器设置 如下图

        F10单步调试 ALT+8调出反汇编窗口记录mian函数基址如下图

然后进入OD中 Ctrl+G输入main函数基址 在入口处右键设置新的EIP F8单步开始测试函数调用堆栈 在CALL出F7步入函数观察堆栈变化

可以观察到默认调用中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;
}

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

int main()
{
        fun(3, 5);
    return 0;
}
进入OD进行观察 如下

可以观察到此时main函数不在使用ADD ESP的方式对函数调用后的堆栈进行平衡
在进入fun函数前的堆栈指针如下

fun函数结束的时候如下

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

同理可以推知 在进行RETN的时候也是默认进行了一次JMP
所以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;
}


只有2个参数的时候

可以观察到在main函数中仍然不对函数进行堆栈平衡,由函数自行平衡。且在函数参数存储的时候使用了EDX 和ECX寄存器进行存储参数

        在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);
   

在汇编中 类的封装性是如何被实现或者破坏的?
汇编中ECX对类中this指针是如何使用的? 与C++中的相同之处有哪些?

页: [1]
查看完整版本: 对四种调用约定的一些理解和不解