函数的调用在底层的过程

    计算机是用来跑程序的,因此理解了程序的运行对学习计算机有很大的好处,在这里我对程序的运行做一个简要的总结。

    如下是计算机的总体构造,cpu、内存、硬盘直接通过总线连接在一起,以此来传输数据和控制性。这里省略掉了cpu的内部寄存器,后面会详细说明。

    

   我们的程序一开始是以存储在硬盘的文件里的,如果我这个时候通过命令行说要运行一段程序的话,硬盘里的程序会被搬运到内存里,同时也把字符串里的数据也搬过去,以一个简单的hello_world.c为例,数据就是"hello,word!"这个要打印的字符串。

   紧接着,就是程序的运行过程了,这个过程是由cpu和内存配合完成的,我们已经知道,目前程序和数据目前已经保存在内存里了,因此cpu要干的事情就是按照内存里的代码指令执行运行。我们要指出的是,这是内存里的代码是机器语言(或者汇编语言,机器语言和汇编语言有着一一对应的关系),而不是C语言这样的高级语言。要理解cpu怎么工作的,需要再画几幅图。

    下图是内存的存储结构,从硬盘拷贝过来的程序和数据被存放在了最下面,他们的地址最小。

    再上面是运行时堆,这个地方我理解为当新建对象时,给对象的存储区域,它是往上生长的。

    其他一切内存区域暂时不管,我们看最顶部,他们叫做函数堆栈,也叫函数帧,这些空间是在程序运行时动态分配的,并且往下生长,一个接着一个叠在一起。要搞清楚程序是如何运行的,就有必要搞清楚函数堆栈是如何生长和释放的。

  
   下面要介绍几个概念,方便我们学习,其中几个cpu里面的寄存器仅限于32位的x86芯片
    当前帧:就是上图中最底下的函数帧3    
    ebp:记录当前帧的首地址,就是指向函数帧3的最上方
    esp:记录函数帧的最下方地址
    pc:程序计数器,用来指出下一条指令在主存储器中的地址
    call:调用程序前,把pc的值压入栈帧保存起来,这个值也叫返回地址
    return:函数被调用完毕后,把返回地址重新赋值给pc,也就是让程序继续执行下去
   当调用一个函数时,首先运行call指令,把下一条要执行的指令压入堆栈,同时esp的值-4
   然后把ebp的值压到堆栈(记住push和pop指令会使esp往下或往上移动),然后把esp的值赋给ebp,这样新的一个函数帧就建立起来了,然后运行函数的若干指令后,esp会不断地往下移动我这里由于没有具体指出被调用的函数是什么样的,所以就一带而过了,此时内存中函数帧结构变成如下形式:
 
    我们可以把ebp和esp之间的这部分函数帧称为帧4.
    紧接着函数需要返回时,只要这么做即可:
    使esp往上走,直到指向旧的ebp(我这里由于没有具体指出被调用的函数是什么样的,所以就一带而过了)
    把esp指向的数据弹出到ebp
    执行return命令,把程序的返回地址交给pc,同时esp又会+4
    于是最后函数帧又变成了这个样子:
    以上就是调用一个函数的过程,大致是没有问题的。
    这个博客我觉得第一次写,语言组织很困难,质量也不尽如人意,以后慢慢改进吧。
  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值