条件转移指令
8086/8088提供了大量的条件转移指令,它们根据某标志位或某些标志位的逻辑运算来判别条件是否成立。如果条件建立,则转移,否则继续顺序执行。
所有条件转移都只是段内转移。
条件转移也采用相对转移方式。即通过在IP上加一个地址差的方法实现转移。但条件转移指令中只用一个字节表示地址差,所以,如果以条件转移指令本身作为基准,那么条件转移的范围在-126至 129之间。如果条件转移的目的超出此范围,那么必须借助于无条件转移指令。
条件转移指令不影响标志。
条件转移指令的格式列于表2.4中,有些条件转移指令有两个助记符,还有些条件转移指令有三个助记符。使用多个助记符的目的是便于记忆和使用。
表2 .4 条件转移指令
指令格式 |
转移条件 |
转移说明 |
其它说明 |
JZ 标号 JE 标号 |
ZF=1 ZF=1 |
等于0转移 或者,相等转移 |
单个标志 |
JNZ 标号 JNE 标号 |
ZF=0 ZF=0 |
不等于0转移 或者,不相等转移 |
单个标志 |
JS 标号 |
SF=1 |
为负转移 |
单个标志 |
JNS 标号 |
SF=0 |
为正转移 |
单个标志 |
JO 标号 |
OF=1 |
溢出转移 |
单个标志 |
JNO 标号 |
OF=0 |
不溢出转移 |
单个标志 |
JP 标号 JPE 标号 |
PF=1 PF=1 |
偶转移 |
单个标志 |
JNP 标号 JPO 标号 |
PF=0 PF=0 |
奇转移 |
单个标志 |
JB 符号 JNAE 符号 JC 符号 |
CF=1 CF =1 CF=1 |
低于转移或者,不高于等于转移 或者,进位标志被置转移 |
单个标志 无符号数 |
JNB 符号 JAE 符号 JNC 符号 |
CF=0 CF=0 CF=0 |
不低于转移或者,高于等于转移 或者,进位标志被清转移 |
单个标志 无符号数 |
JBE 符号 JNA 符号 |
(CF或ZF)=1 (CF或ZF)=1 |
低于等于转移或者,不高于转移 |
两个标志无符号数 |
JNBE 符号 JA 符号 |
(CF或ZF)=0 (CF或ZF)=0 |
不低于等于转移或者,高于转移 |
两个标志无符号数 |
指令格式 |
转移条件 |
转移说明 |
其它说明 |
JL 符号 JNGE 符号 |
(SF异或OF)=1 (SF异或OF)=1 |
小于转移或者,不大于等于转移 |
两个标志有符号数 |
JNL 标号 JGE 标号 |
(SF异或OF)=0 (SF异或OF)=0 |
不小于转移 或者,大于等于转移 |
两个标志有符号数 |
JLE 标号 JNG 标号 |
((SF异或OF)或ZF)=1 ((SF异或OF)或ZF)=1 |
小于等于转移 不大于转移 |
三个标志有符号数 |
JNLE 符号 JG 符号 |
((SF异或OF)或ZF=1 ((SF异或OF)或ZF)=1 |
不小于等于转移 大于转移 |
三个标志有符号数 |
条件转移指令使用得最多的转移指令。通畅,在条件转移指令前,总由于条件判别的有关指令。
下面的程序片段测试AX的低四位是否全是0,如果均是0,那么使CX=0,否则使CX= -1。
MOV CX,- 1 ;先使CX= - 1
TEST AX,0FH ;测试AX的低4位
JNZ NZERO ;不全为0则转移
MOV CX,0 ;全为0时使CX=0
NZERO: ……
从表2.4中可见,无符号数之间大小比较后的条件转移指令和有符号数之间的大小比较后的条件转移指令有很大不同。有符号数间的次序关系称为大于(G) ﹑等于(E)和小于(L);无符号数间的次序关系称为高于(A) ﹑等于(E)和低于(B)。所以,在使用时要注意区分它们,不能混淆。
下面的程序片段实现两个无符号数(设在AX和BX中)的比较,把较大的数存放到AX中,把较小的数存放在BX中:
CMP AX,BX
JAE OK ;无符号数比较大小转移
XCHG AX,BX
OK: ……
如果要比较的两个数是有符号数,则可用下面的程序片段:
CMP AX,BX
JGE OK ;有符号数比较大小转移
XCHG AX,BX
OK: ……
从表2.4中可见,无符号数之间大小比较后的条件转移指令和有符号数之间的大小比较后的条件转移指令测试的标志完全不同。
不论无符号数还是有符号数,两数是否相等由ZF标志反映。
当两个无符号数相减时,CF位的情况说明料是否有错位。因此进位标志CF反映两个无符号数比较后的大小关系,所以用于无符号数比较后的条件转移指令(如JB和JAE等)检测标志CF,以判别条件是否成立。但进位标志CF不能反映两个有符号数比较后的大小关系。两个有符号数比较后的大小关系由符号标志SF和溢出标志OF一起反应。所以用于有符号数比较后的条件转移指令(如JL和JGE等)检测标志SF和OF,以判别条件是否成立。
设要比较的两个不相等的有符号数a和b分别存放在寄存器AX和BX中,执行指令“CMP AX, BX”后,标志SF及OF的设置情况和两数的大小情况如下:
当没有溢出(OF=0)时, 若SF=0,则a>b
若SF=0则a<b
当产生溢出 (OF=1) 时, 若SF=0,则a<b
若SF=1,则a>b
据此可推断出表2.3中用于有符号数比较后的条件转移指令所测试的条件。
3. 循环指令
利用条件转移指令和无条件转移指令可以实现循环,但为了更加方便于循环的实现,8066/8088还提供了四件用于实现循环的循环指令。
循环指令类似于条件转移指令,不仅属于段内转移,而且也采用相对转移的方式,即通过在IP上加一个地址差的方式实现转移。循环指令中也只用一个字节表示地址差,所以,如果以循环指令本身作为基准,那么循环转移的范围在-126 129之间。
循环指令不影响各标志。
1)计数循环指令LOOP
计数循环指令的格式如下:
LOOP 标号
这条指令使寄存器CX的值减1,如果结果不等于0,则转移到标号,否则顺序执行LOOP指令后的指令。该指令类似于如下的两条指令:
DEC CX
JNZ 标号
通常在利用LOOP指令构成循环时,先要设置好计数器CX的初值,即循环次数。由于首先进行CX寄存器减1操作,再判结果是否为0,所以最多可循环65536次。
如下程序片段实现把从偏移1000H开始的512个字节的数据复制到从偏移3000H开始的缓冲区中(假设在当前数据段中进行转移):
MOV SI,1000H ;置源指针
MOV DI,3000H ;置目标指针
MOV CX,512 ;置计数初值
NEXT: MOV AL,[SI]
INC SI
MOV [DI],AL
INC DI
LOOP NEXT ;控制循环
2) 等于/全零循环指令LOOPE/LOOPZ
等于/全零循环指令有两个助记符,格式如下:
LOOPE 标号
或者
LOOPZ 标号
这条指令使寄存器CX的值减1,如果结果不等于0,并且零标志ZF等于1,那么则转移到标号,否则顺序执行。注意指令本身实施的寄存器CX减1操作不影响标志。
如下的程序片段在字符串中查找第一个非‘A’字符,如果找不到,那么使BX=0FFFFH。
……
MOV AL, ˊAˊ
DEC DI
NEXT:INC DI
CMO AL,[DI]
LOOPE NEXT
MOV BX,DI
JNE OK
MOV BX,—1
OK: ……
3) 不等于/非零循环指令LOOP/LOOPNZ
不等于/非零循环指令有两个助记符,格式如下:
LOOPNE 标号
LOOPNZ 标号
这条指令使寄存器CX的值减1,如果结果不等于0,并且零标志ZF等于0,那么则转移到标号,否则顺序执行。注意指令本身实施的寄存器CX减1操作不影响标志。
4) 跳转指令JCXZ
跳转指令也可以认为是条件转移指令。跳转指令的格式如下:
JCXZ 标号
该指令实现当寄存器CX的值等于0时转移到标号,否则顺序执行。
通常该指令用在循环开始前,以便在循环次数为0时,跳过循环体。
例如:
……
JCXZ OK ;如果循环计数为0,就跳过循环
NEXT : …… ;循环体
……
LOOP NEXT ;根据计数控制循环
OK : ……