看懂C++如何实现函数堆栈调用

提问1.main()函数调用一个自定义函数之后(函数的定义再main()外),如何再次回到main()的位置;

提问2.既然知道返回main()函数,那如何知道返回到main()函数的哪一行操作呢?

我们先写一段代码,方便研究:

int sum(int a,int b)
{
	int temp=a+b;
	return temp;
}

int main()
{
	int x = 10;
	int y = 20;
	int result = sum(x,y);
	cout<<result<<endl;
	
	return 0;
}

记得上节课我们有一个重要的总结,所有的代码到计算机层面呢就是指令和数据;同时,我们在分析的时候就需要有些汇编的基础。

首先说明压栈和出栈;

栈是一种特殊的数据结构,符合先进后出的特性,压栈操作呢使得栈增大,而出栈操作使得栈变小;每个栈呢都有ebp、esp寄存器定位,其中esp永远指向栈顶位置,这时候呢压栈就会造成esp地址减小,出栈就造成esp地址增大(栈是个奇葩,地址是反着来的);

画个图解释一下吧:
在这里插入图片描述
打个断点,转到反汇编语言,

整个操作的汇编代码如下:

int sum(int a, int b)
{
00D31890  push        ebp  
00D31891  mov         ebp,esp  
00D31893  sub         esp,0CCh  
00D31899  push        ebx  
00D3189A  push        esi  
00D3189B  push        edi  
00D3189C  lea         edi,[ebp-0CCh]  
00D318A2  mov         ecx,33h  
00D318A7  mov         eax,0CCCCCCCCh  
00D318AC  rep stos    dword ptr es:[edi]  
00D318AE  mov         ecx,offset _7F4A7534_源@cpp (0D3C027h)  
00D318B3  call        @__CheckForDebuggerJustMyCode@4 (0D31226h)  
	int temp = a + b;
00D318B8  mov         eax,dword ptr [a]  
00D318BB  add         eax,dword ptr [b]  
00D318BE  mov         dword ptr [temp],eax  
	return temp;
00D318C1  mov         eax,dword ptr [temp]  
}

int main()
{
00D31900  push        ebp  
00D31901  mov         ebp,esp  
00D31903  sub         esp,0E4h  
00D31909  push        ebx  
00D3190A  push        esi  
00D3190B  push        edi  
00D3190C  lea         edi,[ebp-0E4h]  
00D31912  mov         ecx,39h  
00D31917  mov         eax,0CCCCCCCCh  
00D3191C  rep stos    dword ptr es:[edi]  
00D3191E  mov         ecx,offset _7F4A7534_源@cpp (0D3C027h)  
00D31923  call        @__CheckForDebuggerJustMyCode@4 (0D31226h)  
	int x = 10;
00D31928  mov         dword ptr [x],0Ah  
	int y = 20;
00D3192F  mov         dword ptr [y],14h  
	int result = sum(x, y);
00D31936  mov         eax,dword ptr [y]  
00D31939  push        eax  
00D3193A  mov         ecx,dword ptr [x]  
00D3193D  push        ecx  
00D3193E  call        sum (0D31087h)  
00D31943  add         esp,8  
00D31946  mov         dword ptr [result],eax  
	cout << result << endl;
00D31949  mov         esi,esp  
00D3194B  push        offset std::endl<char,std::char_traits<char> > (0D31253h)  
00D31950  mov         edi,esp  
00D31952  mov         eax,dword ptr [result]  
00D31955  push        eax  
00D31956  mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (0D3B0A8h)]  
00D3195C  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0D3B09Ch)]  
00D31962  cmp         edi,esp  
00D31964  call        __RTC_CheckEsp (0D31230h)  
00D31969  mov         ecx,eax  
00D3196B  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0D3B0A0h)]  
00D31971  cmp         esi,esp  
00D31973  call        __RTC_CheckEsp (0D31230h)  

	return 0;
00D31978  xor         eax,eax  
}

1.将main()函数的mainCTRstartup函数的栈底指针压栈,并且初始化main()的栈帧空间;

2.当运行到sum()函数时,esp和ebp会移动到栈顶新开辟出的地址,用于完
成sum()函数的操作;

3.在sum()函数计算过程中,借助寄存器eax完成,根据汇编语言可以看出将a,b的值放入到了寄存器eax中;

4.之后会回退sum()函数的栈空间,出栈、并且回退到main()函数的栈底;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值