您的位置: 网站首页 > 程序开发 > 汇编语言与微机原理教程 > 第9章 80x86的寻址方式与指令系统 > 【9.3.4 控制转移指令】

9.3.4 控制转移指令

 

9.3.4  控制转移指令

程序控制指令能控制程序执行的流程,可构成转移、循环、调用和返回。

1.控制转移指令

转移指令分无条件转移和条件转移两类,它们本身执行后都不影响FL寄存器的状态标志。

1)无条件转移指令。

无条件转移指令JMP<TARGET>,控制程序转移到TARGET目标)标号处去执行。按TARGET目标地址单元的属性有4种转移范围、5种指令格式。

JMP SHORT<TARGET>           ; 段内直接短转移

JMP NEAR PTR<TARGET>        ; 段内直接近转移

JMP WORD PTR<TARGET>        ; 段内间接转移

JMP FAR PTR<TARGET>         ; 段间直接转移

JMP DWORD PTRTARGET      ; 段间间接转移

段内转移只改变IP值,CS代码段基址)不变。段内直接转移为相对寻址,将IP指向的下条)指令距目标TARGET的偏移量字节距离)与IP的当前值相加后送IP,其中,段内短转移的偏移量为8位,以当前指令位置为准的)转移范围为129-126若以IP当前值为准则为127-128);段内直接近转移的偏移量为16位、以当前指令位置为准的)转移范围为32769-32766若以IP当前值为准则为32767-32768);段内间接转移是绝对寻址,TARGET是一个16位的寄存器或存储器单元,将其内容直接赋给IP;段间转移跨段,段间直接转移将指令中给出的TARGET偏移量和段基址赋给IPCS,段间间接转移将指令中给出的TARGET存储单元开始的4个字节分别赋给IPCS,从而实现跨段转移。

无条件转移指令的汇编格式、语句操作、转移范围如表9-1所示。

9-1  无条件转移指令

指令种类

   

   

转移范围

段内直

接转移

短转移

JMP SHORT<TARGET>

IPIP+Disp8

-128127

近转移

JMP NEAR PTR<TARGET>

IPIP+Disp16

-3276832767

段内间接转移

JMP<Reg16>

IPReg16

当前代码段内

JMP<Mem16>

IPMem16

段间直接转移

JMP FOR PTR<TARGET>

IPTARGET偏移量

CSTARGET段基址

跨段,整个内存

段间间接转移

JMP DWORD PTR <TARGET>

IPEA),CSEA2

注:①在当前代码段内,<……>内为符号地址或寄存器或存储单元的具体内容。

2)条件转移指令。

条件转移指令测试标志寄存器(FL)的当前状态标志,满足条件就转移到目标地址去执行,否则顺序向下执行。条件是对一个或两个或3个状态标志位的状态判断。

8086/8088所有条件转移指令都是段内直接短转移,转移的范围是-128127个字节距离。指令长度为两个字节,第一字节为操作码,第二字节为距TARGET目标)的8位偏移量。

条件转移指令的汇编格式、转移条件、应用场合、指令编码等如表9-2所示。

9-4一个16位数的数组存储在以ARRAY为首地址的数据段中,长度为n小于256)。编程求数组中正数、0及负数的个数,分别存放在BHBLDI中。

MOV CX,<n>                  ; 数组长度送计数器CX

MOV AX0

MOV SI,AX                   ; 数组指针初始化为0

MOV BX,AX                   ; 结果寄存器清零

MOV DIAL

AGAIN  CMP AXARRAY[SI]   ; 比较

JG      PLUS

Jz    ZERO

INC     DI                  ; 是负数,负数个数寄存器加l

JMP     NEXT

ZER0  INC BL               ; 00个数寄存器加1

JMP NEXT

PLUS  INc BH               ; 是正数,正数个数寄存器加1

NEXT  ADD SI2            ; 指向下一个数组元素

DEC CX

JNZ AGAIN                   ; 未结束则继续

9-2  条件转移指令

判断

指令名称

汇编格式

转移条件

应用

等价助记符

单标志位判断

结果为零相等)转移

JZ<TARGET>

ZF=1

相等

比较

JE<TARGET>

结果不为零不相等)转移

JNZ<TARGET>

ZF=0

JNE<TARGET>

结果为负转移

JS<TARGET>

SF=1

正负

判断

 

结果为正转移

JNS<TARGET>

SF=0

 

结果溢出转移

JO<TARGET>

OF=1

溢出

判断

 

结果不溢出转移

JNO<TARGET>

OF=0

 

结果偶特性转移

JP<TARGET>

PF=0

奇偶

判断

JPE<TARGET>

结果奇特性转移

JNP<TARGET>

PF=1

JPO<TARGET>

低于不高于等于)转移

JB<TARGET>

CF=1

无符

号数

比较

JNAE<TARGET>

JC<TARGET>

不低于高于等于)转移

JNB<TARGET>

CF=0

JAE<TARGET>

JNC<TARGET>

双标志位判断

低于等于不高于)转移

JBE<TARGET>

CFZF=1

有符

号数

比较

JNA<TARGET>

不低于等于高于)转移

JNBE<TARGET>

CFZF=0

JA<TARGET>

小于不大于等于)转移

JL<TARGET>

SF xor 0F=1

JNGE<TARGET>

