|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
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++中的相同之处有哪些?
|
-
|