第 3 章 MCS-51 单片机指令系统
1.MCS-51 单片机指令概述
- MCS-51系列单片机指令系统共有111条指令。
按功能分为5类:①数据传送(29条)②算术运算(24条)③逻辑运算(24条)④控制转移(17条)⑤布尔处理(17条)
按字节长度分为3类:①单字节指令(49条)②双字节指令(46条)③三字节指令(只有16条)
按执行时间分为3类:①单机器周期指令(64条)②双机器周期指令(45条)③四机器周期指令(只有2条)
- MCS-51单片机指令系统的特点:
- ① 助记符少:MCS-51指令系统用44种助记符表示了33种指令功能。
- ②空间和时间效率均较高:平均指令长度和平均指令执行时间短。
- ③更适合于实时控制: MCS-51指令系统中有17条布尔处理指令。
1.MCS-51单片机汇编语言指令格式
- 操作码用来规定指令进行什么操作;
- 操作数则是指令操作的对象;
- 有单字节指令、双字节指令、三字节不同长度的指令,格式不同:
- 1)单字节指令:指令只有一个字节,操作码和操作数同在一个字节中。
- 2)双字节指令:一个字节为操作码,另一个字节是操作数。
- 3)三字节指令:操作码占一个字节,操作数占二 个字节。其中操作数既可能是数据,也可能是地址。
操作数的特点:
① 操作数可以是数据本身,也可以是数据的地址、数据地址的地址或操作数的其他信息;
② 操作数可分为目的操作数和源操作数;
③ 操作数可用二进制数、十进制数或十六进制数表示;
④ 操作数的个数可以是0~3个;
⑤ 操作数与操作码之间用空格分隔,操作数与操作数之间用逗号“,”分隔。
2.布尔处理机
- 布尔处理机——位处理机,专门用于位处理。
布尔处理机硬件主要由以下五部分支持:
① 布尔运算器ALU。
② 布尔累加器Cy(PSW.7)。
③ 布尔RAM区。
④ 布尔I/O口
⑤ 布尔指令集
3.指令中的常用符号
- 1)#:立即数前导符。#data:8 位立即数;#data16:16 位立即数。
- 2)direct:8 位直接地址,代表片内 RAM 或 SFR 的地址 00H~7FH 或 80H~FFH。
- 3)@:间接寻址符。在间接寻址方式中,表示间接寻址寄存器指针的前缀标志。如@Ri, @DPTR,@A+PC,@A+DPTR。
- 4)addr11:11 位目的地址。主要用于 ACALL 和 AJMP 指令中。
- 5)addr16:16 位目的地址。主要用于 LCALL 和 LJMP 指令中。
- 6)rel:带符号的 8 位偏移地址。主要用于相对转移指令,以形成转移的目的地址,其 范围是相对于下一条指令第 1 字节地址的−128~+127 个字节。
- 7)bit:位地址。代表片内 RAM 中的可寻址位 00H~7FH 及 SFR 中的可寻址位。
- 8)Rn(n=0~7):表示当前工作寄存器 R0~R7 中的任一个寄存器。
- 9)Ri(i=0 或 1):表示通用寄存器组中用于间接寻址的两个寄存器 R0 或 R1。
- 10)A(或 ACC)、B:表示累加器、B 寄存器(A 是寄存器寻址方式,ACC 是直接寻 址方式的累加器)。
- 11)C:表示 PSW 中的进位标志位 Cy,也称位累加器。
- 12)$:表示当前指令的地址。
- 13)/:在位逻辑与、逻辑或操作指令中,表示对该位先求反后再参与相应的逻辑运算, 但该位的内容保持不变。
- 14)(X):表示由 X 所指定的某寄存器或某单元中的内容。
- 15)((X)):表示由 X 间接寻址单元中的内容。
- 16)←:表示指令的操作结果是将箭头右边的内容传送到左边。
- 17)→:表示指令的操作结果是将箭头左边的内容传送到右边。
- 18) ∧ 、∨ 、⊕ :表示逻辑与、或、异或。
2.MCS-51 单片机的寻址方式
寻址方式——计算机指令中说明操作数所在地址的方法。
MCS-51 单片机的指令系统有 7 种寻址方式,分别为立即寻址、直接寻址、寄存器寻址、 寄存器间接寻址、基址加变址寻址、相对寻址和位寻址。
1.立即寻址
- 寻址空间:程序存储器。
- 立即寻址是指
指令中直接给出操作数本身的寻址方式
。指令中的操作数称为立即数,立即数前面加“#”以区别直接寻址。
例如:MOV A,#45H
- 其中,45H就是立即数,指令的功能是把立即数45H传送到累加器A中。参考下图:
注:E0H为累加器A的字节地址。
- 在MSC-51型单片机中,除了有8位立即数外,还有一条16位立即数的数据传送指令,即
MOV DPTR,#dataH
,其功能是把16位立即数传送到数据指针DPTR中。
例如:MOV DPTR,#1234H
- 上式表示把立即数1234H传送到数据指针DPTR中,其中12H传送到DPH,34H传送到DPL中。参考下图:
注:DPH的字节地址是83H,DPL的字节地址是82H。
2.直接寻址
- 寻址空间:内部RAM的低128字节和特殊功能寄存器SFR(直接寻址是访问SFR的唯一寻址方式)。
- 指令中给出的不是操作数本身,而是操作数的单元地址称为直接寻址。
- 直接寻址的指令有三种形式:
例如:MOV A, 45H
- 45H就是要操作的数据所在的单元地址,如果内RAM(45H)=36H,那么指令执行后(A)=36H。参考下图:
例如:ANL 30H,#30H
- ANL是逻辑“与”操作指令,第一个30H是操作数地址,第二个30H是参加“与”运算的操作数。最后将“与”的结果存入第一个30H单元中。
例如:
MOV 40H,B // 将寄存器B中的数值送入内部RAM的40H单元中
INC 30H // 将内部RAM的30H单元中的数值加一
MOV TL0,R7 // 将寄存器R7中的数值送入特殊功能寄存器TL0中
3.寄存器寻址
-
寻址空间:R0~R7,A、B、Cy(位),DPTR。
-
寄存器寻址方式:指令给出存放操作数据的某个寄存器,而不是数据本身。即指出寄存器组R0~R7中的某一个或其他寄存器(A,B,DPTR和进位Cy等)的内容为操作数。当寄存器为Rn时,操作码的低3位指明是R0~R7中的哪一个。
-
寄存器寻址有三种指令形式:
例如:MOV A,R7
- 指令中R7就是存放源操作数据的寄存器,如果(R7)=19H,则指令执行后(A)=19H,而上述指令为:01011111,其中低三位111就表示操作数寄存器是R7。
例如:
MOV R1,B // 将寄存器B中的数值送入寄存器R1中
INC R2 // 将寄存器R2中的数值加一
MOV A,R5 // 将寄存器R5中的数值送入累加器A中
4.寄存器间接寻址
-
寻址空间:内部RAM(@R0,@R1,SP)和外部数据存储器(@R0,@R1,@DPTR)。
-
将要处理的数据的地址放在寄存器中,即用寄存器中的数据作为存储单元的地址数值。
-
寄存器间接寻址的操作数要以寄存器的符号形式表示,即在寄存器前面添加前缀“@”。
-
寄存器间接寻址有三种指令形式:
例如:已知(R0)=30H,(30)=40H,分析指令:MOV A,@R0
- 这是累加传送指令,设(R0)=30H,则该指令是把内部RAM的30H写入累加器A中。
例如:
MOV @R1,#05H // 将数值05H送入以R1内数值为地址的内部RAM中
ADD A,@R1 // 将A寄存器中的数值加上R1内部数值为地址的内部RAM单元中的数据,结果存放于A中
MOVX A,@DPTR // 将以DPTR中数值为地址的外部数据存储器的内容送至A中存储
5.基址加变址寻址
- 基址加变址寻址:
将要处理的数据地址分开存放在基地址和变地址寄存器中,即用一个寄存器(称为基址寄存器)中的数据作为存储单元的基本地址数值,用另一个寄存器(称为变址寄存器)中的数据作为存储单元的偏移地址数值,实际寻址单元的地址数值为两个寄存器内容之和
。 - 寻址空间:程序存储器(@A+DPTR,@A+PC)
- 以DPTR或PC作基址寄存器,A作变址寄存器(存放8位无符号数),两者相加形成16位程序存储器地址作操作数地址,用改地址去访问ROM。
- 该寻址方式是单字节指令,用于读出程序存储器中数据表格中的常数(查表)到累加器A中。
例如:已知(DPTR)=1234H,(A)=50H,程序存储器(1284H)=65H,分析如下执行结果:MOVC A,@A+DPTR。
- DPTR与A相加后的地址是1284H,而实际寻址地址是1284H,其操作数是65H,最后将65H送至累加器A中。
例如:
MOVC A,@A+PC // 将A和PC两个寄存器的数值相加之和作为程序存储器中的数据地址,将该地址的内容送到A中
MOVC A,@A+DPTR // 将A和DPTR两个寄存器的数值相加之和作为程序存储器中的数据地址,将该地址的内容送到A中
6.相对寻址
- 相对寻址是把程序计数器PC的内容加上指令格式中的形式地址D而形成操作数的有效地址。程序计数器的内容就是当前指令的地址。“相对”寻址,就是相对于当前的指令地址而言。
- 寻址空间:程序存储器
- 在相对转移指令中使用,相对转移指令执行时,将当前的PC值加上指令中规定的偏移量rel,其和作为实际的转移目标地址。
- PC的当前值是相对转移指令下面一条指令的地址。
- 目标地址、当前的PC值和rel三者之间的关系:
- rel=目标地址-(PC)
- rel为补码形式的8位地址偏移量(-128~+127)
- 相对转移指令有三种指令形式:
例如:2000H:SJMP 06H
- 该指令是一条2B指令,它存储在ROM 2000H、2001H这两个单元中。当执行到该指令时,首先取出该指令,由于PC具有自动加1功能,取出指令后PC内容已加2,此时PC当前值为2002H,地址偏移量06H为正值,可得转移的目的地址是2002H+06H=2008H,即程序将从2008处开始执行。执行过程如图所示:
- 偏移量rel的计算公式
- 正向跳转时: r e l = 目 的 地 址 − 转 移 指 令 所 在 的 起 始 地 址 − 转 移 指 令 的 字 节 数 = 地 址 差 值 − 转 移 指 令 的 字 节 数 rel=目的地址-转移指令所在的起始地址-转移指令的字节数=地址差值-转移指令的字节数 rel=目的地址−转移指令所在的起始地址−转移指令的字节数=地址差值−转移指令的字节数
- 反向跳转时,目的地址小于转移指令的起始地址,rel用负数的补码形式表示。 r e l = ( 目 的 地 址 − ( 转 移 指 令 的 起 始 地 址 + 转 移 指 令 的 字 节 数 ) ) 补 rel=(目的地址-(转移指令的起始地址+转移指令的字节数))_补 rel=(目的地址−(转移指令的起始地址+转移指令的字节数))补
有如下程序段
……
JNZ NEXT
……
NEXT:……
假设指令JNZ NEXT的地址为2000H(当前PC的值为2002H),标号NEXT的地址为2340H,则指令JNZ NEXT中的相对偏移量: rel=2340H-2002H=33EH
2340H:0010 0011 0100 0000
2002H:0010 0000 0000 0010
0010 0011 0100 0000
+ 0010 0000 0000 0010
--------------------------
0000 0011 0011 1110
--------------------------
0 3 3 E H
所以,rel=33EH
机器汇编时,该rel的值是在汇编时由汇编器计算,人工汇编时由程序员计算
指令JNZ NEXT执行时,将计算当前PC的值与rel之和(2002H+33EH=2340H),然后转移到地址为2340H处执行
7.位寻址
- 寻址空间:片内RAM的20H~2FH中的128个可寻址位和11个字节地址能被8整除的SFR中的83个可寻址位,共210个位。
- 对内部RAM、特殊功能寄存器SFR中的位地址空间进行访问寻址方式称之为位寻址 。
- 注意:访问累加器CY的寻址方式既可属于寄存器寻址又可属于位寻址。
- 位地址的表示有4种方法:
- ① 直接使用位寻址区中的位地址。
MOV C,7EH; (Cy)←(7EH)
- ② 采用“字节地址.位号”表示方法。上述位地址7EH可以表示为2FH.6,相应指令为:
MOV C,2FH.6 ;(Cy)←(2FH.6)
- ③ 采用“特殊功能寄存器名.位号”表示方法。
MOV C,ACC.0 ;(Cy)←(ACC.0)
- ④ 使用位名称。
SETB EA
- ① 直接使用位寻址区中的位地址。
注:SETB EA:EA置为1;CLR EA:EA置为0。
各寻址方式与相应的寻址空间
寻址方式 | 利用的变量 | 使用的空间 |
---|---|---|
寄存器寻址 | R0~R7,A,B,CY,DPTR | 片内 |
直接寻址 | direct | 片内RAM低128字节 特殊功能寄存器SFR |
寄存器间址 | @R0,@R1,SP @R0,@R1,@DPTR | 片内RAM 片外RAM与I/O口 |
立即寻址 | #data | 程序存储器 |
基址加变址 | @A+PC @A+DPTR | 程序存储器 |
相对寻址 | PC+rel | 程序存储器 |
位寻址 | bit | 片内RAM的20H~2FH 可位寻址的SFR |
3.MCS-51 单片机的指令系统
在MCS-51单片机的指令中:操作码占1字节;
-
操作数中:
- 直接地址direct占1字节
- #data占1字节
- #data16占两字节
-
A、B、R0~R7、@Ri、@DPTR、@ A+ DPTR、 @ A+ PC等均隐含在操作码中(由操作码中的几位二进制位表示)。
1.数据传送指令
所谓数据“传送”,就是把源操作数传送到目的寄存器或RAM单元中,指令执行后一般源地址单元内容不变,属于“复制”而不是“剪切”;或者源操作数与目的地址单元内容互换(交换指令)。
数据传送指令共29条,可分为五类:
-
内部RAM或寄存器间的数据传送(16条)MOV
-
累加器A与外部RAM间的数据传送(4条)
-
累加器A与程序存储器间的数据传送(2条)
-
数据交换(5条)
-
堆栈操作(2条)
1.内部RAM或寄存器间的数据传送(16条) MOV
指令格式 | 举 例 | 指令功能 |
---|---|---|
MOV A,#data | MOV A,#25H | 将立即数25H送至A |
MOV A,Rn | MOV A,R3 | 将寄存器R3中的内容送至A |
MOV A,direct | MOV A,45H | 将45H单元的内容送至A |
MOV A,@Ri | MOV A,@R0 | 将寄存器R0所指的内存单元内容送至寄存器A |
MOV direct,#data | MOV direct,#22H | 将立即数22H送RAM区direct单元 |
MOV direct,A | MOV 22H,A | 将A中的内容送至40H单元 |
MOV direct,Rn | MOV 23H,Rn | 将寄存器Rn中的内容送至23H单元 |
MOV direct,@Ri | MOV 24H,@Ri | 将Ri所指单元的内容送至24H单元 |
MOV direct,direct2 | MOV 30H,40H | 将40H单元的内容送至30H单元 |
MOV Rn,#data | MOV R6,#66H | 将8位立即数66H送至R6 |
MOV Rn,A | MOV R7,A | 将A中的内容送至寄存器R7 |
MOV Rn,direct | MOV R4,60H | 将60H单元的内容送至寄存器R4 |
MOV @Ri,#data | MOV @R0,#25H | 将8位立即数25H送至R0所指的RAM单元中 |
MOV @Ri,A | MOV @R1,A | 将A中的内容送至R1所指的RAM单元 |
MOV @Ri, direct | MOV @R0, 25H | 将25H单元的内容送至R1所指的RAM单元 |
MOV DPTR , #data16 | MOV DPTR , #2300H | 将16位立即数2300H送至数据指针寄存器 |
-
注意事项:
-
1.立即数是一个不带符号的8位常数,且立即数不能作目的操作数;
-
2.direct表示的是8位直接地址,以此指出8051中128个RAM单元和128-255之间的特殊功能寄存器。但是要注意在128-235区有很多单元是空的写入空单元的数将被丢掉,从空单元读取的数无意义。
-
3.通用寄存器之间不允许直接传送;
-
4.通用寄存器与寄存器间接寻址的RAM单元之间不能直接传送;
错误的: MOV Rn,Rn MOV @Ri, @Ri MOV Rn, @Ri MOV #data, A
-
5.在指令格式中,立即数寻址和直接寻址的表示方式不同。
MOV A,#40H 立即数40H送A MOV A,40H 40H单元的内容送A MOV 40H,#40H 将立即数40H送40H单元
-
2.累加器A与外部RAM间的数据传送(4条) MOVX
- CPU与外部数据存储器或外部扩展的I/O口之间进行数据传送时,必须使用外部传送指令MOVX。
- 外部数据传送必须通过累加器A,且只能采用寄存器间接寻址(用R0, R1和DPTR三个间接寻址的寄存器)方式完成。
汇编语言指令 | 举例 | 指令功能 |
---|---|---|
MOVX A, @Ri | MOVX A, @R1 | 将R1所指的外部存储器单元的内容送A |
MOVX A, @DPTR | MOVX @R0,A | 将A中的内容送至Ri所指的外部存储器单元 |
MOVX @Ri, A | MOVX A,@DPTR | 将16位指针DPTR所指的外部存储器单元的内容送至A |
MOVX @DPTR, A | MOVX @DPTR,A | 将A中的内容送至DPTR所指的外部存储器单元 |
- 例.下列指令执行完之后,累加器A和外部RAM 1234H单元内容分别是多少?
MOV 30H,#44H ;(30H)=44H
MOV R1,#30H ;(R1)=30H
MOV A,@R1 ;(A)=44H
MOV DPTR,#1234H ;(DPTR)=1234H
MOVX @DPTR,A ;(1234H)=(A)=44H
执行完上述指令之后,(A)=44H,(1234H)=44H
- 注意:
- 由于Ri是8位的寄存器,所以只能访问片外RAM的一页中的256个单元,页内偏移地址00H~0FFH放在Ri中,页地址先由P2口输出。
- DPTR可以访问片外RAM的全部64KB的空间。
3.累加器A与程序存储器间的数据传送(2条)MOVC
- MCS-51单片机的程序存储器内的数据是只读的,因此程序存储器的数据传送是单向的,并且只能读到累加器A中。这类指令在查表中经常用到,所以又称为查表指令。查表指令一共有2条,都属于基址加变址寻址。
编语言指令 | 机器码 | 指令功能 |
---|---|---|
MOVC A , @A+DPTR | 1001 0011 | 将DPTR中的16位地址和A中的内容相加得新地址,将此地址单元中的内容送至A中 |
MOVC A , @A+PC | 1000 0011 | 将PC和A中的内容相加,所得的值作为新的地址,将此地址的内容送至A中 |
- 【例】将外ROM 1234H单元中的数据传送至内RAM的30H单元中。
解法:
MOV DPTR,#1234H ;将16位立即数1234H送至数据指针寄存器
MOV A,#00H ;将立即数00H送至A中
MOVC A,@A+DPTR ;将DPTR中的16位地址和A中的内容相加得新地址,将此地址单元中的内容送至A中
MOV 30H,A ;将A中的数据传送至内RAM的30H单元中
4.数据交换指令(5条)XCH XCHD SWAP
- 1)半字节数据交换指令(2条)
汇编语言指令 | 机器码 | 指令功能 |
---|---|---|
SWAP A | 1100 0100 | 将A的高四位和低四位交换 |
XCHD A, @Ri | 1101 011i | Ri为R0或R1,将Ri所指单元的低4位与A的低4位互换,高4位不变 |
注:XCHD A, @Ri 指令对P标志位有影响。
- 2)整字节交换指令(3条)
汇编语言指令 | 机器码 | 指令功能 |
---|---|---|
XCH A,Rn | 1100 1rrr | Rn为R0~R7之一,将工作寄存器Rn的内容和A的内容交换 |
XCH A,direct | 1100 0101 direct | 将 direct单元内容和A的内容交换 |
XCH A,@Ri | 1100 011i | Ri为RO或R1,将Ri所指单元的内容和A的内容互换 |
- 例1.A中为1110 0110,则执行SWAP A 后,A中为0110 1110。
- 例2.已知(A)=12H、(R1)=30H、(30H)=34H,分析指令执行的结果。
- XCHD A, RI
解:(A)=14H、(30H)=32H,R1内容仍然保持不变。
- 例3.已知(A)=12H、(R1)=30H、(30H)=34H,分析指令执行的结果。
- XCH A. @ RI
解:(A)=34H、(30H)=12H,R1内容保持不变。
5.堆栈操作指令(2条)PUSH POP
汇编语言指令 | 机器码 | 指令功能 |
---|---|---|
PUSH direct | 1100 0000 direct | SP←(SP)+1 (SP)←(direct) |
POP direct | 1101 0000 direct | direct←((SP)) SP←(SP)-1 |
- PUSH DPH:先将SP加1,再将数据指针高位DPH推入堆栈SP+1单元;
- PUSH DPL:先将SP加1,再将数据指针低位DPL推入堆栈SP+1单元;
- PUSH direct:先将SP加1,再将direct所指单元内容推入SP+1所指的堆栈单元;
- POP direct:先将SP单元的内容弹出到 direct单元,再将SP减1;
- POP DPH:先将栈顶SP的内容弹出到数据指针的高8位DPH,再将SP减1;
- POP DPL:先将栈顶SP的内容弹出到数据指针的低8位DPL,再将SP减1。
- 例.分析下面程序的执行结果,假设(30H)=55H,(40H)=AAH。
PUSH 30H
PUSH 40H
POP 30H
POP 40H
解:程序执行后(30H)=AAH,(40H)=55H
注意: 堆栈操作指令的操作数只能使用直接寻址,直接地址不能是寄存器名,因此应注意指令的书写格式。
- 例如:
- PUSH ACC ;(不能写成PUSH A)
- POP 00H ; (不能写成POP R0)
2.算术运算指令
- 算术运算指令主要完成加、减、乘、除四则运算,以及加1、减1、BCD码调(十进制调整)指令整等。
- 加减运算指令的两个操作数中,目的操作数必须为累加器A;源操作数可以为Rn或@Ri(片内RAM)以及direct,或是#data,大多数都要影响到程序状态字PSW,乘除指令不影响AC标志位。
以下8条指令对PSW中的所有标志位均产生影响!!!
- 不带进位的加法指令(4条)
汇编语言指令 | 举 例 | 指令功能 |
---|---|---|
ADD A , #data | ADD A,#23H | 将立即数23H和A相加,结果送至A |
ADD A, direct | ADD A,40H | 将40H单元的内容和A相加,结果送至A |
ADD A , Rn | ADD A,R3 | 将A的内容和R3的内容相加,结果送至A |
ADD A , @Ri | ADD A,@R0 | 将A的内容和R0所指的片内RAM单元的内容相加,结果送至A |
例.分析下面的程序段的功能。
MOV A,#85H
ADD A,#97H
MOV 50H,A
解:
1000 0101 ===> 85H
+ 1001 0111 ===> 97H
---------------
1 0001 1100 ===> 11EH
解析:指令的功能是将85H和97H相加,并把相加的结果传送到50H单元中,且相加后的进位标志Cy的为1
- 加法指令影响PSW的进位标志Cy。如果最高位(D7)有进位,则Cy=1;否则Cy=0。
- 例如,在85H+97H后最高位有进位,(Cy)=1。
- 如果低4位有进位(即D3向D4进位),则辅助进位标志AC=1,否则AC=0。
- 如果相加以后,D7、D6中只有一位有进位则溢出标志OV=1;若D7、D6中均有进位或均无进位,则溢出标志OV=0;
- 若A中“1”的个数为偶数,则P=0,否则,P=1。
【例1】请分析执行如下程序段后A、Cy、AC、OV的结果。
1)MOV A,#00110110B
ADD A,#00110101B
解:指令执行后 (A)=6BH、(Cy)=0、(AC)=0、(OV)=0
2)MOV A,#11010001B
ADD A,#01011001B
解:指令执行后 (A)=2AH、(Cy)=1、(AC)=0、(OV)=0
3)MOV A,#10010010B
ADD A,#11001001B
解:指令执行后 (A)=5BH、(Cy)=1、(AC)=0、(OV)=1
4)MOV A,#0110011B
ADD A,#00110110B
解:指令执行后 (A)=9DH、(Cy)=0、(AC)=0、(OV)=1
- 带进位的加法指令(4条)
汇编语言指令 | 举 例 | 指令功能 |
---|---|---|
ADDC A , #data | ADDC A,#23H | A←(A)+data+( Cy) |
ADDC A, direct | ADDC A,40H | A←(A)+ (direct) +( Cy) |
ADDC A , Rn | ADDC A,R3 | A←(A)+(Rn) +( Cy) |
ADDC A , @Ri | ADDC A,@R0 | A←(A)+((Ri)) +( Cy) |
- 与ADD指令的唯一区别是:ADDC指令除了降至零中规定的两个操作数相加外,还要加上进位标志位Cy的值。此处的Cy的值是指令执行前的进位标志位的内容,不是相加后产生的Cy的值。
【例2】已知当前(Cy)=1,分析下列指令执行后,A与PSW相关标志位的结果。
MOV A,#85H
ADDC A,#97H
解:(A)=1DH、(Cy)=1、(AC)=0、(OV)=1、(P)=0
【例3】编写程序,将内RAM 30H与50H为起始单元的单元2B无符号数相加,并将结果存放到30H为起始地址的区域中。设30H、50H是操作数的低字节。
解:
MOV A,30H
ADD A,50H
MOV 30H,A
MOV A,31H
ADDC A,51H
MOV 31H,A
MOV A,#00H
ADDC A,#00H
MOV 32H,A
【例4】将内RAM 20H单元、21H单元、22H单元中的三个无符号数相加,并将和存入R0(高位)与R1(低位)。
解:
MOV A,20H ;把20H单元内容存入A
ADD A,21H ;把21H单元的内容和A中单元内容(即20H)相加
MOV R1,A ;将前两个数相加的低位存入R1
MOV A,#00H ;给A赋值为0
ADDC A,#00H ;将前两个数相加的进位存入A
MOV R0,A ;将前两个数相加的高位(进位)存入R0
MOV A,R1 ;将前两个数相加的低位存入A
ADD A,22H ;前两个数相加的低位与第三个数相加
MOV R1,A ;三个数和的低位存入R1
MOV A,#00H ;给A赋值为0
ADDC A,R0 ;第二次加法的进位与第一次加法的高位(R0中的数)相加
MOV R0,A ;高位和存入R0
- 带借位的减法指令(4条)
汇编语言指令 | 指令功能 | 举 例 |
---|---|---|
SUBB A , #data | A←(A)-data- (Cy) | SUBB A , #10H |
SUBB A, direct | A←(A) - (direct) - (Cy) | SUBB A, 50H |
SUBB A , Rn | A←(A) - (Rn) - (Cy) | SUBB A , R3 |
SUBB A , @Ri | A←(A) - ((Ri)) - (Cy) | SUBB A , @R0 |
- MCS-51指令系统中没有不带借位的减法,因此要实现不带借位的减法,需在执行SUBB指令前,应使用指令CLR C 对Cy清零。
- 它对PSW中的所有标志位均产生影响。
【例】.已知(Cy)=1,分析下面指令的执行结果。
MOV A,#79H
SUBB A,#56H
解:
0111 1001
- 0101 0110
----------------
0010 0010
指令执行后,累加器A的内容是22H,(Cy)=0、(AC)=0、(OV)=0、(P)=0
- 十进制调整指令(1条)
汇编语言指令 | 指令功能 | 举 例 |
---|---|---|
DA A | 将A的内容调整为正确的BCD码 | DA A |
- 十进制调整指令是一条专门用于对8421 BCD码加法结果进行调整的指令,它跟在加法指令ADD或ADDC后面,对BCD码数的和进行BCD码修正。
- BCD码调整的原则:
- ① 若累加器A的低4位大于9或(AC)=1,则(A)=(A)+06H;
- ② 若累加器A的高4位大于9或(Cy)=1,则(A)=(A)+60H;
- 它对PSW中除OV之外的的所有标志位均产生影响。
- 另外,十进制调整指令不能对减法指令进行修正。BCD码减法必须采用BCD补码运算法则,变减法为补码加法(被减数+减数的补码,单字节减数的补码=9AH-减数),然后对其进行十进制调整来实现。
【例】试编写程序求68H和99H这两个数的BCD码之和。
解:
MOV A,#68H ;(A)=68H
MOV R0,#99H ;(R0)=99H
ADD A,R0
;未调整时 (A)=01H,(Cy)=1,(AC)=1
DA A
;调整之后(A)=67H,(Cy)=1,结果为167,正确
- 加1指令(5条)
汇编语言指令 | 指令功能 | 举 例 |
---|---|---|
INC A | A←(A)+1 | INC A |
INC direct | direct←(direct)+1 | INC 30H |
INC Rn | Rn←(Rn) +1 | INC R4 |
INC @Ri | (Ri)←((Ri))+1 | INC @R0 |
INC DPTR | DPTR←(DPTR)+1 | INC DPTR |
- 它只对PSW中的P标志位产生影响。
【例】编写程序,将内RAM 30H为起始地址的3个无符号数相加,并将结果(假设结果小于100H)存放到40H单元中。
MOV A,#00H
MOV R0,#30H
ADD A,@R0
INC R0
ADDC A,@R0
INC R0
ADDC A,@R0
MOV 40H,A
- 减1指令(4条)
汇编语言指令 | 指令功能 | 举 例 |
---|---|---|
DEC A | A←(A)-1 | DEC A |
DEC direct | direct←(direct) -1 | DEC 50H |
DEC Rn | Rn←(Rn) -1 | DEC R4 |
DEC @Ri | (Ri)←((Ri)) -1 | DEC @R1 |
- 它只对PSW中的P标志位产生影响。
【例】编程实现DPTR减1的运算。
解:由于减1指令中没有DPTR减1的指令,因此需要将DPTR拆分为DPH 和DPL来进行操作。
CLR C ;将Cy清零
MOV A,DPL ;将数据指针的低8位送入A
SUBB A,#01H ;将A的内容减1送入A
MOV DPL,A ;将A的内容减1送入DPL
MOV A,DPH ;将数据指针的高8位送入A
SUBB A,#00H ;将A的内容减0,再减去低位的借位送入A
MOV DPH,A ;将A中得到的最终结果送入DPH
- 乘除指令(2条)
汇编语言指令 | 机器码 | 指令功能 |
---|---|---|
MUL AB | 1010 0100 | (B)(A)←(A) (B) |
DIV AB | 1000 0100 | (A)←(A)/(B) (B)←(A)mod(B) |
- 一条乘法指令只能完成2个8位无符号数相乘,乘数和被乘数分别放在A和B寄存器中,乘积的高8位放在B寄存器中、低8位放在累加器A中;
- 一条除法指令只能完成2个8位无符号数相除,被除数和除数分别存放在A和B寄存器中,商存放在A中,余数存放在B中。
【例】分析下面指令的执行结果
MOV A,#36H
MOV B,#03H
MUL AB
解:
0011 0110
x 0000 0011
---------------
0011 0110
0 0110 110
---------------
0 1010 0010
结果:(A)=0A2H、(B)=00H、(Cy)=0、(OV)=0、(P)=1
【例】分析下面指令执行结果
MOV A,#87H
MOV B,#0CH
DIV AB
解:(A)=0BH、(B)=03H、(Cy)=0、(OV)=0、(P)=1
3.逻辑运算和移位指令
- 常用的逻辑运算和移位类指令有: 逻辑与、逻辑或、逻辑异或、循环移位、清零、求反等指令,它们的操作数都是8位的。
- 逻辑运算都是按位进行的。
- 逻辑运算和移位指令中,以A为目的操作数的指令影响P标志位,带进位的循环移位指令影响Cy和P标志位,其余均不影响PSW各标志位。
- 逻辑与运算指令(6条)
汇编语言指令 | 指令功能 | 举 例 |
---|---|---|
ANL A ,#data | A←(A) data | ANL A ,#0F0H |
ANL A , direct | A←(A) (direct) | ANL A , 50H |
ANL A , Rn | A←(A) (Rn) | ANL A , R3 |
ANL A , @Ri | A←(A) ((Ri)) | ANL A , @R1 |
ANL direct ,A | direct←(A) (direct) | ANL 40H ,A |
ANL direct,#data | direct←(direct) (data) | ANL 55H,#55H |
注:逻辑与的规则为“见0为0,全1为1”。
- 逻辑或运算指令(6条)
汇编语言指令 | 指令功能 | 举 例 |
---|---|---|
ORL A, #data | A←(A) data | ORL A ,#0F0H |
ORL A, direct | A←(A) (direct) | ORL A , 50H |
ORL A, Rn | A←(A) (Rn) | ORL A , R3 |
ORL A, @Ri | A←(A) ((Ri)) | ORL A , @R1 |
ORL direct, A | direct←(A) (direct) | ORL 40H ,A |
ORL direct, #data | direct←(direct) (data) | ORL 55H,#55H |
注:逻辑或的规则为“见1为1,全0为0”。
- 逻辑异或运算指令(6条)
汇编语言指令 | 指令功能 | 举 例 |
---|---|---|
XRL A, #data | A←(A) data | XRL A ,#0F0H |
XRL A, direct | A←(A) (direct) | XRL A , 50H |
XRL A, Rn | A←(A) (Rn) | XRL A , R3 |
XRL A, @Ri | A←(A) ((Ri)) | XRL A , @R1 |
XRL direct, A | direct←(A) (direct) | XRL 40H ,A |
XRL direct, #data | direct←(direct) (data) | XRL 55H,#55H |
注:逻辑异或的规则为“相同为0,相异为1”。
- 循环移位指令(4条)
- MCS-51单片机的循环移位指令共有4条:
- ①不带进位的循环左移指令RL;
- ②不带进位的循环右移指令RR;
- ③带进位的循环左移指令RLC;
- ④带进位的循环右移指令RRC。
- 它们都只能对累加器A进行移位。
- 使用移位指令可以实现乘法或除法:
- 左移一位相当于乘2;
- 右移一位相当于除2。
汇编语言指令 | 指令功能 |
---|---|
RL A | ![]() |
RR A | ![]() |
RLC A | ![]() |
RRC A | ![]() |
- 累加器清零与取反指令(2条)
汇编语言指令 | 指令功能 |
---|---|
CLR A | A←0 |
CPL A | A←(A) |
- 利用取反,可以进行求补操作,即对要求补的数先取反再加 1。
4.控制转移指令
- 计算机在运行的过程中,一般通过程序计数器PC的自动加1实现顺序执行,有时候对于较复杂的操作,需要通过强迫改变PC值的方法来进行程序的分支转移,这就需要用到控制转移指令。
- 控制转移指令的功能——通过改变程序计数器PC中的内容,控制程序执行的流程,实现程序分支转向。
- MCS-51单片机提供了17条控制转移指令。
- 无条件转移指令(4条)
汇编语言指令 | 机器码 | 指令功能 |
---|---|---|
LJMP addr16 | 0000 0010 addr15~8 addr7~0 | PC←addr15~0 |
AJMP addr11 | A10A9A80 0001 A7~A0 | PC←(PC)+2, PC 10~0←addr11 |
SJMP rel | 1000 0000 rel | PC←(PC)+rel |
JMP @A+DPTR | 0111 0011 | PC←(DPTR)+(A) |
1)长转移指令(LJMP addr16)
- 长转移指令提供了16位的目标转移地址,其功能是把指令码中的16位转移目标地址送入PC,因此这条指令可以跳转到64KB ROM的任意位置。
- 为了方便,程序中addr16通常采用符号地址表示,汇编时再被汇编成16位二进制地址,所以该指令的使用格式通常为:
LJMP 标号
2)绝对转移指令(AJMP addr11)
-
这条指令可以在该指令的下一条指令的同一个2KB区域(211)内跳转。PC15~PC11用于把64KB的ROM划分为32个区域,相当于32个页(每页2KB,由PC10~PC0确定)。
-
指令执行时,用指令码中的11位地址替换当前PC值(AJMP的下一条指令的地址)的低11位,当前PC值的高5位不变。
-
在实际程序设计中,addr11也常用标号代替,程序汇编时再被自动汇编成对应的11位地址。该指令的使用格式通常为:
AJMP 标号
3)相对(短)转移指令(SJMP rel)
- 执行本指令时,转移的目标地址为(PC)=(PC)+rel,rel是一个用补码表示的8位带符号二进制数,范围为-128~+127,负数表示向前(地址变小方向)转移,正数表示向后(地址变大方向)转移。
- 程序中,rel常用符号地址表示,因此,该指令的常用格式为:
SJMP 标号
- 机器汇编时由汇编程序自动计算出rel的值,手工汇编时,需要人工计算rel的值:
rel=目标标号的地址-当前的PC值
- 在编程中,经常使用短转移指令SJMP和绝对转移指令AJMP,以便生成浮动代码。
- 另外,MCS-51单片机无专用的停机指令,若要求动态停机(不想单片机继续往下执行)可用SJMP指令,常用方法有以下两种:
- 方法1:
HERE :SJMP HERE
- 方法2:
SJMP $
- 方法1:
4)间接(散)转移指令(JMP @A+DPTR)
- 功能:把累加器A中的8位无符号数与数据指针DPTR中的16位数相加,其结果送入PC,作为转移的目标地址,利用这条指令能实现程序的散转。
- 散转指令可以在不需要判断的情况下实现程序的多分支转移。
- 例2. 分析下面程序的执行过程。
MOV DPTR,#TAB ;将TAB所代表的地址送入DPTR
MOV A,R1 ;从R1中取数送入A
MOV B,#2 ;给B赋值为2
MUL AB ;A中的数(即原来R1中的数)乘以2
JMP @A+DPTR ;跳转
TAB: SJMP S0 ;跳转表格,S0处理程序
SJMP S1 ;S1处理程序
SJMP S2 ;S2处理程序
- 条件转移指令(8条)
-
条件转移指令的功能:在规定的条件满足时进行程序转移,否则程序往下顺序执行。
-
MCS-51单片机中,条件转移指令有:
- 累加器A判零转移指令(JNZ/JZ)
- 比较不相等转移指令(CJNE)
- 减1不为0转移指令(DJNZ)(循环控制指令)
1)累加器A判零转移指令(2条)
汇编语言指令 | 机器码 | 指令功能 |
---|---|---|
JZ rel | 0110 0000 rel | 若(A)=0,则转移(PC)←(PC)+rel; 若(A)≠0,则顺序执行 |
JNZ rel | 0111 0000 rel | 若(A)≠0,则(PC)←(PC)+rel; 若(A) =0,则顺序执行 |
2)比较转移指令(4条)
汇编语言指令 | 机器码 | 指令功能 |
---|---|---|
CJNE A, direct, rel | 10110101 direct rel | 若(A)=(direct),则顺序执行; 若(A)>(direct),则(PC)←(PC)+rel,Cy= 0; 若(A) <(direct),则(PC)←(PC)+rel,Cy= 1 |
3)减1不为0转移指令(循环控制指令)(2条)
汇编语言指令 | 机器码 | 指令功能 |
---|---|---|
DJNZ Rn, rel | 1101 1rrr rel | (Rn)←(Rn)-1, 若(Rn)≠0则 (PC) ←(PC)+rel 若(Rn)=0则顺序执行 |
- 例3. 编程计算1+2+3+……+10的值。
解:本题目为自然数依次相加,从1加到10,故可以用循环指令来控制循环次数。
程序如下:
MOV R0,#10 ;设置循环次数
CLR A ;累加器清零
LOOP:ADD A,R0 ;循环体
DJNZ R0,LOOP ;控制循环次数
SJMP $ ;结束
- 子程序调用与返回指令(4条)
- 在程序运行时,可以通过调用指令来调用并执行子程序;子程序执行完后,再用返回指令从子程序返回到主程序。
- 为了实现子程序的完整调用,子程序调用指令和返回指令必须成对出现。
- 子程序可以嵌套,即在一个子程序执行过程中可以调用另外的子程序,形成子程序的嵌套。子程序嵌套有利于模块化程序设计。
汇编语言指令 | 机器码 | 指令功能 |
---|---|---|
LCALL addr16 | 0001 0010 addr15~8 addr7~0 | (PC)←(PC)+3, SP←(SP)+1,(SP)←(PC)7~0; SP←(SP)+1,(SP)←(PC)15~8, (PC)15~0←addr16 |
1)长调用指令 LCALL
- 长调用指令,用于调用存放在 64KB 空间任意地方的子程序,本指令不影响 PSW 的各标志位。
- 使用格式为:LCALL 标号(标号即为子程序名)。
2)短调用指令 ACALL
- 该指令的调用范围为 2KB,执行该指令时共完成 2 项操作:
- ① 断点保护,即通过自动入栈,把断点地址((PC)+2 的值)保存起来;
- ② 构造目的地址,即用 addr11 代替当前 PC的低 11 位,而 PC 的高 5 位不变。
- 子程序必须存放在该指令的下一条指令的第一个字节开始 的 2KB 范围内,即同一页内。
- 该指令的使用格式为:ACALL 标号(标号即为子程序名)。
3)子程序返回指令 RET
- 该指令与子程序调用指令成对出现,其功能是从堆栈中取出断点地址,送入 PC,使主程序从断点(调用指令的下一条指令)处继续执行。
4)中断返回指令 RETI
- 中断服务程序是一种特殊的子程序,它是在计算机响应中断时,由硬件完成调用而进入相应的中断服务程序。
- RETI 指令与 RET 指令的区别在于 RETI 在从中断服务程序返回时,还要对相应优先级的中断触发器清 0。无论是 RET 还是 RETI 都是子程序执行的最后一条指令。
- 空操作指令
汇编语言指令 | 机器码 | 指令功能 | 指令字节数 | 机器周期数 |
---|---|---|---|---|
NOP | 0000 0000 | PC←PC+1,空操作 | 1 | 1 |
- 空操作指令不进行任何操作,但要占一个字节的空间,执行时要占用一个机器周期,多用于延时等待或在抗干扰设计中做指令冗余,以提高软件的可靠性。
5.位操作指令
- 位操作指令操作对象是某个可寻址的位,由于位的取值只能是0或1,故位操作指令又称为布尔变量操作指令。
- 位操作指令操作的对象——片内RAM的128个可寻址的位和SFR中11个可位寻址的特殊功能寄存器中的82个可寻址位。
- 位操作指令以进位标志Cy作为位累加器(C),可以实现布尔变量的传送、运算和控制转移等功能。
- 位数据传送指令(2 条)
- 位数据传送可以在可寻址位与位累加器 C 之间进行,以 C 做中介可以实现两个位之间的数据传送。
汇编语言指令 | 指令功能 | 举 例 |
---|---|---|
MOV C ,bit | C← (bit) | MOV C ,20H MOV C ,P0.2 |
MOV bit , C | bit ← © | MOV 20H,C MOV P0.2,C |
- 位状态控制指令(4 条)
- 位状态控制主要是对位置位或复位。
汇编语言指令 | 指令功能 | 举 例 |
---|---|---|
CLR C | C ← 0 | CLR C |
CLR bit | bit ← 0 | CLR 30H CLR EA |
SETB C | C ← 1 | SETB C |
SETB bit | bit ← 1 | SETB 30H SETB EA |
- 位逻辑操作指令(6 条)
- 位逻辑操作有位与、位或、位异或、位取反等,除了位取反指令 CPL bit 外,其余指令均以位累加器 C 为目的操作数,执行结果存入 C,原位的内容不发生变化。
汇编语言指令 | 指令功能 | 机器周期数 |
---|---|---|
ANL C ,bit | C ←© ∧ (bit) | ANL C ,30H |
ANL C ,/bit | C ←© ∧ (bit) | ANL C ,/30H |
ORL C,bit | C ←© ∨ (bit) | ORL C,30H |
ORL C ,/bit | C ←© ∨ (bit) | ORL C ,/30H |
CPL C | C ← © | CPL C |
CPL bit | (bit) ← (bit) | CPL TR0 |
例:用软件实现下图所示的P1.0 ~ P1.3间的逻辑运算。
MOV C,P1.1
ORL C,P1.2
ANL C,P1.0
MOV P1.3,C
- (P1.1 ≥ P1.2) & P1.0
例3.25 设x, y, z为不同的位地址,编程实现(z)=(x) ⊕ (y)
解 析 : M O V C , y ; ( C ) = ( y ) A N L C , / x ; ( C ) = ( y ) ∧ ( x ˉ ) M O V Z , C ; ( z ) = ( C ) = ( y ) ∧ ( x ˉ ) M O V C , x ; ( C ) = ( x ) A N L C , / y ; ( C ) = ( x ) ∧ ( y ˉ ) O R L C , Z ; ( C ) = ( y ) ∧ ( x ˉ ) + ( x ) ∧ ( y ˉ ) M O V Z , C ; ( Z ) = ( y ) ∧ ( x ˉ ) + ( x ) ∧ ( y ˉ ) = ( x ) ⊕ ( y ) \begin{aligned} 解析: &MOV \quad C,y \quad ;(C)=(y) \\ &ANL \quad C,/x \quad ;(C)=(y) ∧ ( \bar{x} ) \\ &MOV \quad Z,C \quad ;(z)=(C)=(y)∧ (\bar{x} )\\ &MOV \quad C,x \quad ;(C)=(x) \\ &ANL \quad C,/y \quad ;(C)=(x) ∧ ( \bar{y} )\\ &ORL \quad C,Z \quad ;(C)=(y) ∧ ( \bar{x} )+(x)∧ (\bar{y} ) \\ &MOV \quad Z,C \quad ;(Z)=(y) ∧ ( \bar{x} )+(x)∧ (\bar{y} )=(x) ⊕ (y)\\ \end{aligned} 解析:MOVC,y;(C)=(y)ANLC,/x;(C)=(y)∧(xˉ)MOVZ,C;(z)=(C)=(y)∧(xˉ)MOVC,x;(C)=(x)ANLC,/y;(C)=(x)∧(yˉ)ORLC,Z;(C)=(y)∧(xˉ)+(x)∧(yˉ)MOVZ,C;(Z)=(y)∧(xˉ)+(x)∧(yˉ)=(x)⊕(y)
- 位条件(控制)转移指令(5 条)
- 位条件(控制)转移指令和前面介绍过的条件转移指令类似,只不过是以位的状态作为 程序转移的判断条件,可以使程序设计更加方便、灵活。
汇编语言指令 | 指令功能 | 举 例 |
---|---|---|
JC rel | 若©=1,则转移(PC)←(PC)+rel ; 否则顺序执行 | JC NEXT |
JNC rel | 若©=0,则转移(PC)←(PC)+rel; 否则顺序执行 | JNC NEXT |
JB bit , rel | 若(bit)=1,则转移(PC)←(PC)+rel; 否则顺序执行 | JB F0,NEXT |
JNB bit , rel | 若(bit)=0,则转移(PC)←(PC)+rel; 否则顺序执行 | JNB F0,NEXT |
JBC bit , rel | 若(bit)=1,则转移(PC)←(PC)+rel,且(bit )←0; 否则顺序执行 | JBC F0,NEXT |
例3.26 求出内RAM30H单元中的数据含1的个数,并将结果存入31H单元。
解:
CLR C ;C清零
MOV R2,#8 ;设置循环次数
MOV R1,#00 ;计数单元清零
MOV A,30H ;把30H单元内容读入A
LOOP:RRC A ; 将(ACC.0)循环移入Cy中
JNC NEXT ;Cy中不为1则转至NEXT
INC R1 ;若Cy为1,则R1内容加1
NEXT:DJNZ R2,LOOP ; 8不够则继续执行移位
MOV 31H,R1 ;将计数结果送入31H单元
SJMP $ ;停机(原地踏步)
END ;结束