
2.2 指令系统
MCS-51指令系统有42种助记符,代表了33种功能,指令助记符与各种可能的寻址方式相结合,共构成111条指令。在这些指令中,单字节指令有49条,双字节指令有45条,三字节指令有17条;从指令执行的时间来看,单周期指令有64条,双周期指令有45条,只有乘法、除法两条指令的执行时间是4个机器周期。
按指令的功能,MCS-51指令系统可分为下列5类:
1)数据传送类指令(29条);
2)算术运算类指令(24条);
3)逻辑运算及移位类指令(24条);
4)位操作类指令(17条);
5)控制转移类指令(17条)。
在分类介绍指令前,先把描述指令的一些符号的意义做一简单介绍。
Rn——当前选定的寄存器区中的8个工作寄存器R0~R7,n=0~7。
Ri——当前选定的寄存器区中的2个寄存器R0、R1,i=0、1。
Direct——8位内部RAM单元的地址,它可以是一个内部数据区RAM单元(00H~7FH)或特殊功能寄存器地址(I/O端口、控制寄存器、状态寄存器,80H~0FFH)。
#data——指令中的8位常数。
#data16——指令中的16位常数。
addr16——16位的目的地址,用于LJMP、LCALL,可指向64KB程序存储器的地址空间。
addr11——11位的目的地址,用于AJMP、ACALL指令。目的地址必须与下一条指令的第一个字节在同一个2KB程序存储器地址空间之内。
rel——8位带符号的偏移量字节,用于SJMP和所有条件转移指令中。偏移量相对于下一条指令的第一个字节计算,在-128~+127范围内取值。
bit——内部数据RAM或特殊功能寄存器中的可直接寻址位。
DPTR——数据指针,可用作16位的地址寄存器。
A——累加器。
B——寄存器,用于MUL和DIV指令中。
C——进位标志或进位的位。
@——间接寄存器或基址寄存器的前缀,如@Ri,@DPTRBFQ。
/——位操作的前缀,表示对该位取反。
(X)——X中的内容。
((X))——由X寻址的单元中的内容。
←——箭头左边的内容被箭头右边的内容所替代。
2.2.1 数据传送类指令
数据传送类指令一般的操作是把源操作数传送到指令所指定的目标地址。指令执行后,源操作数保持不变,目的操作数被源操作数所替代。
数据传送类指令用到的助记符有:MOV,MOVX,MOVC,XCH,XCHD,PUSH,POP,SWAP。
一般数据传送指令的助记符用“MOV”表示。
格式:MOV[目的操作数],[源操作数]
功能:目的操作数←(源操作数中的数据)。
源操作数可以是:A、Rn、direct、@Ri、#data;目的操作数可以是:A、Rn、direct、@Ri。
数据传送指令一般不影响标志位,只有一种堆栈操作可以直接修改程序状态字PSW,这样,可能使某些标志位发生变化。
1.以累加器为目的操作数的内部数据传送指令

这组指令的功能是:把源操作数的内容送入累加器A。例如:MOV A,#10H,该指令执行时,将立即数10H(在ROM中紧跟在操作码后)送入累加器A中。
2.数据传送到工作寄存器Rn的指令

这组指令的功能是:把源操作数的内容送入当前工作寄存器区的R0~R7中的某一个寄存器。指令中Rn在内部数据存储器中的地址由当前的工作寄存器区选择位RS1、RS0确定,可以是00H~07H、08H~0FH、10H~17H、18H~1FH。例如:MOV R0,A,若当前RS1、RS0设置为00(即工作寄存器0区),执行该指令时,将累加器A中的数据传送至工作寄存器R0(内部RAM 00H)单元中。
3.数据传送到内部RAM单元或特殊功能寄存器SFR的指令

这组指令的功能是:把源操作数的内容送入内部RAM单元或特殊功能寄存器。其中第三条指令和最后一条指令都是三字节指令。第三条指令的功能很强,能实现内部RAM之间、特殊功能寄存器之间或特殊功能寄存器与内部RAM之间的直接数据传送。最后一条指令是将16位的立即数送入数据指针寄存器DPTR中。
片内RAM及寄存器的数据传送指令MOV、PUSH和POP共18条,如图2-5所示。
4.累加器A与外部数据存储器之间的传送指令



