|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
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链接器设置 如下图
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函数前的堆栈指针如下
std进入fun
fun函数结束的时候如下
stdfun结束
可以观察到 进入前和进入后的ESP相差4 原因是因为在进入CALL的时候经过了一次JMP
JMP
同理可以推知 在进行RETN的时候也是默认进行了一次JMP
所以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个参数的时候
可以观察到在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++中的相同之处有哪些?
|
-
|