什么是控制转移指令?
扫描二维码
随时随地手机看文章
控制转移指令能够改变单片机程序寄存器(PC)的值,即改变单片机从ROM中读取指令的顺序,从而改变程序执行顺序。控制转移指令包括以下几类:无条件转移指令、条件转移指令和子程序调用及返回指令等。
1.无条件转移指令
转移指令也称为跳转指令,其中无条件转移指令执行时,程序必定发生跳转,其指令语法格式见表3-10。
(1)长转移指令LJMP
LJMP指令的操作数是16位目标地址值。指令执行时该地址值被送入程序计数器PC,使得单片机从目标地址所对应的程序存储器单元取指令,并执行该指令。目标地址值是16位的,可以指向64KB ROM地址空间的任何一个单元,即LJMP指令可以不受限制地跳转到程序的任何位置。
【例3-44】LJMP指令。程序段如下:
程序分析:左侧程序与右侧程序的功能完全一致,即:程序将越过指令“MOV A,#00H”直接跳转到NEXT标号处执行“MOV A,#01H”指令;指令“LJMP NEXT”中的“NEXT”是指令“MOV A,#01H”的标号地址,实际上等于“MOV A,#01H”在ROM中的存放地址。
需要指出的是:在实际程序设计时,跳转指令中均以标号地址代表目标地址值;程序汇编时,汇编程序会自动将标号地址转换成实际的目标地址,不需要程序员计算。
(2)绝对转移指令AJMP
在表3-10所示的AJMP功能解释“(PC)←(PC)+2”中,“←”右侧的PC值是AJMP指令在ROM中的存放地址,而AJMP指令长度为2B,所以“←”左侧的PC值是在ROM中紧邻AJMP指令的下一条指令的存放地址,即AJMP指令的当前PC值。另外,由AJMP功能解释的第二部分“(PC)10~0←addr11”可知,AJMP指令跳转时当前PC的高5位(PC15~11)不变化,低11位(PC)10~0的变化范围为211=2KB范围内,即(PC)10-0的取值范围为0000000000B~11111111111B。
通常,单片机的64KB程序地址空间可以被划分成32页,每页2KB,其中页的编号(0~31,即00000B~11111B)也被称为页地址,而每页内存储单元的编号(0~7FFH,即0000000000B~11111111111B)被称为页面内地址。因此,可以说AJMP指令的跳转范围是1个页,该页即是紧邻AJMP指令的下一条指令所在的页。
(3)相对转移指令SJMP
SJMP指令中的地址偏移量rel是8位有符号数,其数值范围是-128~+127。SJMP指令执行时,首先,将SJMP指令的存储地址加2,以获得下一条指令的地址值,即当前PC值;然后,将当前PC值加上rel,从而使程序以当前PC为中心发生-128~+127个字节范围内的跳转。正因为SJMP的跳转范围与当前PC值有关,其跳转范围是相对而非绝对的,所以该指令属于相对转移指令。
【例3-46】SJMP指令。程序段如下:
程序分析:SJMP指令执行后,程序将直接跳转到标号NEXT处执行。与例3-45相似,SJMP指令的跳转范围是有限的,一定要注意跳转的目标地址是否符合跳转范围的要求。
(4)散转指令JMP
散转指令JMP通常用于多分支程序设计,该指令将累加器A中的8位无符号数与数据指针寄存器DPTR中的16位无符号数相加,相加的结果作为转移目标地址送入PC中,使程序跳转到目标地址所对应的ROM单元取指令并执行指令。JMP指令不改变累加器A和DPTR的值,也不影响任何标志位。
(5)空操作指令NOP
NOP指令执行时,除了使程序计数器(PC)的内容加1及执行下一条指令外,没有其他作用。NOP指令可以用于延时程序,实现对程序执行时间的微调。
2.条件转移指令
条件转移指令仅当某一特定条件被满足时才跳转,否则顺序执行转移指令的下一条指令。
(1)累加器A判0转移指令JZ和JNZ
JZ和JNZ指令可以判断累加器A中的数是否为0,常用于比较数值大小的程序中,根据比较结果确定后续程序的执行顺序。JZ和JNZ指令的差别是前者在累加器A为0时跳转,而后者在累加器A不为0时跳转。
(2)位判断转移指令JC和JNC
JC和JNC指令能判断进位标志位(CY)是否为1,与累加器A判0转移指令相似,也常用于比较数值大小的程序中,根据比较的结果确定程序后续执行的顺序。JC和JNC的差别是,JC指令在CY为1时跳转,而JNC在CY为0时跳转。
(3)位判断转移指令JB、JNB与JBC
与JC和JNC指令相似,JB、JNB与JBC也用于判断位数据的状态。不同的是,这三条指令所判断的位可以是包括进位标志位(CY)在内的任意一个可以按位寻址的位。JB和JNB指令分别在所判断位为1和为0时跳转,而JBC指令与JB指令唯一的差别是JBC会在跳转的同时将被判断的位清0。
(4)比较不相等转移指令CJNE
CJNE指令可比较指令中前两个无符号操作数是否相等,如果不相等则跳转。实际上,该指令隐含执行了一个减法运算,即:目的操作数(即第1个操作数)-源操作数(即第2个操作数),并且若目的操作数小于源操作数,则(CY)=1,否则(CY)=0。在CJNE指令执行后,可以进一步根据CY的值来判断CJNE指令中前两个操数的大小关系。另外,隐含执行的减法操作不改变CJNE指令的前两个操作数的值。
(5)减1不为0转移指令DJNZ
DJNZ指令用于控制循环次数。该指令执行时,首先将指令中的第1个操作数减1,然后判断减1的结果是否为0,若为0则跳转,否则不跳转。
3.子程序调用及返回指令
程序中经常需要完成一些重复性的操作,为了减少代码录入工作量、缩短程序长度和降低程序修改及维护的成本,可将这些重复性操作的指令块编制成为子程序。子程序可以被调用指令调用并执行,也可以通过返回指令结束运行。子程序调用指令和返回指令的语法格式见表3-12。
对比无条件转移指令(见表3-10)与调用指令可以发现,这两类指令都可以使程序发生转移(即跳转),其差别是:调用指令将目标地址(addr16或addr11)送入PC前,会将返回地址压入到堆栈之中。所谓返回地址是指紧邻调用指令的下一条指令在ROM中的存放地址,即“(PC)←(PC)+2”中“←”左侧的PC值,而“←”右侧的PC值是调用指令本身的存放地址。
调用指令将返回地址压入堆栈的目的是:在子程序返回时,可以通过返回指令(RET或
RETI)将返回地址从堆栈中取出并送入程序指针计数器(PC),从而使程序返回并执行调用指令的下一条指令。由此可知,转移指令的目标是使程序发生跳转,而调用指令不但使程序跳转,而且还要与返回指令配合使子程序运行结束后返回。
RET指令和RETI指令的差别是:①RETI比RET多了一个“清除中断状态寄存器”操作,即通知CPU中断已处理完毕,可以开放与该中断同级别的中断,以确保中断系统的逻辑正确性,专用于中断程序的返回;②RET指令仅用于一般子程序返回。切记RET和RETI指令不能互换使用。