(4)转移指令的应用
1、【例】: 判断AX当前值的正负,若为正数,则置CX为50,否则令CX为200。
程序段三(用ZF测试):
TEST AX,8000H
JNZ L
MOV CX,50
JMP NEXT
L: MOV CX,200
NEXT: … …
程序段二:
ADD AX,0
JS L
MOV CX,50
JMP NEXT
L: MOV CX,200
NEXT: … …
例: 已知X为16位的数,判断X是奇数还是偶数,若为奇数,则令Z=X,若为偶数,令Z=0。
程序段一(用ZF测试):
MOV AX,X
TEST AX,1
JNZ L
MOV Z,0
JMP NEXT
L: MOV Z,AX
NEXT: … …
程序段二(用CF测试):
MOV AX,X
BT AX,0
JC L
MOV Z,0
JMP NEXT
L: MOV Z,AX
NEXT: … …
2、【例】在首地址为TABLE的数据段中,存放了若干个带符号字节数据块,其长度为COUNT(设不超过255),试统计其中正元素、负元素及零的个数,并分别将统计的个数存入PLUS、MINUS和ZERO字节单元中。
分析:为了统计正元素、负元素及零的个数,可先将PLUS、MINUS和ZERO三个单元清零,然后将数据区中的带符号数逐个取入AL寄存器,并执行能影响状态标志位的指令,再利用JS、JZ等条件转移指令测试该数是负数、零还是正数,然后分别在相应的单元中进行统计。主要程序段如下:
XOR AL,AL ;AL清0
MOV PLUS,AL ; PLUS字节单元清0
MOV MINUS,AL ;MINUS字节单元清0
MOV ZERO,AL ;ZERO字节单元清0
LEA SI,TABLE ;取源串首址
MOV CX,COUNT ;取数据块长度
CLD ;设置增址方向
LOP: LODSB ;取一个数据到AL中
AND AL,AL ;为产生状态标志
JS L1 ;若结果为负数转L1,L1标号取代OPR
JZ L2 ;若结果为零转L2
INC PLUS ;结果为正,统计加1
JMP NEXT ;转下一个
L1: INC MINUS ;负数个数统计
JMP NEXT ;转下一个
L2: INC ZERO ;零个数统计
NEXT: DEC CX ;修改循环次数
JNZ LOP ;CX≠0继续循环
3、【例】: 已知W为16位的数,若W为正数,则令Z=W,若为0,令Z=400H,若为负数,则Z=|W|+50H。
程序段一:
MOV AX,W
CMP AX,0
JZ L1
JNS L2
NEG AX
ADD AX,50H
MOV Z,AX
JMP NEXT
L2: MOV Z,AX
JMP NEXT
L1: MOV Z,400H
NEXT: … …
程序段二:
MOV AX,W
CMP AX,0
JNZ L1
MOV Z,400H
JMP NEXT
L1: JNS L2
NEG AX
ADD AX,50H
MOV Z,AX
JMP NEXT
L2: MOV Z,AX
NEXT: … …
4、【例】在字节变量X中存有一个无符号数,当它高于、等于或低于100的三种情况,分别转去执行三个不同的程序段PROG1、PROG2和PROG3。
主要程序段如下:
MOV AL,X ;X送入AL
CMP AL,100 ;X与100比较产生状态标志位
JA PROG1 ;X﹥100 转PROG1
JB PROG3 ;X﹤100 转PROG3
PROG2: ┉ ;X=100 执行程序段PROG2
┋
PROG1: ┉ ;X﹥100 执行程序段PROG1
┋
PROG3: ┉ ;X﹤100 执行程序段PROG3
5、【例】 设X、Y均为存放在BUF1和BUF2单元中的16位带符号数,满足X>100转移到TOOHIGH去执行,否则作X-Y,如出现溢出,则转移到OVERFLOW去执行,否则计算∣X-Y∣,并把结果存入RESULT中。
主要的程序段为:
MOV AX,BUF1 ;取X值
CMP AX,100
JG TOOHIGH ;X>100 转
SUB AX,BUF2 ;X-Y→AX
JO OVERFLOW ;溢出转OVERFLOW
JNS NEXT ;为非负数,则转NEXT
NEG AX
NEXT: MOV RESULT,AX
TOOHIGH: ┋
┋
OVERFLOW: ┇
6、【例】 X、Y为两个带符号双精度数,已分别存放于DX、AX及BX、CX中。要求编制一个程序使X﹥Y时,转向L1执行,X=Y时转向L2执行,X﹤Y时转L3执行。
主要程序段如下:
CMP DX,BX ;先比较高16位为带符号数
JG L1
JL L3
CMP AX,CX ;再比较低16位为无符号数
JA L1
JB L3
L2: ┇
L1: ┇
L3: ┇
7、例: M字数组的首地址ARRAY,试编写一个程序,求出该数组的内容之和(不考虑溢出),并把结果存入TOTAL中。
程序段如下:
?
MOV CX,M ;循环次数
MOV AX,0 ;AX寄存器清0
MOV SI,AX ;SI寄存器清0
LSTART:ADD AX,ARRAY[SI]
ADD SI,2
LOOP LSTART
MOV TOTAL,AX ;结果送TOTAL
?
8、例:有一串L个字符的字符串存储于首地址为ASCII_STR的存储区中。如要求在字符串中查找“空格”(ASCII码为20H)字符,找到则继续执行,如末找到则转到NOT_FOUND去执行,编制实现这一要求的程序如下:
MOV CX,L
MOV SI,-1
MOV AL,20H
NEXT: INC SI
CMP AL,ASCII_STR[SI]
LOOPNE NEXT
JNZ NOT_FOUND
?
NOT_FOUND:
在程序执行的过程中,有两种可能性:
(1)在字符串中找到了空格,经CMP指令产生ZF=1,因此提前结束循环。在执行JNZ指令时,因不满足测试条件ZF=0的要求而不转到NOT_FOUND去执行指令,而是顺序执行JNZ以下的“找到空格字符所要执行的程序段”。
(2)如果查遍整个字符串还找不到空格而结束循环,此时必有CX=0,ZF=0,所以在执行指令JNZ时,满足条件ZF=0的要求而转到NOT_FOUND处执行指令。
?
9、【例】 CALL BX
若事先BX=2600H,指令CALL执行后转到同一个代码段,可知子程序的入口地址IP=BX=2600H,于是从2600H偏移地址处开始执行子程序。
5.7 处理机控制指令
?5.7.1 标志位操作指令
1.??? CLC (Clear carry) 进位位置0指令
指令格式与操作:CLC ;CF←0
2. STC (Set carry) 进位位置1指令
指令格式与操作:STC ;CF←1
3. CMC (Complement carry) 进位位求反指令
指令格式与操作:CMC ;CF←CF
4. CLD (Clear direction) 方向标志位置0指令
指令格式与操作:CLD ;DF←0,设置增址方向
5. STD (Set direction) 方向标志位置1指令
指令格式与操作:STD ;DF←1,设置减址方向
6. CLI (Clear interrupt) 中断标志位置0指令
指令格式与操作:CLI ;IF←0,中断被屏蔽
7. STI (Set interrupt) 中断标志位置1指令
指令格式与操作:STI ;IF←1,中断开放
当IF置1后,CPU将允许外部的可屏蔽中断请求。
这组指令仅对有关状态标志位进行操作,而对其他状态标志位则没有影响。