函数调用栈

1、函数参数的带入

  • 参数带入顺序

以如下代码为例:

int fun(int a, int b)
{
    int c = a + b;
    return c;
}

int main()
{
    int a = fun(10, 20);
    return 0;
}

调试进入main函数栈帧,EBP = 0x006FFC4C(不固定),ESP = 0x006FFC00(不固定),edp作为栈底寄存器,esp作为栈顶寄存器,栈顶栈底唯一地标识一个函数调用栈。

以下是上段代码调用fun函数部分的汇编代码

int a = fun(10, 20);
0018141E  push        14h  
00181420  push        0Ah  
00181422  call        fun (01811D1h)

从上边汇编代码可以看出首先入栈的是20,然后是10,由此可以看出,参数入栈的顺序是从右向左依次入栈的。

  • 参数小于等于8字节的参数带入

当参数大小为1字节的时候,以如下代码为例:

struct tmp
{
	char a;
};
int fun(struct tmp a, struct tmp b)
{
	return 0;
}

int main()
{
	struct tmp tmp1;
	tmp1.a = 10;
	struct tmp tmp2;
	tmp2.a = 20;
	int a = fun(tmp1, tmp2);

	return 0;
}

其调用fun函数部分的汇编代码如下:

int a = fun(tmp1, tmp2);
002F1A46  movzx       eax,byte ptr [tmp2]  
002F1A4A  push        eax  
002F1A4B  movzx       ecx,byte ptr [tmp1]  
002F1A4F  push        ecx  
002F1A50  call        fun (02F11E0h)  

由以上汇编代码可以看出首先将tmp2的值取出存放在eax寄存器中,然后将eax push入栈,再取出tmp1的值存入ecx寄存器中,然后push入栈。由此可见一个字节的参数采用的是push入栈的方式将参数带入。

当参数大小为4字节的时候,以如下代码为例:

struct tmp
{
	int a;
};
int fun(struct tmp a, struct tmp b)
{
	return 0;
}

int main()
{
	struct tmp tmp1;
	tmp1.a = 10;
	struct tmp tmp2;
	tmp2.a = 20;
	int a = fun(tmp1, tmp2);

	return 0;
}

其调用fun函数部分的汇编代码如下:

int a = fun(tmp1, tmp2);
011F365C  mov         eax,dword ptr [tmp2]  
011F365F  push        eax  
011F3660  mov         ecx,dword ptr [tmp1]  
011F3663  push        ecx  
011F3664  call        fun (011F11E0h)  

其汇编代码和参数为1字节的时候汇编代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值