(9)转移指令
转移指令是汇编语言程序员经常使用的一组指令。在高级语言中,时常有“尽量不要使用转移语句”的劝告,但如果在汇编语言的程序中也尽量不用转移语句,那么该程序要么无法编写,要么没有多少功能,所以,在汇编语言中,不但要使用转移指令,而且还要灵活运用,因为指令系统中有大量的转移指令。
转移指令分无条件转移指令和有条件转移指令两大类。
1、无条件转移指令(Transfer Unconditionally)
无条件转移指令包括:JMP、子程序的调用和返回指令、中断的调用和返回指令等。
下面只介绍无条件转移指令JMP(Unconditional Jump)。
JMP指令的一般形式:
JMP 标号/Reg/Mem
JMP指令是从程序当前执行的地方无条件转移到另一个地方执行。这种转移可以是一个短(short)转移(偏移量在[-128, 127]范围内),近(near)转移(偏移量在[-32K, 32K]范围内)或远(far)转移(在不同的代码段之间转移)。
短和近转移是段内转移,JMP指令只把目标指令位置的偏移量赋值指令指针寄存器IP,从而实现转移功能。但远转移是段间转移,JMP指令不仅会改变指令指针寄存器IP的值,而且还会改变代码段寄存器CS的值。
该转移指令的执行不影响任何标志位。
例如:
…
next1: …
JMP next1 ;向前转移,偏移量之差为负数
…
JMP next2 ;向后转移,偏移量之差为正数
…
next2: …
在目前流行的汇编系统中,当段内转移时,有些软件把该转移指令默认为近转移,从而使指令的偏移量用一个字来表示,于是生成3个字节的指令代码,但如果程序员自己清楚转移的幅度在一个短转移的范围之内,那么,可用前置short的办法来告诉汇编程序,让它产生2个字节的指令代码。
比如:如果程序员知道在上例中的标号next2离“JMP next2”指令的偏移量不会超过127,那么,可用下面的转移方式来省掉一个字节的指令代码。
next2: …
JMP short next2 ;生成2个字节的转移指令,从而节省一个字节
…
…
2、条件转移指令(Transfer Conditionally)
条件转移指令是一组极其重要的转移指令,它根据标志寄存器中的一个(或多个)标志位来决定是否需要转移,这就为实现多功能程序提供了必要的手段。微机的指令系统提供了丰富的条件转移指令来满足各种不同的转移需要,在编程序时,要对它们灵活运用。
条件转移指令又分三大类:基于无符号数的条件转移指令、基于有符号数的条件转移指令和基于特殊算术标志位的条件转移指令。
(a) 无符号数的条件转移指令(Jumps Based on Unsigned (Logic) Data)
(b) 有符号数的条件转移指令(Jumps Based on Signed (Arithmetic) Data)
(c) 特殊算术标志位的条件转移指令(Jumps Based on Special Arithmetic Tests)
例5.15 编写一程序段,它把寄存器AX-BX的绝对值存入BX中。
解:
…
SUB BX, AX
JNS next
NEG BX
next: …
例5.16 已知一个字节变量char,试编写一程序段,把其所存的大写字母变成小写字母。
解:
…
char DB 'F' ;变量说明
…
MOV AL, char
CMP AL, 'A'
JB next ;注意:字符是无符号数,不要使用指令JL
CMP AL, 'Z'
JA next
ADD char, 20H ;小写字母比大写字母的ASCII码大20H
next: …
如果不知道(或忘了)大小写字母ASCII码之间的关系,那么,可用数值表达式'a'-'A'、'b'-'B'、…、'z'-'Z'等来代替具体的数值20H。
例5.17 编写一段程序,完成下面计算公式,其中:变量X和Y都是字类型。
解:
…
X DW ? ;变量说明
Y DW ?
…
MOV AX, X
MOV BX, AX ;用BX来临时存放计算结果
CMP AX, 0
JLE setdata
CMP AX, 500
JG case3
ADD BX, 100D ;BX=X+100
JMP setdata
next: SUB BX, 50D ;BX=X-50
setdata: MOV Y, BX ;把计算结果赋给变量Y
…
例5.18 下面循环体的指令代码字节数超过128,试改写该循环。
…
MOV CX, COUNT ;给循环计数器赋初值(>0)
again: 循环体指令序列 ;循环体的首地址偏移量大于128
LOOP again
解:
…
MOV CX, COUNT
again: 循环体指令序列
DEC CX
JNZ again ;把LOOP指令改为条件转移指令