c++的4种调用方式

__cdecl

c默认的函数调用方法。

  • 参数从右到左入栈
  • 调用者清栈(手动清栈),add esp, xxx

所以,参数由调用者维护,可变参数函数只能用此约定。

输出函数名前会加上一个下划线前缀。

__stdcall

c++标准调用方式。

  • 参数从右到左入栈,成员方法this最后入栈;
  • 被调用者清栈(自动清栈),retn x,x是参数占用的字节数

函数编译时必须确定并控制参数个数,否则返回出错。

函数名格式:_funcname@参数字节数

__fastcall

ecx和edx传送两个dword参数,其余参数仍然用栈。

被调用者清栈,retn x

函数名格式:@funcname@参数字节数

__thiscall

仅用于c++成员函数。__thiscall不是关键字,所以不能被程序员指定。

传参和返回与stdcall一样。只是this用ecx传递。

Borland c++编译器使用eax存储this。

代码验证

#include <iostream>

class C 
{
public:
	void func()
	{
		std::cout << this << std::endl;
	}
};

void func_c(char arg)
{
	int a;
}

void __stdcall func_std(char arg0, int arg1)
{
	int a;
}

void __fastcall func_fast(char arg0, int arg1, int arg2, int arg3)
{
	int a;
}

int main()
{
	C c;
	c.func();

	func_c(0);
	func_std(1, 2);
	func_fast(3, 4, 5, 6);

	return 0;
}
	C c;
	c.func();
009742D8 8D 4D F7             lea         ecx,[c]  
009742DB E8 3E CD FF FF       call        C::func (097101Eh)  

	func_c(1);
009742E0 6A 01                push        0 
009742E2 E8 50 CD FF FF       call        func_c (0971037h)  
009742E7 83 C4 04             add         esp,4  
	func_std(1, 2);
009742EA 6A 02                push        2  
009742EC 6A 01                push        1  
009742EE E8 87 D0 FF FF       call        func_std (097137Ah)  
	func_fast(3, 4, 5, 6);
009742F3 6A 06                push        6  
009742F5 6A 05                push        5  
009742F7 BA 04 00 00 00       mov         edx,4  
009742FC B1 03                mov         cl,3  
009742FE E8 81 D0 FF FF       call        func_fast (0971384h)  

func_std汇编代码:

void __stdcall func_std(char arg0, int arg1)
{
009718D0 55                   push        ebp  
009718D1 8B EC                mov         ebp,esp  
009718D3 81 EC CC 00 00 00    sub         esp,0CCh  
009718D9 53                   push        ebx  
009718DA 56                   push        esi  
009718DB 57                   push        edi  
009718DC 8D BD 34 FF FF FF    lea         edi,[ebp-0CCh]  
009718E2 B9 33 00 00 00       mov         ecx,33h  
009718E7 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
009718EC F3 AB                rep stos    dword ptr es:[edi]  
	int a;
}
009718EE 5F                   pop         edi  
	int a;
}
009718EF 5E                   pop         esi  
009718F0 5B                   pop         ebx  
009718F1 8B E5                mov         esp,ebp  
009718F3 5D                   pop         ebp  
009718F4 C2 08 00             ret         8  

func_fast汇编代码

void __fastcall func_fast(char arg0, int arg1, int arg2, int arg3)
{
009718A0 55                   push        ebp  
009718A1 8B EC                mov         ebp,esp  
009718A3 81 EC E4 00 00 00    sub         esp,0E4h  
009718A9 53                   push        ebx  
009718AA 56                   push        esi  
009718AB 57                   push        edi  
009718AC 51                   push        ecx  
009718AD 8D BD 1C FF FF FF    lea         edi,[ebp-0E4h]  
009718B3 B9 39 00 00 00       mov         ecx,39h  
009718B8 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
009718BD F3 AB                rep stos    dword ptr es:[edi]  
009718BF 59                   pop         ecx  
009718C0 89 55 EC             mov         dword ptr [arg1],edx  
009718C3 88 4D F8             mov         byte ptr [arg0],cl  
	int a;
}
009718C6 5F                   pop         edi  
009718C7 5E                   pop         esi  
009718C8 5B                   pop         ebx  
009718C9 8B E5                mov         esp,ebp  
009718CB 5D                   pop         ebp  
009718CC C2 08 00             ret         8  

如果没有arg2和arg3的话,最后依据就是ret,而不是ret 8.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值