转移指令
转移指令分无条件转移指令和有条件转移指令两大类。
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)
条件转移指令又分三大类:基于无符号数的条件转移指令、基于有符号数的条件转移指令和基于特殊算术标志位的条件转移指令。
①无符号数的条件转移指令(Jumps Based on Unsigned (Logic) Data)
|
指令的助忆符 |
检测的转移条件 |
功能描述 |
|
JE/JZ |
ZF=1 |
Jump Equal or Jump Zero |
|
JNE/JNZ |
ZF=0 |
Jump Not Equal or Jump Not Zero |
|
JA/JNBE |
CF=0 and ZF=0 |
Jump Above or Jump Not Below or Equal |
|
JAE/JNB |
CF=0 |
Jump Above or Equal or Jump Not Below |
|
JB/JNAE |
CF=1 |
Jump Below or Jump Not Above or Equal |
|
JBE/JNA |
CF=1 or AF=1 |
Jump Below or Equal or Jump Not Above |
②有符号数的条件转移指令(Jumps Based on Signed (Arithmetic) Data)
|
指令的助忆符 |
检测的转移条件 |
功能描述 |
|
JE/JZ |
ZF=1 |
Jump Equal or Jump Zero |
|
JNE/JNZ |
ZF=0 |
Jump Not Equal or Jump Not Zero |
|
JG/JNLE |
ZF=0 and SF=OF |
Jump Greater or Jump Not Less or Equal |
|
JGE/JNL |
SF=OF |
Jump Greater or Equal or Jump Not Less |
|
JL/JNGE |
SF≠OF |
Jump Less or Jump Not Greater or Equal |
|
JLE/JNG |
ZF=1 or SF≠OF |
Jump Less or Equal or Jump Not Greater |
③特殊算术标志位的条件转移指令(Jumps Based on Special Arithmetic Tests)
|
指令的助忆符 |
检测的转移条件 |
功能描述 |
|
JC |
CF=1 |
Jump Carry |
|
JNC |
CF=0 |
Jump Not Carry |
|
JO |
OF=1 |
Jump Overflow |
|
JNO |
OF=0 |
Jump Not Overflow |
|
JP/JPE |
PF=1 |
Jump Parity or Jump Parity Even |
|
JNP/JPO |
PF=0 |
Jump Not Parity or Jump Parity Odd |
|
JS |
SF=1 |
Jump Sign (negative) |
|
JNS |
SF=0 |
Jump No Sign (positive) |
例5.15 编写一程序段,它把寄存器AX-BX的绝对值存入BX中。
|
解: |
|
|
|
next: |
… |
|
|
|
SUB |
BX, AX |
|
|
JNS |
next |
|
|
NEG |
BX |
|
|
… |
|
例5.16 已知一个字节变量char,试编写一程序段,把其所存的大写字母变成小写字母。
|
解: |
|
|
|
|
next: |
… |
|
|
|
|
char |
DB 'F' |
;变量说明 |
|
|
… |
|
|
|
|
MOV |
AL, char |
|
|
|
CMP |
AL, 'A' |
|
|
|
JB |
next |
;注意:字符是无符号数,不要使用指令JL |
|
|
CMP |
AL, 'Z' |
|
|
|
JA |
next |
|
|
|
ADD |
char, 20H |
;小写字母比大写字母的ASCII码大20H |
|
|
… |
|
|
如果不知道(或忘了)大小写字母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指令改为条件转移指令 |