图2-5 片内RAM及寄存器的数据传送指令
这组指令的功能是:在累加器A与外部数据存储器RAM单元或I/O口之间进行数据传送前两条指令执行时,P3.7引脚上输出有效信号,用作外部数据存储器的读选通信号;后两条指令执行时,P3.6引脚上输出WR有效信号,用作外部数据存储器的写选通信号。DPTR所包含的16位地址信息由P0(低8位)和P2(高8位)输出,而数据信息由P0口传送,P0口作分时复用的总线。由Ri作为间接寻址寄存器时,P0口上分时Ri指定的8位地址信息及传送8位数据,指令的寻址范围只限于外部RAM的低256个单元。
片外数据存储器数据传送指令MOVX共4条,如图2-6所示。

图2-6 片外数据存储器数据传送指令
5.程序存储器内容送累加器的指令

这是两条很有用的查表指令,可用来查找存放在外部程序存储器中的常数表格。第一条指令是以PC作为基址寄存器,A的内容作为无符号数和PC的内容(下一条指令的起始地址)相加后得到一个16位的地址,并将该地址指出的程序存储器单元的内容送到累加器A。这条指令的优点是不改变特殊功能寄存器PC的状态,只要根据A的内容就可以取出表格中的常数。缺点是表格只能放在该条指令后面的256个单元之中,表格的大小受到了限制,而且表格只能被一段程序所使用。
第二条指令是以DPTR作为基址寄存器,累加器A的内容作为无符号数与DPTR内容相加,得到一个16位的地址,并把该地址指出的程序存储器单元的内容送到累加器A。这条指令的执行结果只与指针DPTR及累加器A的内容有关,与该指令存放的地址无关,因此,表格的大小和位置可以在64KB程序存储器中任意安排,并且一个表格可以为各个程序块所共用。
程序存储器查表指令MOVC共2条,如图2-7所示。

图2-7 程序存储器查表指令
6.堆栈操作指令

在MCS-51单片机的内部RAM中,可以设定一个先进后出、后进先出的区域,称其为堆栈。在特殊功能寄存器中有一个堆栈指针SP,它指出栈顶的位置。进栈指令的功能是:首先将堆栈指针SP的内容加1,然后将直接地址所指出的内容送入SP所指出的内部RAM单元;出栈指令的功能是:将SP所指出的内部RAM单元的内容送入由直接地址所指出的字节单元,接着将SP的内容减1。
例如:进入中断服务程序时,把程序状态寄存器PSW、累加器A、数据指针DPTR进栈保护。设当前SP为60H,则程序段为

执行后,SP内容修改为64H,而61H、62H、63H、64H单元中依次栈入PSW、A、DPL、DPH的内容,当中断服务程序结束之前,有如下程序段(SP保持64H不变):

指令执行之后,SP内容修改为60H,而64H、63H、62H、61H单元的内容依次弹出到DPH、DPL、A、PSW中。
MCS-51提供一个向上的堆栈,因此SP设置初值时,要充分考虑堆栈的深度,要留出适当的单元空间,以满足堆栈的使用。
7.字节交换指令
字节交换主要是在内部RAM单元与累加器A之间进行,有整字节和半字节两种交换方式。
(1)整字节交换指令

(2)半字节交换指令
该指令指的是字节单元与累加器A进行低4位的半字节数据交换,只有一条指令:

(3)累加器高低半字节交换指令
只有一条指令:

【例2-1】分别用上述3种字节交换指令实现:(R0)=30H,(A)=65H,(30H)=8FH。
执行指令:

字节交换指令XCH、XCHD和SWAP共5条,如图2-8所示。

图2-8 数据交换指令
2.2.2 算术操作类指令
算术运算类指令共有24条,包括加、减、乘、除4种基本算术运算指令,这4种指令能对8位的无符号数进行直接运算,借助溢出标志,可对带符号数进行补码运算;借助进位标志,可实现多精度的加、减运算,同时还可对压缩的BCD码进行运算,其运算功能较强。算术指令用到的助记符共有8种:ADD、ADDC、INC、SUBB、DEC、DA、MUL、DIV。
1.加法指令
加法指令分为普通加法指令、带进位加法指令和加1指令。
(1)普通加法指令

这组指令的功能是将累加器A的内容与第二操作数相加,其结果放在累加器A中。相加过程中如果位7(D7)有进位,则进位标志Cy置“1”,否则清“0”;如果位3(D3)有进位,则辅助进位标志Ac置“1”,否则清“0”。
对于无符号数相加,若Cy置“1”,说明和数溢出(大于255)。带符号数相加时,和数是否溢出(大于+127或小于-128),可通过溢出标志OV来判断,若OV置为“1”,说明和数溢出。
【例2-2】(A)=85H,R0=20H,(20H)=0AFH,执行指令:


结果:(A)=34H;Cy=1;AC=1;OV=1。
对于加法,溢出只能发生在两个加数符号相同的情况下。在进行带符号数的加法运算时,溢出标志OV是一个重要的编程标志,利用它可以判断两个带符号数相加时和数是否溢出。
(2)带进位加法指令

这组指令的功能与普通加法指令类似,唯一的不同之处是,在执行加法时,还要将上一次进位标志Cy的内容也一起加进去,对于标志位的影响也与普通加法指令相同。
【例2-3】(A)=85H,(20H)=0FFH,Cy=1,执行指令:


结果:(A)=85H;Cy=1;AC=1;OV=0。
(3)增量指令

这组指令的功能是:将指令中指出的操作数的内容加1。若原来的内容为0FFH,则加1后将产生溢出,使操作数的内容变成00H,但不影响任何标志位。最后一条指令是对16位的数据指针寄存器DPTR执行加1操作,指令执行时,先对低8位指针DPL的内容加1,当产生溢出时就对高8位指针DPH加1,但不影响任何标志位。
【例2-4】(A)=12H,(R3)=0FH,(35H)=4AH,(R0)=56H,(56H)=00H,执行如下指令:


(4)十进制调整指令

这条指令对累加器A参与的BCD码加法运算所获得的8位结果进行十进制调整,使累加器A中的内容调整为2位压缩型BCD码的数。使用时必须注意,它只能跟在加法指令之后,不能对减法指令的结果进行调整,且其结果不影响溢出标志位。
执行该指令时,判断A中的低4位是否大于9,若满足大于则低4位进行加6操作;
同样,A中的高4位大于9则高4位进行加6操作。
例如,有两个BCD数36与45相加,结果应为BCD码81,程序如下:

这段程序中,第一条指令将立即数36H(BCD码36H)送入累加器A;第二条指令进行加法,得结果7BH;第三条指令对累加器A进行十进制调整,低4位(为0BH)大于9,因此要加6,最后得到调整的BCD码为81。过程如下:

2.减法指令
(1)带进位减法指令

这组指令的功能是:将累加器A的内容与第二操作数及进位标志相减,结果送回到累加器A中。在执行减法过程中,如果位7(D7)有借位,则进位标志Cy置“1”,否则清“0”;如果位3(D3)有借位,则辅助进位标志AC置“1”,否则清“0”。若要进行不带借位的减法操作,则必须先将Cy清“0”。
(2)减1指令

这组指令的功能是:将指出的操作数内容减1。如果原来的操作数为00H,则减1后将产生溢出,使操作数变成0FFH,但不影响任何标志位。
3.乘法指令
乘法指令完成单字节的乘法,只有一条指令:

这条指令的功能是:将累加器A的内容与寄存器B的内容相乘,乘积的低8位存放在累加器A中,高8位存放于寄存器B中,如果乘积超过0FFH,则溢出标志OV置“1”,否则清“0”,进位标志Cy总是被清“0”。
【例2-5】(A)=50H,(B)=0A0H,执行指令:

结果:(B)=32H,(A)=00H(即乘积为3200H),Cy=0,OV=1。
4.除法指令
除法指令完成单字节的除法,只有一条指令:

这条指令的功能是:将累加器A中的内容除以寄存器B中的8位无符号整数,所得商的整数部分放在累加器A中,余数部分放在寄存器B中,清进位标志Cy和溢出标志OV为“0”。若原来B中的内容为0,则执行该指令后A与B中的内容不定,并将溢出标志置“1”,在任何情况下,进位标志Cy总是被清“0”。
算术运算类指令包括:ADD、ADDC、SUBB、MUL、DIV、INC、DEC和DA,如图2-9所示。

图2-9 算术运算类指令
2.2.3 逻辑运算指令
逻辑运算指令共有24条,分为简单逻辑操作指令、逻辑与指令、逻辑或指令和逻辑异或指令。逻辑运算指令用到的助记符有CLR、CPL、ANL、ORL、XRL、RL、RLC、RR、RRC,如图2-10所示。

图2-10 逻辑运算类指令
1.简单逻辑操作指令

这组指令的功能是:对累加器A的内容进行简单的逻辑操作,除了带进位的移位指令外,其他都不影响Cy、AC、OV等标志位。下面的示意图可以帮助我们进一步理解循环移位指令。
循环左移指令RL A示意图:

