重学计算机组成原理(五)- "旋转跳跃"的指令实现(下)

简介: 重学计算机组成原理(五)- "旋转跳跃"的指令实现(下)

2 从if/else看程序的执行和跳转

我们现在就来看一个包含if…else的简单程序。

  • test.c

1.png

用rand生成了一个随机数r(0/1)

  • 当r是0,我们把之前定义的变量a设成1
  • 不然就设成2

我们把这个程序编译成汇编代码。你可以忽略前后无关的代码,只关注于这里的if…else条件判断语句


对应的汇编代码是这样的

1.png

对于r == 0的条件判断,被编译成了cmp和jne两条指令。

  • cmp指令比较了前后两个操作数的值
    DWORD PTR 代表操作的数据类型是32位的整数
    [rbp-0x4]则是一个寄存器的地址
    第一个操作数就是从寄存器里拿到的变量r的值
    第二个操作数0x0就是我们设定的常量0的16进制表示


cmp指令的比较结果,会存入到条件码寄存器


状态寄存器又名条件码寄存器,它是计算机系统的核心部件——运算器的一部分

状态寄存器用来存放两类信息:

一类是体现当前指令执行结果的各种状态信息(条件码),如有无进位(CF位)、有无溢出(OF位)、结果正负(SF位)、结果是否为零(ZF位)、奇偶标志位(P位)等

另一类是存放控制信息(PSW:程序状态字寄存器),如允许中断(IF位)、跟踪标志(TF位)等

有些机器中将PSW称为标志寄存器FR(Flag Register)。


如果比较结果 True,即 r == 0,就把零标志条件码(对应的条件码是ZF,Zero Flag)设置为1


条件码是CPU根据运算结果由硬件设置的位,体现当前指令执行结果的各种状态信息

例如:算术运算产生的正、负、零或溢出等的结果。条件码可被测试,作为分支运算的依据,此外,有些条件码可被设置,例如对于最高位进位标志C,可用指令对它置位和复位。


Intel的CPU下还有

  • 进位标志(CF,Carry Flag)
    最近的操作使最高位产生了进位。可以用来检查无符号操作数据的溢出。
  • 符号标志(SF,Sign Flag)
    最近的操作得到的结果为负数。
  • 溢出标志(OF,Overflow Flag)
    最近的操作导致一个补码溢出–正溢出或负溢出


用在不同的判断条件下。


cmp指令执行完成之后,PC寄存器会自增,开始执行下一条jne的指令


跟着的jne指令(jump if not equal),它会查看对应的零标志位

如果为0,会跳转到后面跟着的操作数4a的位置

4a,对应汇编代码的行号,也就是else条件里的第一条指令

当跳转发生,PC寄存器不再是自增变成下一条指令的地址,而被直接设置4a这个地址

这个时候,CPU再把4a地址里的指令加载到指令寄存器执行。


跳转到执行地址为4a的指令,实际是一条mov指令

第一个操作数和前面的cmp指令一样,是另一个32位整型的寄存器地址,以及对应的2的16进制值0x2

mov指令把2设置到对应的寄存器里去,相当于一个赋值操作

然后,PC寄存器里的值继续自增,执行下一条mov指令。


这条mov指令的第一个操作数eax,代表累加寄存器


在中央处理器中,累加器 (accumulator) 是一种寄存器,用来储存计算产生的中间结果。如果没有像累加器这样的寄存器,那么在每次计算 (加法,乘法,移位等等) 后就必须要把结果写回到 内存,也许马上就得读回来。然而存取主存的速度是比从算术逻辑单元到有直接路径的累加器存取更慢。


第二个操作数0x0则是16进制的0的表示。这条指令其实没有实际的作用,它的作用是一个占位符

if条件如果满足,在赋值的mov指令执行完成之后,有一个jmp的无条件跳转指令

跳转的地址就是这一行的地址51

我们的main函数没有设定返回值,而mov eax, 0x0 其实就是给main函数生成了一个默认的为0的返回值到累加器里面

if条件里面的内容执行完成之后也会跳转到这里,和else里的内容结束之后的位置是一样的。


image.pngimage.pngimage.png

image.png

上一讲我们讲打孔卡的时候说到,读取打孔卡的机器会顺序地一段一段地读取指令,然后执行。

执行完一条指令,它会自动地顺序读取下一条指令

如果执行的当前指令带有跳转的地址,比如往后跳10个指令,那么机器会自动将卡片带往后移动10个指令的位置,再来执行指令

同样的,机器也能向前移动,去读取之前已经执行过的指令

这也就是我们的while/for循环实现的原理。


