从汇编的角度看C++函数的参数传入

在初学C语言的时候,我们一定碰到过这样的小坑:

void swap(int a,int b)
{
	int tmp=a;
	a=b;
	b=tmp;
}
int main()
{
int a,b=3,5;
swap(a,b);
//No exchanged: a=3,b=5
}

懵懂的我们会有这样的疑问:为什么在swap里面a和b没有真正的交换呢?

后来,我们都学会了如果想要参数得到改变要这样写:

void swap(int &a,int &b)
{
	int tmp=a;
	a=b;
	b=tmp;
}
int main()
{
int a,b=3,5;
swap(a,b);
//Exchanged: a=5,b=3
}

但是为什么,同样是写swap(a,b),却由于函数参数格式不一样而结果不一样呢?

好,现在让我们从汇编的角度来看下,void swap(int &a,int &b)void swap(int a,int b),到底发生了什么。

我们对两个函数进行反汇编(在vs里面调用反汇编窗口即可),得到这样的代码:
【1】(int a,int b)

/*################################ */
	int tmp = a;
mov eax,dword ptr [a]  //把内存单元[a]的数值复制到eax寄存器
mov dword ptr [tmp],eax  //把eax寄存器的数值复制到[tmp]内存单元里面
/*################################ */
	a = b;
mov eax,dword ptr [b]  //把内存单元[b]的数值复制到eax寄存器
mov dword ptr [a],eax  //把eax寄存器的数值复制到[a]内存单元里面
/*################################ */
	b = tmp;
mov eax,dword ptr [tmp]  //把内存单元[tmp]的数值复制到eax寄存器
mov dword ptr [b],eax //把eax寄存器的数值复制到[b]内存单元里面

【2】(int &a,int &b)

/*################################ */
	int tmp = a;
mov eax,dword ptr [a]  //把内存单元[a]的数值复制到eax寄存器,需要注意的是,此时[a]里面装的传入函数的源地址
mov ecx,dword ptr [eax]  //把内存单元[eax]的数值复制到ecx寄存器
mov dword ptr [tmp],ecx  //把ecx寄存器的数值复制到[tmp]内存单元里面
/*################################ */
	a = b;
mov eax,dword ptr [a]  
mov ecx,dword ptr [b]  
mov edx,dword ptr [ecx]  
mov dword ptr [eax],edx  
/*################################ */
	b = tmp;
mov eax,dword ptr [b]  
mov ecx,dword ptr [tmp]  
mov dword ptr [eax],ecx  

通过汇编代码,就可以明白:int &a,传入的实际上是a的源地址,由于函数堆栈必须满足这样一个原则:传入者一定不变的,因为函数是通过汇编堆栈实现的,压进栈的数据是被冻结的,弹出来的时候一定是原样的。

&符号是取值符,当我们传入a,这时真真实实的a变量,通过&a,我们才得以把真正的地址赋值给函数。

那现在我们用汇编自己写一段交换函数的代码:

void swap(int &a, int &b)
{
	__asm {
		mov eax,dword ptr [a]
		mov ecx,dword ptr [eax]
		mov ebx,dword ptr[b]
		mov edx,dword ptr [ebx]
		mov dword ptr [eax],edx
		mov dword ptr [ebx],ecx
	}
}

完整(VS2019编译成功,因为使用的是masm的预编译):

#include <stdio.h>

void swap(int &a, int &b)
{
	__asm {
		mov eax,dword ptr [a]
		mov ecx,dword ptr [eax]
		mov ebx,dword ptr[b]
		mov edx,dword ptr [ebx]
		mov dword ptr [eax],edx
		mov dword ptr [ebx],ecx
	}
}

int main()
{
	int a=3;
	int b = 8;
	swap(a, b);
	printf("%d %d", a, b);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值