深入探索c/c++函数(1)---全局函数调用的基本过程

在c/c++等许多程序设计语言中,可以将一段经常需要使用的代码封装起来,在需要使用时可以直接调用,这就是程序中的函数,函数内封装了对数据和逻辑的处理。通过函数调用来执行函数体,下面根据代码进行分析。

#include <iostream>
using namespace std;
int test(int a,int b)
{
      return a+b;
}
int main(int argc, char* argv[])
{
     int a=2;
     int b=3;
     int c=test(2,3);
     cout<<c<<endl;
     system("pause");
     return 0;
}

在code::block(GUN GCC编译器)反汇编如下:
int test(int a,int b)对应的汇编代码:

 

004013EE push ebp                                     ;ebp入栈
004013EF mov ebp,esp                                ;把test函数的调用者的栈帧的栈顶作为一个新的栈帧的开始,即为test函数开辟栈帧。
                                                                     ;基本上每个函数的调用都会有这两句。
004013F1 mov eax,DWORD PTR [ebp+0xc] ;把ebp+0xc地址处的四个字节内存里的数据放到eax寄存器中。
004013F4 add eax,DWORD PTR [ebp+0x8] ;将eax数据和ebp+0x8地址开始四个字节内存里的数据相加,结果放在eax中
004013F7 pop ebp                                       ;把栈顶数据push到ebp寄存器中
004013F8 ret                                                ;这条指令等同于pop eip,jmp eip; 

 main函数对应的汇编代码:

004013FA push ebp
004013FB mov ebp,esp        ;main函数开辟栈帧
004013FD sub esp,0x18      ;抬高栈顶为局部变量分配空间。
00401400 and esp,0xfffffff0 ;对齐用,保证栈是16字节对齐的。
00401403 mov eax,0x0
00401408 add eax,0xf
0040140B add eax,0xf
0040140E shr eax,0x4
00401411 shl eax,0x4
00401414 mov DWORD PTR [ebp-0x10],eax
00401417 mov eax,DWORD PTR [ebp-0x10]
0040141A call 0x40d154 <_alloca>
0040141F call 0x40ccd4 <__main>
00401424 mov DWORD PTR [ebp-0x4],0x14 ;为临时变量a分配空间,并赋值20
0040142B mov DWORD PTR [ebp-0x8],0x1e ;为临时变量b分配空间,并赋值30
00401432 mov eax,DWORD PTR [ebp-0x8] ;eax的值30
00401435 mov DWORD PTR [esp+0x4],eax ;将esp+0x4处往下涵盖四个字节的内存值设为30
00401439 mov eax,DWORD PTR [ebp-0x4]
0040143C mov DWORD PTR [esp],eax       ;将esp处往下涵盖四个字节的内存值设为20,
                                                                   ;和上面对应的语句其实等同于push 0x1e,push 0x14,vc++下基本是这两条语句
0040143F call 0x4013ee <test(int, int)>     ;call 指令中隐含push eip操作
00401444 mov DWORD PTR [ebp-0xc],eax ;test函数的返回值存在eax中,函数返回值如果是整形,
                                                                    ;则返回值在eax中。
00401447 mov eax,DWORD PTR [ebp-0xc]
0040144A mov DWORD PTR [esp+0x4],eax
0040144E mov DWORD PTR [esp],0x4453c0 ;0040144A和 0040144E 这两句指令相当于push 变量c的值
                                                                    ;再 push std::out对象的地址 而vc++编译器 一般会把this指针放在ecx寄存器中
00401455 call 0x42de94 <std::ostream::operator<<(int)>
0040145A mov DWORD PTR [esp+0x4],0x43d3dc
00401462 mov DWORD PTR [esp],eax
00401465 call 0x42d084 <std::ostream::operator<<(std::ostream& (*)(std::ostream&))>
0040146A mov DWORD PTR [esp],0x442000
00401471 call 0x415154 <system>
00401476 mov eax,0x0
0040147B leave
0040147C ret

通过上述分析,我们大致可以了解了函数调用的具体过程:
首先函数参数的按照调用约定依次入栈,也就是说函数参数的对应的内存分配在栈上,而且处于函数的被调用者的栈帧上,函数体内通过ebp或esp寻址,找到参数的地址,并对其操作.

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值