条件处理
本章要点
1.简介
2.布尔和比较指令
3.条件跳转
4.条件循环指令
5.条件结构
6.应用:有限状态机
7.决策伪指令
6.1 简介
本章,读者将看到高级条件分支如何翻译成底层的实现代码。
处理硬件设备的程序必须能够操控数字中的单个数据位,应该能够测试清楚和设置数据位。数据加密和压缩也依赖于位操作。
本章试图解答如下基本问题:
1.如何使用1章中介绍的布尔运算符(AND,OR和NOT)?
2.在汇编语言中如何写一条IF语句?
3.编译器是如何将嵌套的IF语句翻译成机器语言的?
4.如何设置和清楚二进制数字中的单个位?
5.在布尔表达式中有符号和无符号树有什么区别?
6.什么是有限状态机?
7.GOTO语句真是有害的吗?
本章遵循自底向上的姿势,首先讲述程序逻辑背后的二进制基础知识,接下来讲述如何使用CPU指令和处理器状态标识来比较操作数,最后将所有这些进行综合讲述如何使用汇编语言实现高级语言的逻辑结构。
6.2 布尔和比较指令
下面开始在二进制层次学习如何进行条件处理,使用布尔代数中的4种基本操作-AND,OR,XOR和NOT,这类操作在计算机硬件和软件设计中都有广泛的应用。
IA-32指令集中包括AND,OR,XOR,NOT,TEST和BTop指令,直接实现了字节、字和双字的布尔运算。
6.2.1 CPU的状态标志
布尔指令影响零标志、进位标志、符号标志、溢出标志和奇偶标志。
1.零标志操作的结果等于0时置位。
2.进位标志在指令执行产生的结果(视为无符号整数)对目的操作数而言太大(或太小)而无法容纳时的置位。
3.符号标志是目的操作数高位的一份副本,如果目的操作数为负数则设置该标志,如果是正数则清零。
4.溢出标志在指令产生的有符号结果无效时置位。
5.在指令的操作数的低字节中,为1的数据位的数据量偶数时设置奇偶标志。
6.2.2 AND指令
AND指令在每对操作数的对应数据位之间执行布尔(位)“与”操作并把结果放在目的操作数中:
AND 目的操作数,源操作数,下面的操作数格式都是允许的:
AND reg ,reg
AND reg ,mem
AND reg ,imm
AND mem,reg
ANDmem,imm
6.2.3 OR指令
格式和AND一样......
影响的标志位:OR指令总是清除溢出标志和进位标志。它根据目的操作数的值修改符号标志、零标志、奇偶标志。可以把一个数字同自身进行“或”运算以获取关于其值的某些信息,如:
or al,al
零标志和符号标志的值与AL中的内容关系如下:
6.2.4 XOR指令
XOR指令在每对操作数的对应数据之间执行布尔“异或”操作,格式个AND一样。
影响的标志:XOR指令总是清楚溢出标志和进位标志,它依据目的操作数的值修改零标志和奇偶标志。
检查奇偶标志:奇偶标志位表明了位做操作或幻速运算结果的最低字节包含为1的数据的个数是奇数还是偶数。当为1的数据位为欧舒适设置奇偶标志,为奇数时清除该标志。检验数字中为1的数据位个数的奇偶性的方法之一是将数字同全0字节进行异或运算,无需改变其值:
6.2.5 NOT指令
NOT指令对于一个操作数所有数据位取反,得到的结果成为该操作数的反码。该指令允许下面的操作数据类型:
NOT reg
NOT mem
影响的标志:NOT指令不影响任何状态标志。
6.2.6 TEST指令
TEST指令在没对操作数的对应数据位之间执行隐含的“与”操作,并相应设置标志位。TEST指令和AND指令之间的唯一区别在于TEST指令饼不修改目的操作数。TEST指令的操作数格式与AND相同,该指令在测试操作数某些为是否被设置时特别有用。
6.2.7 CMP指令
CMP指令在源操作数和目的操作数之间执行隐含的减法操作,两个操作数都不会被修改:
CMP 目的操作数,源操作数
CMP指令与AND指令的操作数格式相同。
影响的标志:CMP指令根据对目的操作数进行假象的减法操作后目的操作数的值修改溢出标志、符号标志、零标志、进位标志、辅助进位标志和奇偶变址的值。在比较两个无符号操作数的时候,零标志和进位标志反应了两个操作数之间的关系:
如果比较的两个操作数是有符号的,则符号标志、零标志、溢出标志与两个操作数之间的关系如下表所示:
CMP指令时创建条件逻辑结构的有效工具。IF语句在汇编语言中等价于在CMP指令后
跟一条条件跳转指令。
例子:下面我们来看三个代码片段,以弄清CMP指令时如何影响标志的。在AX中装入5并且和10进行比较的时候,由于5-10需要借位,因此CF标志置位:
mov ax,5
cmp ax,10
比较1000和1000会设置零标志位,因为从源数中减去目的数得到的结果是0:
比较105和0会清楚零标志和进位标志,因为105大于0:
6.2.8 设置和清除单个CPU状态标志
如何设置和清除零标志、符号标志、进位标志和溢出标志?有很多种方法,但大多数方法都需要修改目的操作数。要设置零标志,可以讲操作数同0进行TEST或AND操作;要想清除零标志,可以将操作数同1进行OR操作:
test al ,0 ;设置零标志
and al ,0 ;设置零标志
or al ,1 ;清楚零标志
TEST指令不会修改操作数,不过AND操作修改操作数。要设置符号标志,将操作数的最高位同1进行OR操作;要清楚该标志,将操作数的高位同0进行AND操作:
or al ,80h ;设置符号标志
and al ,7Fh ;清楚符号标志
使用STC指令可以设置进位标志,使用CLC指令可以清除进位标志:
stc ;设置进位标志
clc ;清楚进位标志
要设置溢出标志,把两个将得到复数和的整数字节相加;要清楚溢出标志,将操作数同0进行OR操作:
mov al ,7Fh ;al = +127
inc al ;al =80h(-128) ,OF = 1
or eax ,0 ;清除溢出标志