循环右移指令RR A示意图:

带进位的循环左移指令RLC A示意图:

带进位的循环右移指令RRC A示意图:

2.逻辑与指令

这组指令的功能是:将两个操作数的内容按位进行逻辑与操作,并将结果送回目的操作数的单元中。
【例2-6】(A)=37H,(R0)=0A9H执行指令:

结果:(A)=21H。
3.逻辑或指令

这组指令的功能是:将两个操作数的内容按位进行逻辑或操作,并将结果送回目的操作数的单元中。
【例2-7】(A)=37H,(P1)=09H执行指令:

结果:(A)=3FH。
4.逻辑异或指令

这组指令的功能是:将两个操作数的内容按位进行逻辑异或操作,并将结果送回目的操作数的单元中。
2.2.4 控制转移类指令
控制转移指令共有17条,不包括按布尔变量控制程序转移指令。其中有64KB范围的长调用、长转移指令,2KB范围的绝对调用和绝对转移指令,有全空间的长相对转移和一页范围内的短相对转移指令,还有多种条件转移指令。由于MCS-51提供了较丰富的控制转移指令,因此在编程上相当灵活方便。这类指令用到的助记符共有10种:AJMP、SJMP、LJMP、JMP、ACALL、LCALL、JZ、JNZ、CJNE、DJNZ。
1.无条件转移指令
(1)绝对转移指令

这是2KB范围内的无条件跳转指令,执行该指令时,先将PC+2,然后将addr11送入PC10~PC0,而PC15~PC11保持不变,这样得到跳转的目的地址。需要注意的是,目标地址与AJMP后一条指令的第一个字节必须在同一个2KB区域的存储器区域内。这是一条2字节指令,其指令格式为:

操作过程可表示为:PC←(PC)+2
PC10~0←addr11
例如程序存储器的2070H地址单元有绝对转移指令:

因此指令的机器代码为:

程序计数器PC当前=PC+2=2070H+02H=2072H,取其高5位00100和指令机器代码给出的11位地址00101101010,最后形成的目的地址为:0010 0001 0110 1010B=216AH。
(2)相对转移指令

执行指令时,先将PC+2,再把指令中带符号的偏移量加到PC上,得到跳转的目的地址送入PC。
目标地址=源地址+2+rel
源地址是SJMP指令操作码所在的地址。相对偏移量rel是一个用补码表示的8位带符号数,转移范围为当前PC值的-128~+127共256个单元。
若偏移量rel取值为FEH(-2的补码),则目标地址等于源地址,相当于动态停机,程序终止在这条指令上,停机指令在调试程序时很有用。MCS-51没有专用的停机指令,若要求动态停机可用SJMP指令来实现:

或写成:

(3)长跳转指令

执行该指令时,将16位目标地址addr16装入PC,程序无条件转向指定的目标地址。转移指令的目标地址可在64KB程序存储器地址空间的任何地方,且不影响任何标志位。
(4)间接转移指令(散转指令)

这条指令的功能是把累加器A中的8位无符号数与数据指针DPTR的16位数相加(模216),相加之和作为下一条指令的地址送入PC中,不改变A和DPTR的内容,也不影响标志位。间接转移指令采用变址方式实现无条件转移,其特点是转移地址可以在程序运行中加以改变。例如,当把DPTR作为基地址且确定时,根据A的不同值就可以实现多分支转移,故一条指令可完成多条条件判断转移指令功能。这种功能称为散转功能,所以间接指令又称为散转指令。
2.条件转移指令

这类指令是依据累加器A的内容是否为0的条件转移指令,如图2-11所示条件满足时转移(相当于一条相对转移指令),条件不满足时则顺序执行下面一条指令。转移的目标地址在以下一条指令的起始地址为中心的256个字节范围之内(-128~+127)。当条件满足时:


图2-11 条件转移类指令
其中(PC)为该条件转移指令的第一个字节的地址。
3.比较转移指令
在MCS-51中没有专门的比较指令,但提供了下面4条比较不相等转移指令:

这组指令的功能是:比较前面两个操作数的大小,如果它们的值不相等则转移。转移地址的计算方法与上述两条指令相同。如果第一个操作数(无符号整数)小于第二个操作数,则进位标志Cy置“1”,否则清“0”,但不影响任何操作数的内容。
4.减1不为0转移指令

