## CSAPP读书日记-第三章-2

在这里插入图片描述
首先,看到上图,你可能会感慨,汇编指令的种类就那么点,就凭借这个,支撑起了我们的复杂的业务代码。

言归正传,让我来说下感触较深的知识点:

一、计算机实现控制是靠“条件码”。“条件码”是由CPU维护的一组单个位的寄存器。有以下几类:

设置“条件码”的指令有2个:
CMP:根据2个操作数的差值来设置条件码
TEST:根据2个操作数的和来设置条件码

设置好了后,肯定要让人来访问,那么访问条件码的操作是什么呢?以跳转指令为例:
在这里插入图片描述
可以清楚地看到,“J”这个单词代表着跳转,而之所以有那么多的跳转指令,是为了根据不同的条件码来做判断,从而选择是否跳转。
也就是说,“设置条件码”的操作和“判断条件码”的操作是解耦的。CMP和TEST指令只管设置“条件码”,至于怎么用“条件码”,是各个不同指令自己的事(例如JMP、SET操作。举个简单的例子:当ZF被设置为1的时候,je或sete操作才会执行)

不要小看这简单的4个条件码,有了它们,就能实现我们程序常用的if分支操作(通过jmp)、以及if分支操作衍生出来的switch(通过使用数组,使跳转更加高效)、和循环(do-while、while、for循环)。
这就是所谓的大道至简吧~

二、第2个要说的是“过程”

过程:是一段功能代码的抽象,隐藏实现细节,而又提供清晰简洁的接口定义。

要提供对过程的机器级支持,需要3种机制:
1.转移控制(函数调用另一个函数)
2.传递数据 (函数间传递参数,包括被调用函数的返回值)
3.分配和释放内存

首先,根据现实的工作来看,函数套函数是非常常见的。所以16个64位的寄存器根本缓存不了那么多的参数和局部变量,这就要靠”栈”来存储了。
然后,利用”栈”这种数据结构的”后进先出”的管理原则,函数间的调用本质上就是减小”栈指针”,分配空间;运行完某个函数后,再增加”栈指针’,释放空间。
栈的结构如下所示:
在这里插入图片描述

今天我们来看控制是如何转移的:
就那上面的图来说,函数P调用了函数Q。函数P会使用一个call指令,然后call指令下面肯定还有别的指令,call指令会将下面那条指令的地址压入栈中,以作为Q函数调用完后的返回地址;接着会再把PC设置为Q函数的起始地址。就这2部,实现了函数的控制转移(P转移到Q,Q运行完再转移到P)
注:PC(program counter) 是程序计数器,当执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,此过程称为“取指令”。与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。此后经过分析指令,执行指令。完成第一条指令的执行,而后根据PC取出第二条指令的地址,如此循环,执行每一条指令。

猜你喜欢

转载自blog.csdn.net/zjx130/article/details/83957252
今日推荐