如何通过if…else和goto来实现循环?

image.png

我们再看一段简单的利用for循环的程序。我们循环自增变量i三次,三次之后,i>=3,就会跳出循环。整个程序,对应的Intel汇编代码就是这样的:

1.png

可以看到,对应的循环也是用1e这个地址上的cmp比较指令

和紧接着的jle条件跳转指令来实现的


主要的差别在于,这里的jle跳转的地址,在这条指令之前的地址14,而非if…else编译出来的跳转指令之后

往前跳转使得条件满足的时候,PC寄存器会把指令地址设置到之前执行过的指令位置,重新执行之前执行过的指令,直到条件不满足,顺序往下执行jle之后的指令,整个循环才结束。

image.png

如果你看一长条打孔卡的话,就会看到卡片往后移动一段,执行了之后,又反向移动,去重新执行前面的指令。


jle和jmp指令,有点像程序语言里面的goto命令,直接指定了一个特定条件下的跳转位置

虽然我们在用高级语言开发程序的时候反对使用goto,但是实际在机器指令层面,无论是if…else…也好,还是for/while也好,都是用和goto相同的跳转到特定指令位置的方式来实现的。


3 总结

学习了程序里的多条指令,究竟是怎么样一条一条被执行的

除了简单地通过PC寄存器自增的方式顺序执行外

条件码寄存器会记录下当前执行指令的条件判断状态

然后通过跳转指令读取对应的条件码

修改PC寄存器内的下一条指令的地址

最终实现if…else以及for/while这样的程序控制流程。


虽然我们可以用高级语言,可以用不同的语法,比如 if…else 这样的条件分支,或者 while/for 这样的循环方式,来实现不用的程序运行流程

但是回归到计算机可以识别的机器指令级别,其实都只是一个简单的地址跳转而已,也就是一个类似于goto的语句。


想要在硬件层面实现这个goto语句,除了本身需要用来保存下一条指令地址,以及当前正要执行指令的PC寄存器、指令寄存器外

我们只需要再增加一个条件码寄存器,来保留条件判断的状态。这样简简单单的三个寄存器,就可以实现条件判断和循环重复执行代码的功能。

4 推荐阅读

《深入理解计算机系统》的第3章

详细讲解了C语言和Intel CPU的汇编语言以及指令的对应关系,以及Intel CPU的各种寄存器和指令集。

Intel指令集相对于之前的MIPS指令集要复杂一些


所有的指令是变长的

从1个字节到15个字节不等

即使是汇编代码,还有很多针对操作数据的长度不同有不同的后缀

参考

目录
相关文章
计算机组成原理(微课版) -- 第三章 -- 运算方法与运算器
计算机组成原理(微课版) -- 第三章 -- 运算方法与运算器
|
存储 算法 调度
【考研必备】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)(下)
【考研必备】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)
|
6月前
|
算法 C语言
计算机简单算法举例
计算机简单算法举例
27 1
|
6月前
|
块存储 芯片 内存技术
计算机组成原理(4)-----Cache的原理及相关知识点(1)
计算机组成原理(4)-----Cache的原理及相关知识点
288 2
|
6月前
|
缓存 算法 内存技术
计算机组成原理(4)-----Cache的原理及相关知识点(2)
计算机组成原理(4)-----Cache的原理及相关知识点
103 1
|
存储 安全 网络安全
【考研必备二】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)(下)
【考研必备二】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)
|
存储 Unix Linux
【考研必备二】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)(上)
【考研必备二】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)(上)
【考研必备二】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)(上)
|
存储 机器学习/深度学习 Unix
【考研必备】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)(上)
【考研必备】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)
【考研必备】解开“黑匣子”的神秘面纱,透视数字世界底层实现过程(计算机组成原理)(上)
|
存储
计算机组成原理“上分秘籍”——数据的表示和运算
计算机组成原理“上分秘籍”——数据的表示和运算
234 0
计算机组成原理“上分秘籍”——数据的表示和运算
|
存储 芯片
复习单片机:8*8点阵---->点亮数字0(内含:1.设计思路+2.数字0的编程数据+3.原始代码+4.实验现象)(注:获得编程数据工具的下载和使用放在下一篇文章)
复习单片机:8*8点阵---->点亮数字0(内含:1.设计思路+2.数字0的编程数据+3.原始代码+4.实验现象)(注:获得编程数据工具的下载和使用放在下一篇文章)
453 0
复习单片机:8*8点阵---->点亮数字0(内含:1.设计思路+2.数字0的编程数据+3.原始代码+4.实验现象)(注:获得编程数据工具的下载和使用放在下一篇文章)