Control Flow(控制流)
条件码
汇编程序猿眼中有个逻辑上处理器,处理器内部,有通用处理器的状态,有通用处理器的值,还有当前执行指令地址,还有条件码。还有一片连续内存的空间,里面有程序段代码段等。
条件码
CF ZF SF OF (80x86上的条件码不止这四位,要比这个多很多。这里只说这四位)
可以理解未4个一位的寄存器,每个里面存储这些标志位(条件码)
进位位 符号位 零(结果是不是零) 溢出位
当我们完成一条指令时,这指令往往是算术运算或逻辑运算。这些运算的结果,先放在信息隐含的有指令,甚至在这些条件码当中。
无符号溢出(两个整数相加变为负数,两个负数相加变为正数)
add 会判断两个进位标志 CF 和 OF
硬件层面依赖CF和OF条件码来区分带符号和不带符号
比较指令和测试指令
比较(compare)指令
测试(Test)指令
主要这几条指令,知道就行了。
读取条件码指令
x86-64下的读取条件码指令
两个函数返回值不同,但是生成通用的汇编代码,body部分。
查找手册
减少流水线前后相关的关系
跳转指令
很多条件判断,即条件码相关的,都伴随着条件执行。
条件移动指令
和C语言里条件表达式很像。
条件移动指令的体系结构背景
i686及其之后,新的处理器,用条件移动指令取代,条件跳转指令。
微体系结构背景
从两个层面讲汇编,从汇编讲计算机系统结构的知识。
C语言角度,从上往下看。
从低往上看,从流水线往上看。
新的流水线设计,会对编译,新流水线有什么影响?
分成五个段。
每一道手续只做一部分。提高频率。整体同时运行指令数增长。
现代的通用处理器 支持深度流水线以及多发射结构,如 Pentium 4: >=20 stages, up to 126 instructions on-fly
一个cycle进入多条指令,吞吐率提高了。但是对于跳转指令,或者条件跳转指令。
使用条件转移指令,替换条件跳转指令。
全局变量,计算量大。(改全局变量,有副作用)
整数运算开销小,浮点型开销大。
循环的汇编语言表示
同样的代码,不同年代的GCC编译器,编译出来的汇编不一样,从C的层面是看不出来的。
为什么不同年代编译的不一样呢?
尽量从处理器结构方面解释。
这种否定之否定是为什么呢?
jump-to-middle
这个Goto模式看起来有一点点奇怪,
goto middle
一进来,先跳下面,在跳上面
历史上做过,现在不这么做
当年有它的道理
有两个跳转指令,
jump-to-middle 把两个条件跳转指令变成一个无条件跳转指令+一个条件跳转指令。
无条件跳转指令运行开销非常低,好像在性能上有所提高。
避免双重测试,不尽然,真正执行跳转是循环多少次,不是汇编有多少行。
循环表示的体系结构背景
条件跳转指令往往会引起一定的性能损失。想办法消除
一个是刚刚说 move, 使用范围有限,很多时候消除不了
消除不了,怎么办??猜,
Branch Prediction 技术被引入来进行优化
switch的汇编语言表示
跳转表
因为不同case差距较大,所以不适合用跳转表。跳转表所占空间太大。
if else 是以二叉树结构组织形式。