不小于(大于等于)转移

JNL<TARGET>

SF xor 0F=0

JGE<TARGET>

三标志位判断

小于等于不大于)转移

JLE<TARGET>

SF xor 0F

ZF=1

JNG<TARGET>

不小于等于大于)转移

JNLE<TARGET>

SF xor 0F

ZF=0

JG<TARGET>

注:<……>内为目标的具体符号地址名称为∨指or,∧指and

80386开始扩大了条件转移的范围,实模式下能够转移到代码段的任何位置。

2.循环指令

循环程序非常普遍,用条件指令就可实现;为方便编程,基本指令集特意提供了4条循环指令。

循环指令放在循环程序的开头或结尾,通过测试CX是否为0以及ZF标志的状态来控制循环结束与否。循环指令长度都是两个字节,一个字节操作码加8位偏移量,循环转移范围为-128127。循环指令执行不影响标志寄存器(FL)的状态标志。

循环指令的汇编格式、测试条件、语句操作如表9-3循环控制指令所示。

9-3  循环控制指令

指令名称

汇编格式

测试条件

语句操作

循环

LOOP<TARGET>

CX0

CXCX-1

满足条件则循环执行,否则顺序向下执行退出循环)

为零相等)循环

LOOPZ<TARGET>

LOOPE<TARGET>

ZF=1CX0

不为零不相等)循环

LOOPNZ<TARGET>

LOOPNE<TARGET>

ZF=0CX0

CX为零循环

JCXZ<TARGET>

CX=0

同上,但CX不减1

注:<……>内为目标的具体符号地址名称。

9-5一字符串长度<256)存放在ASCII STR单元,ASCII STR单元之后接着存放该字符串。试编程判断该字符串中是否有“空格”字符,若有DI1,否则DI清零。

MOV BX,0                ; 地址指针初始化为0

MOV DI,BL               ; 预置没有“空格”标志

MOV AL,20H              ; “空格”字符送AL

MOV CX,ASCIISTR[BX]     ; 串长度送CX

NEXT  INC  BX

CMP AL,ASCIISTR[BX]     ; 判断是否为空格

LOOPNZ NEXT

JNZ  D0NE

MOV DI,01H              ; 置有“空格”标志

DONE:…                 ; 没有“空格”,继续运行

32位的80x86微处理器还可以使用ECX作为隐含的循环计数器。即便是80486,循环指令也只能在短距离内进行循环,即相对于当前循环指令的地址,转移的范围为-129126

3.子程序调用指令(CALL)和返回指令(RET

子程序调用不同于转移指令,首先要把CALL指令的下一条指令地址即返回地址)入栈保存,然后转向子程序的首地址去执行。调用分段内调用和段间调用。段内调用只对IP操作CS不变),段间调用要同时对CSIP操作。段内/段间调用又分直接调用和间接调用。调用和返回指令都没有条件判断。

调用和返回指令的汇编格式、语句操作如表9-4所示。

返回指令根据调用的距离属性自动执行段内返回或段间返回。带立即数返回指令废除栈顶若干个偶数)字节单元,使堆栈指针SP向栈底高地址方向)移动<Exp>个字节单元,常用于以堆栈传送参数的子程序调用。

9-4  子程序调用和返回指令

指令名称

汇编格式

语句操作

段内直接调用

CALL<PROC>

SPSP-2SPIPIPIP+Disp16

段内间接调用

CALL<Reg16>

CALL<Mem16>

SPSP-2SPIPIPReg16

SPSP-2SPIPIPMem16

段间直接调用

CALL<PROC>

SPSP-2SPCSSPSP-2SPIP

IP偏移地址,CS段基址

段间间接调用

CALL<Mem16>

SPSP-2SPCSSPSP-2SPIPIPEA),CSEA+2

段内返回

RET

IPSP),SPSP+2

段内带立即数返回

RET<Exp>

IPSP),SPSP+2SPSP+<Exp>

段间返回

RET

IPSP),SPSP+2CSSP),SPSP+2

段间带立即数返回

RET<Exp>

IPSP),SPSP+2CSSP),SPSP+2SPSP+<Exp>

注:<……>内为具体名称过程名、寄存器、存储器或表达式,Exp表达式的值为16位无符号偶数。CALL指令格式中可加属性操作符,以指明或修改操作数的属性,参见JMP指令)。

CALLRET指令都不影响标志寄存器(FL)的标志位。

4.中断指令(INT)和中断返回指令(IRET

中断指令(INT)是一种特殊的调用指令调用例行中断子程序),是段间调用;与段间CALL指令相同的是须先把CSIP入栈保存,不同的是还要首先把标志寄存器(FL)入栈保存。中断返回是段间返回,执行IRET指令,依次恢复IPCSFL

INTIRET指令汇编格式、语句操作如表9-5所示。

9-5  中断指令和中断返回指令

指令名称

汇编格式

语句操作

中断指令调用

INT<Exp>

SPSP-2[SP]FLSPSP-2[SP]CS

SPSP-2[SP]IP

IP[n×4]CS[n×4+2]

断点中断调用

INTINT 3

溢出中断调用

INT 0INT 4

中断返回

IRET

IP[SP]SPSP+2CS[SP]SPSP+2

FL[SP]SPSP+2

注:<Exp>表达式结果是nn为中断类型号1255,不能为0