(2) 比较操作实际就是作减法操作,只是不保存减法所得到的差(即不改变两个操作数本身),而将结果反映在标志位CY上。 (3) CJNE指令将参与比较的两个操作数当作无符号数看待、处理并影响CY标志。因此CJNE指令不能直接用于有符号数大小的比较。
若进行两个有符号数大小的比较,则应依据符号位和CY位进行判别比较。
3.减1条件转移指令
这是一组把减1与条件转移两种功能结合在一起的指令。这组指令共有2条: DJNZ Rn ,rel ;Rn ←(Rn)-1
若(Rn)?0, 则转移,PC←(PC)+2+rel 若(Rn)=0, 按顺序执行,PC←(PC)+2 DJNZ direct ,rel ;direct ←(direct)-1 若(direct)?0,则转移, PC←(PC)+3+rel 若(direct)=0, 按顺序执行, PC←(PC)+3 这组指令的操作是先将操作数(Rn或direct)内容减1,并保存结果,如果减1以后操作数不为0,则进行转移;如果减1以后操作数为0,则程序按顺序执行。
注意:第一条为二字节指令,第二条指令为三字节指令。这两条指令与DEC指令一样,不影响PSW中的标志位。
这两条指令对于构成循环程序十分有用,可以指定任何一个工作寄存器或者内部RAM单元为计数器。对计数器赋以初值以后,就可以利用上述指令,若对计数器进行减1后不为零就进行循环操作,为零就结束循环,从而构成循环程序。
例3-21 试编写程序,将内部RAM以DATA为起始地址的10个单元中的数据求和,并将结果送入SUM单元。设和不大于255。
解:对一组连续存放的数据进行操作时,一般都采用间接寻址,使用INC指令修改地址,可使编程简单,利用减1条件转移指令很容易编成循环程序来完成10个数相加。
MOV R0,#DATA ;数据块首地址送入间址寄存器R0
MOV R7,#0AH ;计数器R7送入计数初值 CLR A ;累加器A存放累加和,先清0
LOOP:ADD A,@R0 ;加一个数
INC R0 ;地址加1,指向下一个地址单元 DJNZ R7,LOOP ;计数值减1不为零循环 MOV SUM,A ;累加和存入指定单元 SJMP $ ;结束
例3-22 将外部RAM的一个数据块传送到内部RAM,两者的首地址分别为DATA1和DATA2,遇到传送的数据为“$”字符,停止传送。
解:外部RAM向内部RAM的数据传送不能直接传送,一定要以累加器A作为桥梁,将数据先取入A中,与“$”的ASCⅡ码比较,不相等,进行传送;相等,终止传送。
MVO DPTR ,#DATA1 ;外部数据块首地址送DPTR MOV R1 ,#DATA2 ;内部数据块首地址送R1 LOOP:MOVX A ,@DPTR ;从外部RAM取数送入A
21
CJNE A,#24H,LOOP1 ;与 $ 比较,不等转移 SJMP LOOP2 ;是 $ 字符,转结束 LOOP1: MOV @R1 ,A ;不是 $ 字符,执行传送 INC DPTR ;修改源地址指针 INC R1 ;修改目的地址指针
SJMP LOOP ;转传送下一个数据 LOOP2: SJMP $ ;结束
以上介绍了MCS-51系列单片机中的各种条件转移指令。这些条件转移指令都是相对转移指令,因此,转移的范围是很有限的。若要在大范围内实现条件转移,可将条件转移指令和长转移指令LJMP结合起来加以实现。
例如,根据A和立即数80H比较的结果转移到标号NEXT1,其转移的距离已超过了256字节,则可用以下指令来实现: CJNE A ,#80H ,NEXT ;不相等,则转移
┇ ;相等,按顺序执行
SJMP NEXT2 ;执行完,跳到NEXT2
NEXT:LJMP NEXT1 ;长转移至NEXT1 CJNE与LJMP这两条指令的结合,可以实现在64KB范围内的条件转移。其中的SJMP NEXT2指令是在执行完两数相等的处理后,转移到继续执行的位置,以免也要去执行LJMP指令,造成程序逻辑上的混乱
3.6.3 子程序调用及返回指令
在程序设计中,常常出现几个地方都需要进行功能完全相同的处理,如果重复编写这样的程序段,会使程序变得冗长而杂乱。对此,可以采用子程序,即把具有一定功能的程序段编写成子程序,通过主程序调用来使用它,这样不但减少了编程工作量,而且也缩短了程序的长度。
调用子程序的程序称之为主程序,主程序和子程序之间的调用关系可用图3-8表示。 从图中可以看出,子程序调用要中断原有指令的执行顺序,转移到子程序的入口地址去执行子程序。与转移指令不同的是:子程序执行完毕后,要返回到原有程序被中断的位置,继续往下执行。因此,子程序调用指令必须能将程序中断位置的地址保存起来,一般都是放在堆栈中保存。堆栈的先入后出的存取方式正好适合于存放断点地址。特别适合于子程序嵌套时断点地址的存放。
22
(a) (b)
图3-8 子程序调用示意图 图3-9 子程序嵌套及断点地址存放
如果在子程序中还调用其他子程序,称为子程序嵌套,二层子程序嵌套过程如图3-9 (a)所示。图3-9(b)为二层子程序调用后,堆栈中断点地址存放的情况。先存入断点地址1,程序转去执行子程序1,执行过程中又要调用子程序2,于是在堆栈中又存入断点地址2。存放时,先存地址低8位,后存地址高8位。从子程序返回时,先取出断点地址2,接着执行子程序1,然后取出断点地址1,继续执行主程序。
调用和返回构成了子程序调用的完整过程。为了实现这一过程,必须有子程序调用指令和返回指令。调用指令在主程序中使用,而返回指令则是子程序中的最后一条指令。
1.子程序调用指令
MCS-51系列单片机共有两条子程序调用指令
LCALL addr16 ;PC←(PC)+3 SP←(SP )+1,(SP )←(PC )7~0 SP←(SP )+1,(SP )←(PC )15~8 PC←addr16 ACALL addr11 ;PC←(PC)+2 SP←(SP )+1,(SP )←(PC)7~0 SP←(SP )+1,(SP )←(PC)15~8 PC10~0 ←addr11
LCALL指令称为长调用指令,是三字节指令。指令的操作数部分给出了子程序的16位地址。该指令功能是:先将PC加3,指向下条指令地址(即断点地址),然后将断点地址压入堆栈,再把指令中的16位子程序入口地址装入PC。以使程序转到子程序入口处。
长调用指令可调用存放在64KB程序存储器任意位置的子程序,即调用范围为64KB。 ACALL指令称为绝对调用指令,是两字节指令。其指令格式为:
a10 a9 a8 0 0 0 0 1 a7 a6 a5 a4 a3 a2 a1 a0 指令的操作数部分提供了子程序的低11位入口地址,其中 a7 ~ a0 在第二字节,a10 ~ a8 则占据第一字节的高3位,而10001是这条指令特有的操作码,占据第一字节的低5位。
绝对调用指令的功能是:先将PC加2,指向下条指令地址(即断点地址),然后将断点地址压入堆栈,再把指令中提供的子程序低11位入口地址装入PC的低11位上,PC的高5位保持不变。使程序转移到对应的子程序入口处。
子程序调用地址是由子程序的低11位地址与PC的高5位合并组成,调用范围为2KB。 使用时应注意:ACALL指令所调用的子程序的入口地址必须在ACALL指令之后的2KB区域内。若把64KB内存空间以2KB字节为一页,共可分为32个页面,所调用的子程序应该与ACALL下面的指令在同一个页面之内,即它们的地址高5位a15 ~ a11 应该相同。也就是说,在执行ACALL指令时,子程序入口地址的高5位是不能任意设定的,只能由ACALL
23
下面指令所在的位置来决定。因此,要注意ACALL指令和所调用的子程序的入口地址不能相距太远,否则就不能实现正确的调用。例如,当ACALL指令所在地址为2300H时,其高5位是00100,因此,可调用的范围是2300H~27FFH。
2.返回指令
返回指令也有两条:
RET ;PC15~8 ←((SP)),SP ←(SP)-1
PC7~0 ←((SP)),SP ←(SP)-1 RETI ;PC15~8 ←((SP)),SP ←(SP)-1 PC7~0 ←((SP)),SP ←(SP)-1
RET指令被称为子程序返回指令,放在子程序的末尾。其功能是从堆栈中自动取出断点地址送入程序计数器PC,使程序返回到主程序断点处继续往下执行。
RETI指令是中断返回指令,放在中断服务子程序的末尾。其功能也是从堆栈中自动取出断点地址送入程序计数器PC,使程序返回到主程序断点处继续往下执行。同时还清除中断响应时被置位的优先级状态触发器,以告之中断系统已经结束中断服务程序的执行,恢复中断逻辑以接受新的中断请求。
请读者注意:
① RET和RETI不能互换使用。 ② 在子程序或中断服务子程序中,PUSH指令和POP指令必须成对使用,否则,不能正确返回主程序断点位置。
3.6.4 空操作指令
NOP ;PC←PC+1
这是一条单字节指令。该指令不产生任何操作,只是使PC的内容加1,然后继续执行下一条指令,它又是一条单周期指令,执行时在时间上消耗一个机器周期。因此,NOP指令常用来实现等待或延时。
3.7 位操作类指令
MCS-51系列单片机其特色之一就是具有丰富的布尔变量处理功能。所谓布尔变量即开关变量,它是以位(bit)为单位来进行运算和操作的。也称为位变量。在硬件方面它有一个布尔处理器,实际上是一个一位微处理器,它是以进位标志CY作为位累加器,以内部RAM位寻址区中的各位作为位存储器。在软件方面它有一个专门处理布尔变量的指令子集,可以完成布尔变量的传送、逻辑运算、控制转移等操作。这些指令通常称之为位操作指令。 位操作类指令的操作对象:一是内部RAM中的位寻址区,即20H~2FH中的128位(位地址00H~7FH)。二是特殊功能寄存器中可以进行位寻址的各位。 位地址在指令中都用bit表示,bit有四种表示形式。一是采用直接位地址表示;二是采用字节地址加位序号表示;三是采用位名称表示;四是采用特殊功能寄存器加位序号表示。
进位标志CY在位操作指令中直接用C表示,以便于书写。位操作指令共有17条。 3.7.1 位变量传送指令
MOV C , bit ;CY←(bit)
MOV bit , C ;bit←(CY)
24