6.4 比较、分支与循环指令
此前的执行都会自然进入下一条指令。控制转移指令(control-transfer instruction)会修改 IP,使处理器能够选择路径或重复工作。条件转移不会从源代码类型中猜测含义;它读取此前运算产生的标志。
CMP 为设置标志而减法,但不保存结果
CMP 左操作数,右操作数 在内部执行与 SUB 左操作数,右操作数 相同的减法,但丢弃数值结果。两个操作数保持不变;CF、PF、AF、ZF、SF 与 OF 描述 左−右。
判断相等时只需要 ZF:
JE或JZ在 ZF=1 时跳转。
JNE或JNZ在 ZF=0 时跳转。
判断大小时必须选择正确的数值解释:
- 无符号跳转使用 CF 与 ZF:
JA、JAE、JB和JBE。
- 有符号跳转组合 SF、OF,有时还包括 ZF:
JG、JGE、JL和JLE。
正在绘制图表…
同一组位可以产生相反的大小关系。F0H 是无符号 240,也是有符号 −16;10H 在两种解释下都是 16。执行 CMP F0H,10H 后,无符号 JA 成立,有符号 JL 也成立。二者并不矛盾,因为程序问的是两个不同问题。
正在加载交互实验...
正在加载概念检查...
正在加载本节练习...
LOOP 隐含使用 CX 作为计数器
LOOP 目标 完成两个动作:
1. 在不修改算术标志的情况下让 CX 减 1。
2. 若新的 CX 不为零,就跳到 目标。
循环体通常位于 LOOP 之前,因此 CX 初值为 1 时,循环体执行一次。CX 初值为 0 很危险:LOOP 会先把它改成 FFFFH,最终经过 65,536 次循环体执行才回到零。
JCXZ 目标 在 CX 已经为零时跳转,并且不修改 CX。若零是合法输入,应在循环体之前使用它:
asm
JCXZ finished
again:
; 循环体
LOOP again
finished:正在绘制图表…
程序员也可以编写 DEC CX 后接 JNZ,但 DEC 会修改状态标志;LOOP 改变 CX 与 IP,却不改变这些标志。如果循环体计算出的标志要留给循环后的代码使用,这个区别就很重要。LOOP 对计数器的使用也是隐含的:指令文字中没有写出 CX。
正在加载交互实验...
正在加载概念检查...
正在加载本节练习...
分支在多个指令地址之间选择,循环则返回已经执行过的地址。第 6.5 节会把重复与隐含寄存器结合起来,用 8086 字符串指令处理成块字节。