2021-05-02


过程


过程是软件一种很重要的抽象,它提供了一种封装代码的方式,用一组指定的参数和一个返回值实现某种功能,然后,可以在不同的地方调用这个函数。

假设过程P调用过程Q,Q执行后返回到P。这些动作包含以下一个或多个机制。
1、传递控制。在进入过程Q的时候,程序计算器必须设置为Q的代码的起始地址,然后再返回的时候,就需要把程序计算器设置为P中调用Q后面那条指令的地址。

2、传递数据。P必须能够向Q提供一个或多个参数,Q必须能够向P返回一个值。

3、分配和释放内存,在开始时,Q可能需要为局部变量分配空间,而在返回前,又必须释放这些存储空间。


运行时栈


C语言过程调用机制的一个关键特性(大多数其他语言也是如此)在于使用了栈数据结构提供的后进先出原则。在过程P调用过程Q的例子中,可以看到当Q执行时,P以及所有向上追溯到P的调用链中的过程,都是暂时被挂起,当Q运行时,它只需要为局部变量分配新的存储空间,或者设置到另一个过程的调用。另一方面,当Q返回时,任何它所分配的局部存储空间都可以被释放。

因此,程序可以用栈来管理它的过程所需要的存储空间,栈和程序寄存器存放着传递控制和数据、分配内存所需要的信息。当P调用Q时,控制和数据信息添加到栈尾。当P返回时,这些信息会被释放掉。

x86-64的栈向低地址方向增长,而栈指针%rsp指向栈顶元素。可以用pushq和popq指令将数据存入栈中或是从栈中取出。将栈指针减少一个适当的量可以为没有指定初始值的数据在栈上分配空间。类似地,可以通过栈指针来释放空间。

当x86-64过程需要的存储空间超出寄存器能够存放大小时,就会在栈上分配空间。这个部分过程称为过程的栈帧(stack frame)
在这里插入图片描述
当前正在执行的过程的帧总是在栈顶。当过程P调用过程Q时,会把返回地址压入栈中,指明当Q返回时,要从P程序的哪个位置继续执行。把这个返回地址当作P的栈帧的一部分,因为它存放的是与P相关的状态。Q的代码会扩展当前栈的边界,分配它的栈帧所需要的空间。在这个空间中,它可以保存寄存器的值,分配局部变量空间,为它调用过程设置参数。大多数栈帧都是定长的,在过程的开始就分配好了。但是有些过程需要变长的帧。

为了提高空间和时间效率,x86-64过程只分配自己所需要的栈帧部分。例如,许多过程有6个或者更少的参数,那么所有的参数都可以通过寄存器传递。


转移控制


指令call Q调用过程Q,指令会把地址A压入栈中,并将PC设置为Q的起始地址。压入的地址A被称为返回地址,是紧跟在call指令后面那天一条指令的地址。对应的指令ret会从栈中弹出地址A,并把PC设置为A。

call指令有一个目标,即指明被调用过程起始的指令地址。同跳转一样,调用可以是直接的,也可以是间接的。在汇编代码中,直接调用的目标是一个标号,而间接调用的目标是*后面跟一个操作数指示符


数据传送


x86-64中,大部分过程间的数据传送是通过寄存器实现的。例如,我们已经看到无数的函数示例,参数在寄存器%rdi、%rsi和其他寄存器中传递。当过程P调用过程Q时,P的代码必须首先把参数复制到适当的寄存器中。

通过栈传递参数时,所有的数据大小都向8的倍数对齐。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


栈上的局部存储


有些时候,局部函数必须存放在内存中,常见情况包括:
1、寄存器不足够存放所有的本地数据。
2、对一个局部变量使用地址运算符&,因此必须能够为它产生一个地址。
3、某些局部变量是数组或结构,因此必须能够通过数组或结构引用被访问到。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值