本节主要学习如何控制机器级别指令的执行顺序
基本条件语句(条件码,条件分支)、循环(循环)、switch语句
ProcessorState#

1.条件码#
- CF(无符号):进位(溢出)
- ZF:刚才的计算结果为零
- SF(有符号):结果的最高有效位为1(负值)
- OF(有符号):进位(溢出)

这些标志一般情况下会被忽视,当进行条件操作时会被关注
显式设置1#

显式设置2#
testq b,a相当于计算 a&b

如果testq a,a。那么只有当a为零时,ZF才会被设置
读取条件码#
根据条件码的某种组合,将一个字节设置成0或1
- 最简单的是,设置ZF条件码的值
sete %al(ZF是什么就设置成什么)

直接设置寄存器的最低字节#
该操作不会影响其他7个字节

条件相关例子#

- %eax是%rax的低四位
- mov指令,从单字节到四字节的零扩展指令
- 前两步骤保证了低四字节的零扩展;x86-64保证:任何计算结果是32位(四字节)的计算,会把寄存器其余32位设置为0(高四字节)。但是,如果是单字节,或双字节,只会影响这个单字节或双字节的结果。
跳转指令#
包括无条件跳转/有条件跳转

传统分支例子#
jle .L4 表示如果条件码结果表示是 y <=x,则跳转到 .L4

使用goto表达上述的汇编代码的意思:
goto Else之后,会继续执行Done标签之后的语句,也就是Done标签后的语句是无论判断是否失败都会执行的

编译器翻译#

Done表示这个C Code后面的所有逻辑代码
条件移动#
result是最后的结果。先把两个结果都算出来,result默认先赋值给其中一个。如果判断错误,则修改result(有条件的移动),否则直接返回。

- 用“提前计算 + 条件选择”取代“分支预测”,避免流水线清空。
- 只是 根据条件选择寄存器值,没有跳转,完全避免分支预测错误
- 假设你知道的指令序列正在代码海洋中巡航,这些指令可以很顺畅的执行,因为他们使用了所谓的流水线技术。这意味着他们在完成下一个指令之前就开始执行下一个指令的一部分,实际上流水线能达到20条以上指令的深度,能达到的深度取决于提前获取的指令的条数,当完成一些指令时仍然有另一些指令留在流水线上,这就是我的海洋线或我的游轮类比。但突然他们到达一个分支会发生什么?他们会试着猜测分支结果,这被称为分支预测技术,猜测会运行哪个分支。在你熟悉的情况下,条件分支将被采用或将被落空,并且他们非常擅长预测,98%的时候他们都能猜对,所以他们甚至可以在路上预测suta曲线,并且开始朝着这个方向前进,只要猜测正确,就会非常有效率。但是,如果分支猜错了,你必须阻止它并转向另一个方向重新开始,在较差的情况下,可能需要40个指令40个时钟周期
- 通过先执行两个分支来提高效率要容易得多,在最后一分钟,你要做的就是是否将值移入寄存器,这并不需要暂停整个处理器的执行然后重新选择分支执行
ConditionMoveExample#
CMOV是单条指令,不会打断 CPU 的指令流水线。
