跳转至

过程

过程是软件中一种很重要的抽象。它提供了一种封装代码的方式,用一组指定的战术和一个可选的返回值实现了某种功能。然后,可以在程序中不同的地方调用这个函数。设计良好的软件用过程作为抽象机制,隐藏某个行为的具体实现,同时又提供清晰简洁的接口定义,说明要计算的是哪些值,过程会对程序状态产生什么样的影响。不同的编程语言中,过程的形式多样:函数、方法、子例程、处理函数等等,但是他们有一些共同的特性。 - 要提供对过程的机器级支持,必须要处理许多不同的属性。为了讨论方便,假设过程P调用过程Q,Q执行后返回到P。这些动作包括下面一个或多个机制: - 传递控制:在进入过程Q的时候,程序计数器必须被设置为Q的代码的起始地址,然后在返回时,要把程序计数器设置为P中对用Q后面那条指令的地址 - 传递数据:P必须能够向Q提供一个或多个参数,Q必须能够向P返回一个值 - 分配和释放内存:在开始时,Q可能需要为局部变量分配空间,而在返回前,又必须释放这些空间(栈帧)

运行时栈

- C语言过程调用机制的一个关键特性:使用了数据结构提供的后进先出的内存管理原则 - 在过程P调用过程Q的例子中,可以看到当Q在执行时,P以及所有在向上追溯到P的调用链的过程,都是暂时被挂起的 - 当Q运行时,它只需要为局部变量分配新的存储空间,或者设置到另一个过程的调用 - 当Q返回时,任何它所分配的局部存储空间都可以被释放 - 栈和程序寄存器存放着传递控制和数据、分配内存所需要的信息 - 当P调用Q时,控制和数据信息添加到栈尾 - 当P返回时,这些信息会释放掉

x86-64的栈向低地址方向增长,而栈指针%rsp指向栈顶元素。可以使用pushq和popq指令将数据存入或取出栈。 将栈指针减小一个适当的量可以为没有指定初始值的数据在栈上分配空间类似的,可以通过增加栈指针来释放空间。 - 栈帧:当过程需要的存储空间超出寄存器能够存放的大小时,就会在栈上分配空间 - 当前正在执行的过程的帧总是在栈顶 - 当过程P调用过程Q时,会把返回地址压入栈中,指明当Q返回时,要从P程序的哪一个位置继续执行 - 为了提高时间和空间效率,过程只会分配自己所需要需要的栈帧部分 - 如果过程需要的参数小于六个,就可以只通过寄存器来传递参数,因此,图中的参数构造区有时可以省略 实际上,许多函数甚至不需要栈帧。 当所有的局部变量都可以保存在寄存器中时,而且该函数不会调用任何其他函数时,就可以这样处理。

后续内容略过,详细见CSAPP:3.7

控制转移call

指令 描述
call label 过程调用
call *Operation 过程调用
ret 从过程调用中返回

数据传送