大多数程序在运行时会按顺序从前往后执行指令,但有时需要让程序反复多次执行某段指令,或跳过某段指令去执行另外的指令,这时就需要用程序控制类指令来控制。程序控制类指令具体分为无条件控制转移指令、有条件控制转移指令和子程序调用及返回指令。
1.无条件控制转移指令
无条件控制转移指令在使用时无须规定程序转移的条件。它包括短转移指令、长转移指令、相对转移指令和绝对转移指令。
(1)绝对转移指令
绝对转移指令的操作码助记符是“AJMP”。其指令的形式和功能见表3-25。
表3-25 绝对转移指令
下面以一个程序段为例来说明绝对转移指令的功能。例如:
在执行该指令前,PC中的值是0100H,即(PC)=0100H,如图3-7a所示。执行该指令时,先将(PC)+2=0102H(0000000100000010),然后再用地址0783H(0000011110000011)中的低11位替代0102H中的低11位,得到的新地址是0000011110000011(0783H),在PC中的值为0783H,PC跳转到0783H处并执行该处的指令(MOV A,#0FFH),如图3-7b所示。
由于绝对转移指令只可以改变PC中的低11位,高5位不能改变,故PC值的变化范围为211=2048=2KB,所以该指令只可以跳转执行2KB范围内的指令,即要求转移的地址和当前地址相隔不能超过2KB。
图3-7 绝对转移指令功能说明
a)指令执行前 b)指令执行后
(2)长转移指令
长转移指令比短转移指令的跳转范围更大,它的操作码助记符是“LJMP”。长转移指令的形式和功能见表3-26。
下面以一个程序段为例来说明长转移指令的功能。例如:
0100H:LJMP 0783H
在执行该指令前,PC中的值是0100H,即(PC)=0100H,如图3-8a所示。执行该指令后,PC中的值变为0783H,PC就跳转到0783H地址并执行该处的指令,如图3-8b所示。
表3-26 长转移指令
长转移指令可以改变PC中的16位,故PC中地址变化范围为216=64KB,所以该指令可以跳转执行0~64KB范围内的指令(如从0000H地址最远只能跳至FFFFH地址)。
(3)短转移指令
短转移指令的操作码助记符是“SJMP”。相对转移指令的形式和功能见表3-27。
表3-27 短转移指令
在编写程序时,rel是一个地址标号。
下面以一个程序段为例来说明短转移指令的功能。例如:
在上述程序中,当执行到“0150H:SJMP 0100H”时,程序会跳转到0100H处,并执行“MOV A,#01H”指令。
因为(PC)目=(PC)源+2+rel,所以rel=(PC)目-(PC)源-2=0100H-0150H-2=-52H,所以地址偏移量为-52H。在编写程序时,只需在“SJMP”后面写地址标号,不用写地址偏移量(在汇编时,汇编程序会自动计算偏移量)。如“SJMP START”。
SJMP指令转移的目标地址可以在当前PC地址的前128B到后127B之间(-128~+127)。例如在执行“0150H:SJMP 0100H”指令时,PC地址为0150H,“SJMP”指令可转移的范围是0150H地址的前128个单元到后127个单元。
(4)相对转移指令
相对转移指令的操作码助记符是“JMP”。相对转移指令的形式和功能见表3-28。
图3-8 长转移指令功能说明
a)指令执行前 b)指令执行后
表3-28 相对转移指令
下面以一个程序段为例来说明相对转移指令的功能。例如:
JMP@A+DPTR
如果指令执行前,(A)=12H,(DPTR)=1234H,上述指令执行后,PC中的值为1246H,程序将跳转并执行1246H地址单元的指令。
总之,绝对转移指令AJMP可在2KB的ROM空间转移,但要求转移的地址和当前地址(当前PC值)在同一个2KB区域内;长转移指令LJMP可在0~64KB的ROM空间任意转移;短转移指令SJMP可在当前地址的前128B到后127B的ROM空间内转移;相对转移指令JMP与长转移指令一样,也可在64KB的ROM空间任意转移,但由于累加器A和DPTR中的数据都可变化,故使用起来更灵活。
2.有条件控制转移指令
有条件控制转移指令在某种条件满足时执行转移,不满足则不执行转移。它包括累加器判0转移指令、位控制转移指令、比较不相等转移指令和减1不为0转移指令。
(1)累加器判0转移指令
累加器判0转移指令首先判断累加器是否为0,然后决定是否转移。它有2条指令,各条指令的形式和功能见表3-29。
表3-29 累加器判0转移指令
下面以一个程序段为例来说明累加器判0转移指令的功能。例如:
第1条指令将累加器A清0;在执行第2条指令时,由于A中数据为“0”,所以程序跳转执行地址标号LOOP处的指令,如果A的数据不为0,程序将执行1012H处的指令,即执行下一条指令“MOV A,#23H”。这是因为JZ指令占两个字节,当JZ指令执行完后,PC中的值变为1012H,PC指向下一条指令。
(2)位控制转移指令
位控制转移指令根据某位的值来决定是否转移。它有5条指令,各条指令的形式和功能见表3-30。
下面以一个程序段为例来说明位控制转移指令的功能。例如:
第1条指令是将数据65H送入累加器A中;第2条指令是将寄存器P1的D3位清0;执行第3条指令时,由于P1的D3位为“0”,所以程序会执行下一条指令(第4条指令),若将第2条指令改为“SETB P1.3”,就将P1的D3位置“1”,执行第3条指令时,程序会跳转执行地址标号为LOOP的第1条指令。(www.xing528.com)
表3-30 位控制转移指令
(3)比较不相等转移指令
比较不相等转移指令的操作码助记符是“CJNE”。
指令格式:CJNE操作数1,操作数2,rel
指令的功能是将操作数1与操作数2进行比较,如果两者不相等,则转移到地址标号rel处。比较不相等转移指令有4条,各条指令的形式和功能见表3-31。
表3-31 比较不相等转移指令
(续)
这4条指令为三字节指令,转移范围是以当前PC值为中心的前128B到后127B的空间,即地址标号rel为-128~+127B。
(4)减1不为0转移指令
减1不为0转移指令的操作码助记符是“DJNZ”。
指令格式:DJNZ操作数1,rel
指令的功能是将操作数1减1,如果结果不为“0”,则转移到地址标号rel处。
减1不为0转移指令有2条,各条指令的形式和功能见表3-32。
表3-32 减1不为0转移指令
3.子程序调用和返回指令
在编程时,如果需要某段程序反复运行,可以将该段程序写成子程序的形式。在主程序运行时,可通过子程序调用指令来执行子程序,子程序执行完后,再通过返回指令从子程序返回到主程序。
(1)子程序调用指令
子程序调用指令有2条:长调用指令和绝对调用指令。各条指令的形式和功能见表3-33。
表3-33 子程序调用指令
子程序调用指令的工作原理简单来说,就是在执行子程序前,先将本指令的下一条主程序指令的地址保存在SP中,然后再执行子程序。之所以要将下一条主程序的指令地址保存下来,是为了在执行完子程序后能够返回到下一条主程序指令,并执行它。
子程序调用指令执行过程很复杂,但这些过程都是由单片机硬件自动完成的,编程时一般不用理会。下面以一个程序段为例来说明子程序调用指令的功能。例如:
当程序运行到“LCALL DELAY”指令时,硬件会先将下一条指令“MOV P2,#23H”的地址保存到SP中,然后执行DELAY处的子程序,当子程序运行到“RET”指令时,该指令让硬件将SP中保存的地址送给PC,PC就指向该地址处的指令“MOV P2,#23H”,并执行该条指令。
(2)返回指令
返回指令有2条:子程序返回指令和中断返回指令。各条指令的形式和功能见表3-34。
返回指令工作原理简单来说,就是将保存在SP中的指令地址(即调用指令的下一条指令的地址)取出,送给PC,然后PC指向该地址处的指令并执行它。返回指令从SP中取出地址并送给PC的过程由硬件自动完成,编程时只要知道执行“RET”指令后,程序会返回到调用指令的下一条指令即可。
表3-34 返回指令
4.空操作指令
空操作指令的操作码助记符是“NOP”。
指令格式:NOP
指令的功能是将PC中的值加1,而不进行其他操作,该指令执行时会耗时1个机器周期。
【例3-7】 图3-6所示为单片机系统硬件图,P1所连接的八个LED中,从P1.0所连接的LED开始亮,依次循环,任何时刻只有一个LED亮,如图3-9所示。
解答:本例设计要点如下:
1)若要从右边第一个亮,则P1刚开始输出11111110。
2)若要从右边第一个亮转成第二个亮,可以使用左移指令RL A。
3)“计数循环”的结构格式,如下所示:
Rn为记录次数的寄存器,循环次数使用立即数,如MOV R7,#5。
图3-9 单灯左移动作示意图
4)每个LED亮的时间为0.1s,因此需要一个延时子程序,如下所示:
其中的“DJNZ R6,”指令是对本身的那一条指令执行R6次,对于12MHz时钟脉冲的单片机系统而言,1个机器周期刚好1μs,整个子程序的延时时间T为
流程图与程序设计如下:
小提示
请自主思考尝试单灯巡回流动。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。