程序控制指令
上一章节讲到的是数据的移动、计算的底层代码表示,其中,每条汇编指令都是顺序执行的。考虑C语言中三种程序执行方式。
顺序、条件、循环。
本章简练介绍条件分支(if、switch)和循环(do-while,while,for)的机器级表示。
条件分支
条件分支指代单条件分支。程序通过测定某些条件的成立与否,控制程序的走向。反映到C语言当中,即 if−else 语句。
除了整型寄存器之外,CPU还会跟踪一个条件码寄存器。某一个条件码只用一个bit来表示,代表某种状态。这些状态可以被测试从而决定是否更改程序的走向,从而达到条件分支的效果。
条件码
- CF(carry flag) : 进位标志。最近的操作产生最有效位进位时,设置为true。可以用来检查无符号整数是否溢出。
- ZF(zero flag) : 零标志。最近的操作产生的结果为0时,设置为true。
- SF(sign flag) : 符号标志。最近的操作产生的结果为负数时,设置为true。
- OF(overflow flag):溢出标记。(补码)最近的操作产生的结果导致溢出(正溢出或者负溢出)时,设置为true。显然用来检测有符号整数是否溢出。
注意,这里标注了说是最近的操作,也就是说,只要进行了数据的计算,条件码都会发生改变(leal除外,因为它不仅仅是用地址进行计算)。
所以说,条件码会不断的发生变化。
cmp指令集合
当有了条件码的时候,计算机就可以根据条件码的状态执行比较和测试指令。
指令 | 基于 | 描述 |
---|---|---|
cmp S2,S1 | S1−S2 | 比较 S1,S2 |
cmpb | compare byte | |
cmpw | compare word | |
cmpl | compare double word | |
test S2,S1 | S1 & S2 | 测试 |
testb | test byte | |
testw | test word | |
testl | test double word |
- cmp 命令基于 sub 命令, sub 在上一章数据计算中已经解释过。不同于 sub , cmp 仅仅是将 s2,s1 中的数据拿出来做了计算,但是并没有改变 s2,s1 中的任意一个寄存器的状态,它们的值是始终保持不变的。
- test 命令是测试,基于命令 and ,基于的意思即不会改变寄存器的状态。它的重要用途是检测某寄存器的数值是0、正数、负数,或者其中一个操作数当做掩码,指示那些位置应当被测试。
set指令集
cmp 指令集的作用类似于数据计算指令集,可以更改条件码的状态。那么当我们有了条件码的状态的时候,我们如何去访问或者获得条件码呢?
条件码不可以被直接访问,通常来讲有三种方法获取条件码。
- 根据条件码的组合将某bit设置为0,1。作为条件分支检测的方式,相当于间接访问了条件码。
- 利用条件码,我们可以跳转到程序的某个分支,也相当于间接访问条件码并且改变了控制流。
- 类似于2,我们可以通过条件检测有条件的传输数据流。
对于第一种方法,不同的条件码的组合设定某个bit为0或者1等,这样的操作cpu集成了 set 指令。
指令 | 同义指令 | 效果 | 设置条件 |
---|---|---|---|
sete D | setz | ZF->
|
相等/零 |
setne D | setnz | ~ZF->
|
不等/非零 |
sets D |