这两条指令把源操作数减1,结果送回到源操作数中去,如果结果不为0则转移。
5.调用及返回指令
在程序设计中,通常把具有一定功能的公用程序段编成子程序,当需要使用子程序时用调用指令,而在子程序的最后安排一条子程序返回指令,以便执行完子程序后能返回主程序继续执行。
(1)绝对调用指令

这是一条2KB范围内的子程序调用指令,其指令格式为;

执行该指令时,PC ←PC+2。

(2)长调用指令

这条指令无条件调用位于16位地址addr16的子程序。执行该指令时,先将PC+3以获得下条指令的首地址,并把它压入堆栈(先入低字节后入高字节),SP内容加2,然后将16位地址放入PC中,转去执行以该地址为入口的程序。LCALL指令可以调用64KB范围内任何地方的子程序。指令执行后不影响任何标志位。其操作过程如下:


(3)子程序返回指令

子程序返回指令是把栈顶相邻两个单元的内容弹出送到PC,SP的内容减2,程序返回PC值所指的指令处执行。RET指令通常安排在子程序的末尾,使程序能从子程序返回到主程序。
(4)中断返回指令

该指令的功能与RET指令类似,通常安排在中断服务程序的最后。
(5)空操作指令

空操作也是CPU控制指令,它没有使程序转移的功能,只消耗一个机器周期的时间。常用于程序的等待或时间的延迟。
2.2.5 位操作指令
MCS-51单片机内部有一个性能优异的位处理器,实际上是一个一位的位处理器,它有自己的位变量操作运算器、位累加器(借用进位标志Cy)和存储器(位寻址区中的各位)等。MCS-51指令系统加强了对位变量的处理能力,具有丰富的位操作指令。位操作指令的操作对象是内部RAM的位寻址区,即字节地址为20H~2FH单元中连续的128位(位地址为00H~7FH),以及特殊功能寄存器中可以对各个位进行位寻址。位操作指令包括布尔变量的传送、逻辑运算、控制转移等指令,它共有17条指令,所用到的助记符有MOV、CLR、CPL、SETB、ANL、ORL、JC、JNC、JB、JNB、JBC共11种,如图2-12所示。

图2-12 位操作类指令
在布尔处理机中,进位标志Cy的作用相当于CPU中的累加器A,通过Cy完成位的传送和逻辑运算。指令中位地址的表达方式有以下几种:
1)直接地址方式,如0A8H;
2)点操作符方式,如IE.0;
3)位名称方式,如EX0;
4)用户定义名方式,如用伪指令BIT定义

经定义后,允许指令中使用WBZD0代替EX0。
以上4种方式都是指允许中断控制寄存器IE中的位0(外部中断0允许位EX0),它的位地址是0A8H,名称为EX0,用户定义名为WBDZ0。
1.位数据传送指令

这组指令的功能是:把源操作数指出的布尔变量送到目的操作数指定的位地址单元,其中一个操作数必须为进位标志Cy,另一个操作数可以是任何可直接寻址位。
2.位变量修改指令

这组指令对操作数所指出的位进行清“0”、取反、置“1”的操作,不影响其他标志位。
3.位变量逻辑与指令

4.位变量逻辑或指令

5.位变量条件转移指令

这组指令的功能是:当某一特定条件满足时,执行转移操作指令(相当于一条相对转移指令);条件不满足时,顺序执行下面的一条指令。前面4条指令在执行中不改变条件位的布尔值,最后一条指令,在转移时将bit清“0”,如图2-13所示。
以上介绍了MCS-51指令系统,理解和掌握本节内容,是用好MCS-51单片机的一个重要前提。

图2-13 位变量条件转移指令
【例2-8】指出下列程序段的每条指令的源操作数是什么寻址方式,并写出每步运算的结果(相关单元的内容)。设程序存储器(1050H)=5AH:

【例2-9】用数据传送指令实现下列要求的数据传送。
1)R0的内容输出到R1。
2)内部RAM 20H单元的内容传送到A中。
3)外部RAM 30H单元的内容送到R0。
4)外部RAM 30H单元的内容送内部RAM20H单元。
5)外部RAM 1000H单元的内容送内部RAM 20H单元。
6)程序存储器ROM 2000H单元的内容送R1。
7)ROM 2000H单元的内容送内部RAM 20H单元。
8)ROM 2000H单元的内容送外部RAM 30H单元。
9)ROM 2000H单元的内容送外部RAM 1000H单元。
解:

