函数栈桢概念

stack frame 栈帧 (激活记录)

1.先要保护现场

2.将参数按照调用约定放在被运行栈帧上,这样这个栈帧的栈顶指针就会发生改变

3.如果有必要,调用函数会配置一个栈指针,保存调用方希望保持不变的内容(寄存器值)

4.被调用函数为它可能需要的任何局部变量分配空间,需要栈帧栈顶向上(-操作)开辟地方

5.被调用函数返回值存放在EAX或者存放在可以立即被调用到的地方

6.一旦函数完成其他操作,任何局部变量都释放了

7.调用地方如果重新获得控制权,删除再栈中开辟的空间(+操作)

8.完成“序言(3,4)”“过程(5,6)”“尾声(6,7)”

 

C的调用约定_cdecl(参数从右向左依次入栈),清理方式:调用者清理

对于参数可变化的:printf("XXXXX");

 

VOID demo_cdecl(int w,int x,int y,int z)

asm

push z

push y

push w

push x

call demo(进入了函数,开始执行了。。。。。。)

add esp,16 4*sizeof(int)

汇编测试代码:

	ret = cdeclAdd(a, b);
00F51939  mov         eax,dword ptr [ebp-24h]   ;cdecl
00F5193C  push        eax  					    ;push b
00F5193D  mov         ecx,dword ptr [ebp-18h]   ;a
00F51940  push        ecx  						;push a
00F51941  call        cdeclAdd (0F5135Ch)  
00F51946  add         esp,8  					;调用者清理堆栈
00F51949  mov         dword ptr [ebp-30h],eax  
//cdecl
int __cdecl	cdeclAdd(int a, int b)
{
00F51800  push        ebp  
00F51801  mov         ebp,esp  
00F51803  sub         esp,0C0h  
00F51809  push        ebx  
00F5180A  push        esi  
00F5180B  push        edi  
00F5180C  lea         edi,[ebp-0C0h]  
00F51812  mov         ecx,30h  
00F51817  mov         eax,0CCCCCCCCh  
00F5181C  rep stos    dword ptr es:[edi]  
	return a + b;
00F5181E  mov         eax,dword ptr [a]  
00F51821  add         eax,dword ptr [b]  
}
00F51824  pop         edi  
00F51825  pop         esi  
00F51826  pop         ebx  
00F51827  mov         esp,ebp  
00F51829  pop         ebp  
00F5182A  ret  

标准调用_stdcall

VOID demo_stdcall(int w,int x,int y,int z)

push z

push y

push x

push w

call demo(进入了函数,开始执行了。。。。。。)

ret 16

	ret = stdAdd(a, b);							;stdcall
00F51929  mov         eax,dword ptr [ebp-24h]   ;b
00F5192C  push        eax  						;push b
00F5192D  mov         ecx,dword ptr [ebp-18h]   ;a
00F51930  push        ecx  						;push a
00F51931  call        stdAdd (0F5124Eh)  		
00F51936  mov         dword ptr [ebp-30h],eax  
// stdcall 
int __stdcall stdAdd(int a, int b)
{
00F51880  push        ebp  
00F51881  mov         ebp,esp  
00F51883  sub         esp,0C0h  
00F51889  push        ebx  
00F5188A  push        esi  
00F5188B  push        edi  
00F5188C  lea         edi,[ebp-0C0h]  
00F51892  mov         ecx,30h  
00F51897  mov         eax,0CCCCCCCCh  
00F5189C  rep stos    dword ptr es:[edi]  
	return a + b;
00F5189E  mov         eax,dword ptr [a]  
00F518A1  add         eax,dword ptr [b]  
}
00F518A4  pop         edi  
00F518A5  pop         esi  
00F518A6  pop         ebx  
00F518A7  mov         esp,ebp  
00F518A9  pop         ebp  
00F518AA  ret         8  

快速调用_fastcall

VOID demo_fastcall(int w,int x,int y,int z)

前两个(ECX=W,edx=x)参数将被分配给ECX,EDX

剩下的都被按照_stdcall调用约定

ret 8

	ret = fastAdd(a, b);
00F5194C  mov         edx,dword ptr [ebp-24h]   ;mov edx,b
00F5194F  mov         ecx,dword ptr [ebp-18h]   ;mov ecx,a
00F51952  call        fastAdd (0F511EAh)  
00F51957  mov         dword ptr [ebp-30h],eax  
//fastcall
int __fastcall fastAdd(int a, int b)
{
00F51840  push        ebp  
00F51841  mov         ebp,esp  
00F51843  sub         esp,0D8h  
00F51849  push        ebx  
00F5184A  push        esi  
00F5184B  push        edi  
00F5184C  push        ecx  
00F5184D  lea         edi,[ebp-0D8h]  
00F51853  mov         ecx,36h  
00F51858  mov         eax,0CCCCCCCCh  
00F5185D  rep stos    dword ptr es:[edi]  
00F5185F  pop         ecx  
00F51860  mov         dword ptr [ebp-14h],edx  
00F51863  mov         dword ptr [ebp-8],ecx  
	return a + b;
00F51866  mov         eax,dword ptr [a]  
00F51869  add         eax,dword ptr [b]  
}
00F5186C  pop         edi  
00F5186D  pop         esi  
00F5186E  pop         ebx  
00F5186F  mov         esp,ebp  
00F51871  pop         ebp  
00F51872  ret  

C++调用约定

使用this指针

VC提供了 thiscall调用,将this传递给而ecx

GC++中被当做静态,存放在栈顶

ret =tt.add(a, b);
00F5195A  mov         eax,dword ptr [ebp-24h]  
00F5195D  push        eax  						;push b
00F5195E  mov         ecx,dword ptr [ebp-18h]  
00F51961  push        ecx  						;push a
00F51962  lea         ecx,[ebp-39h]  
00F51965  call        thiscallTest::add (0F511E5h)  
00F5196A  mov         dword ptr [ebp-30h],eax  
	int __thiscall add(int a, int b) {
00F517C0  push        ebp  
00F517C1  mov         ebp,esp  
00F517C3  sub         esp,0CCh  
00F517C9  push        ebx  
00F517CA  push        esi  
00F517CB  push        edi  
00F517CC  push        ecx  
00F517CD  lea         edi,[ebp-0CCh]  
00F517D3  mov         ecx,33h  
00F517D8  mov         eax,0CCCCCCCCh  
00F517DD  rep stos    dword ptr es:[edi]  
00F517DF  pop         ecx  
00F517E0  mov         dword ptr [ebp-8],ecx  
		return a + b;
00F517E3  mov         eax,dword ptr [a]  
00F517E6  add         eax,dword ptr [b]  
	}
00F517E9  pop         edi  
00F517EA  pop         esi  
00F517EB  pop         ebx  
00F517EC  mov         esp,ebp  
00F517EE  pop         ebp  
00F517EF  ret         8  

测试代码:

// InvokeRules.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

// stdcall 
int __stdcall stdAdd(int a, int b)
{
	return a + b;
}
//cdecl
int __cdecl	cdeclAdd(int a, int b)
{
	return a + b;
}
//fastcall
int __fastcall fastAdd(int a, int b)
{
	return a + b;
}
//thiscall
class thiscallTest
{
public:
	thiscallTest() {}
	~thiscallTest() {}
	int __thiscall add(int a, int b) {
		return a + b;
	}
	
};

int main()
{
	int a = 10, b = 20;
	int ret{ 0 };
	thiscallTest tt;
	__asm {
		mov eax,0x11111
	}
	ret = stdAdd(a, b);
	ret = cdeclAdd(a, b);
	ret = fastAdd(a, b);
	ret =tt.add(a, b);
	__asm {
		mov eax,0x11111
	}
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蚂蚁_CrkRes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值