音无结弦之时,天使跃动之心。立于浮华之世,奏响天籁之音。.|

次林梦叶

园龄:3年3个月粉丝:22关注:2

函数过程调用

这一章中先以如下代码来讨论一下函数调用的大致过程:

 

 

  解释:

  首先明确一点:

    在函数执行的过程中,变量,参数,地址等都是放到栈中:

    

    而且需要注意的是:

    栈的栈底是在高地址,每一次入栈,栈指针寄存器ESP都会 -=

 

  Call指令 会将Call指令的下一条指令的地址入栈,这条保存的数据被称为返回地址

  Ret指令 会将目前ESP所指向的地址,其保存的数据放回到EIP(程序计数器)中

   然后EIP在不断地取指,执行

   注意每一次执行Ret时,都保证ESP目前指向的是当时入栈的返回地址(如果不是的话当然会出错了)

     这样保证了当函数调用返回时,可以延续上一个函数中继续执行

 

  返回值 (即函数return 后面跟着的变量)都是保存到EAX中的

  

 

 

 

 

《函数调用的机器级代码表示》

我们以上面这个代码为例,继续深入讲述函数调用过程

上述代码是 函数P 调用 函数 caller ,函数 caller再调用 add


如下在上面一段函数的汇编代码:

 

 这个过程中 栈中如下:

 解释:

  首先 pushl %ebp 将EBP中的数据保存到栈中

    movl %esp,%ebp  将ESP(栈指针)保存到EBP ,

    这个过程相当于让两个指针 ebp 和 esp 指向栈中同一个地址

      

 

   然后subl $24 ,%esp 即 %esp - 24 

   这个操作是说明有数据要入栈了,栈指针要移动

   然后形成了:  

    

 

  这个时候EBP 和 ESP 分别形成了 一个函数的栈底和栈顶的感觉

 

  

  这一段汇编代码都是在栈底和栈顶之间 保存数据

  这个时候 调用 call指令了 其将下一条指令 movl %eax,-4(%ebp) 的地址入栈

    形成返回地址

 

 然后转移到add函数的代码段处执行(这个过程还有保存现场的操作,这里就不说了)

 

   然后add函数代码段的汇编代码开头和结尾其实都与其他函数差不多

  都是:  

    

  

    然后接着是形成 add函数 的栈底和栈顶的过程(即通过移动EBP和ESP)

    

    注意这里ESP栈底指向的内容是上一个函数中EBP的内容

    即上一个函数中栈底的地址

  然后执行。。。执行。。。

  执行到add函数要结束了

    

    将 目前EBP中的值 送到 ESP中,即让当前函数(add)的栈顶返回到栈底

    这个函数中全部保存的数据随着 栈顶的返回而没用了

  然后popl %ebp 即将当前栈顶中的内容 压入到 EBP中

    即EBP现在保存了 上一个函数(caller)中栈底的内容

    即EBP现在又回到 caller函数的栈底了

  然后 因为pop了 ESP中的内容(即栈指针)肯定要+ 

  则回到了

 

  然后执行ret指令,取出 当前栈顶中的内容送到EIP中

    即取出返回地址中的内容(即caller函数中的地址

  这个时候已经彻底回到 caller函数中继续执行了

 

 

 

《函数过程调用案例》

 

   思考一下变量在我们程序的虚拟内存中是如何存放的

  应该如图存放,再想一想如果一个数组超过了其原先定义的大小
  (即我们常常说的:你数组下标越界了)

 这个时候在我们程序的虚拟内存中是如何变换的呢?

 

  如图所示:

  既然我们定义了a这个数组,那么在响应的虚拟地址中就会有其存放位置

  从汇编代码和图中可以知道:

    a[0]被放到了ESP(即栈顶)的位置处

    然后  

       这条汇编指令是将a[i]=1073.....24这个操作的

  在汇编中如何知道a[i]的位置?

  当然是以a[0]为基址+i*4(4是因为一个int4个字节 )

  现在你可以想一下,以我们这个案例为列:

    如果i超过了2,是不是a[i]会被保存到

    这个上面来?

    对的,这样会覆盖原先的已经保存好的值

    导致十分奇怪的情况发生

  

 

 

 

 

 

 

  

本文作者:次林梦叶的小屋

本文链接:https://www.cnblogs.com/cilinmengye/p/17347400.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   次林梦叶  阅读(53)  评论(0编辑  收藏  举报
历史上的今天:
2022-04-23 acwing----线段树
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起