iqoo neo5|关于CPU的12个硬核干货!( 三 )


下面 , 我们就以条件分支举例来说明程序的执行过程:

程序的开始过程和顺序流程是一样的 , 程序的顺序流程和开始过程相同 。 CPU从0100处就开始执行命令 , 在0100和0101中都是顺序执行 , PC的值顺序+1 , 执行到0102地址的指令时 , 判断0106寄存器的数值大于0 , 跳转到0104地址的指令 , 再将数值输到显示器中 , 随后结束程序 , 0103的指令就被跳过了 。 这和我们程序中的if()判断相同 , 在不满足条件的情况下 , 指令一般会直接跳过 。 因此 , PC的执行过程没有直接+1 , 而是下一条指令的地址 。
09标志寄存器
条件和循环分支会使用到 jump(跳转指令) , 会根据当前的指令来判断是否跳转 , 上面我们提到了标志寄存器 , 无论当前累加寄存器的运算结果是正数、负数还是零 , 标志寄存器都会将其保存 。 CPU在进行运算时 , 标志寄存器的数值会根据当前运算的结果自动设定 , 运算结果的正、负和零三种状态由标志寄存器的三个位表示 。 标志寄存器的第一个字节位、第二个字节位、第三个字节位各自的结果都为1时 , 分别代表着正数、零和负数 。

CPU的执行机制比较有意思 , 假设累加寄存器中存储的XXX和通用寄存器中存储的YYY做比较 , 执行比较的背后 , CPU的运算机制就会做减法运算 。 而无论减法运算的结果是正数、零还是负数 , 都会保存到标志寄存器中 。 结果为正表示XXX比YYY大 , 结果为零表示XXX和YYY相等 , 结果为负表示XXX比YYY小 , 程序比较的指令 , 实际上是在CPU内部做减法运算 。
10函数调用机制
函数的调用和条件分支 , 循环机制有所不同 , 单纯的跳转指令无法实现函数的调用 。 函数的调用需要在函数内部处理后 , 处理流程在返回到函数调用点(函数调用指令的下一个地址) 。 函数的调用处理是通过把程序计数器的值设定成函数的存储地址来实现的 。


11通过地址和索引实现数组
接下来是基址寄存器和变址寄存器 , 通过这两个寄存器 , 可以对主存上的特定区域进行划分 , 以此实现类似数组的操作 。 首先 , 可以用十六进制数将计算机内存上的00000000 - FFFFFFFF的地址划分出来 。 这样 , 凡是该范围的内存地址 , 只要有一个32位的寄存器 , 就可以查看全部地址 。 但是 , 要是想像数组那样 , 分割特定的内存区域以达到连续查看的目的的话 , 使用两个寄存器会更方便一些 , 比如 , 我们用两个寄存器来表示内存的值 。

这种表示方式很像数组的构造 , 数组是指同样长度的数据 , 在内存中进行连续排列的数据构造 。 用数组名表示数组全部的值 , 通过索引来区分数组的各个数据元素 , 例如: a[0
- a[4
, [
内的 0 - 4 就是数组的下标 。
12CPU指令执行过程
那说了这么多 , CPU到底是怎么一条条的执行指令的呢?几乎全部的冯·诺伊曼型计算机的CPU , 工作都可以分为5个阶段:取指令、指令译码、执行指令、访存取数、结果写回 。 取指令阶段就是将内存中的指令读取到CPU中寄存器的过程 , 程序寄存器用于存储下一条指令所在的地址;
●在取指令完成后 , 立马进入指令译码阶段 , 在指令译码阶段 , 指令编码器按照预先的指令格式 , 对取回的指令进行拆分和解释 , 识别区分出不同的指令类别和各种获取操作数的方法;
●执行指令阶段的任务是完成指令所规定的各种操作 , 具体实现指令的功能;
●访问取数阶段的任务是:根据指令地址码 , 得到操作数在主存中的地址 , 并从主存中读取该操作数用于运算;