跳转至

第2章 MCS-51单片机指令系统

第二章 MCS-51单片机指令系统

常用符号

Rn(n = 0~7):当前选中的工作寄存器组R0~R7。它在片内的地址由PSW中的RS1,RS0确定
Ri(i = 0,1):当前选中的工作寄存器组中可作为地址指针的两个工作寄存器R0,R1
#data:8位立即数,即指令中给出的8位常数
#data16:16位立即数,即指令中给出的16位常数
direct:8位片内RAM(包括SFR)的直接地址
addr11:11位目的地址。用于ACALL和AJMP指令中。目的地址必须放在与下一条指令第一字节同2k字节的程序存储器区地址空间内。
addr16:16位目的地址。用于LCALL和LJMP指令中,它的地址范围是64k字节程序存储器地址空间
rel:8位带符号的偏移量。用于SJMP和所有的条件转移指令中地址偏移量范围在-128~+127(即偏移量用补码形式表示)
bit:片内RAM和SFR的直接寻址位地址
@:间接寻址方式,表示间址寄存器的符号
/:位操作数前缀,表示对该位操作数求反
(x):表示x中内容
((x)):表示x寻址的单元中的内容
←:指令操作流程,将箭头右边的内容送到箭头左边的单元中

寻址方式

立即寻址

寻址空间:程序存储器(ROM)

指令所用到的操作数以指令字节的形式存放在程序存储器

直接寻址

寻址空间:内部RAM的低128字节,特殊功能寄存器(RAM高128字节)

直接寻址是访问SFR的唯一方式。意思是对于52系列单片机,片内RAM高128字节与特殊功能寄存器SFR地址重叠,此时只有直接寻址,才能访问到SFR,如只有寻址80H,才能访问到P0,若要访问RAM高128字节,则只能通过寄存器间接寻址的方式来实现

操作码后面的一个字节是实际操作数地址。这种直接在指令中给出操作数真实地址的方式称为直接寻址。

寄存器寻址

寻址空间:R0~R7(由PSW中RS1、RS0两位的值选定工作寄存器区),A、B、CY(位),DPTR

指令选定的寄存器所存储的内容是实际的操作数

寄存器寻址无需额外空间存储寄存器变量,即寄存器变量不占字节

MOV A,#00H  ;该代码中对A的寻址方式为寄存器寻址,只有以Acc形式出现时,对A的寻址方式为直接寻址。
            ;因此,PUSH、POP指令对A进行出栈、弹栈时,必须要写Acc。因为PUSH、POP只能对direct操作

寄存器间接寻址

寻址空间:内部RAM(@R0,@R1,SP), 外部数据存储器(@R0,@R1,@DPTR)

指令所选中的寄存器内容是实际操作数的地址(而不是操作数)

寄存器间接寻址无需额外空间存储寄存器变量地址,即寄存器变量的地址不占字节

基址寄存器加变址寄存器间接寻址

寻址空间:程序存储器(@A+DPTR,@A+PC)

以DPTR或PC作基址寄存器,A作变址寄存器(存放8位无符号数),两者相加以形成16位程序存储器地址作操作数地址

相对寻址

用于程序控制,利用指令修正PC指针的方式实现转移。即以程序计数器PC的内容为基地址,加上指令中给出的偏移量rel,所得结果为转移目标地址。

偏移量rel是一个8位有符号补码数,范围-128~+127。

正向跳转:rel = 目的地址 - 源地址 - 2

反向跳转时,目的地址小于源地址,rel用负数的补码表示rel=(目的地址 -(源地址 + 2))补

位寻址

寻址空间:片内RAM的20H~2FH,SFR中12个能被8整除的字节

位寻址与直接寻址中的字节地址形式完全一样,是访问“字节”还是访问“位”完全以指令来区分

CLR C
SETB C

数据传送类指令

重点的4+3+5+3种MOV要给一个总结的话,就是:所有数据迁移指令,只有direct允许全部方式,其他

目的操作数不允许使用同个或同组寄存器(详细说就是,A不允许使用A,@Ri不允许使用@Ri与Rn,Rn

不允许使用@Ri与Rn);

查表MOVC牢记MOVC A, @A+DPTR

MOVC查表指令(2条)(必须使用累加器A,访问ROM)

MOVC A, @A+DPTR ;  (A) <- ((A) + (DPTR))
MOVC A, @A+PC ;  (A) <- ((A) + (PC))

此时PSEN信号有效

MOVX传送类指令(4条)(必须使用累加器A,使用寄存器间接寻址方式,访问片外RAM)

MOVX A, @DPTR ; (A) <- ((DPTR))
MOVX @DPTR, A ; ((DPTR)) <- (A)
MOVX A, @Ri ; (A) <- ((Ri))
MOVX @Ri, A ; ((Ri)) <- (A)

向DPTR/寄存器读数据时,RD信号有效;向DPTR/寄存器写数据时,WR信号有效

交换指令(5条)(前3条为字节交换,后2条为半字节交换)

XCH A, Rn ; (A) <-> (Rn)
XCH A, direct ; (A) <-> (direct)
XCH A, @Ri ; (A) <-> ((Ri))
XCHD A, @Ri ; (A3 ~ 0) <-> ((Ri)3 ~ 0)   半字节交换
SWAP A ; (A3 ~ 0) <-> (A7 ~ 4)  交换低四位和高四位

堆栈类

PUSH direct ; (SP) <- (SP) + 1
            ; ((SP)) <- (direct)
POP direct ; (direct) <- ((SP))
           ; (SP) <- (SP) - 1

注意,若想要对累加器A进行压栈弹栈操作,必须写PUSH Acc。看到Acc时,才是直接寻址。

算数运算类指令

加法指令(4条)

ADD A, Rn ; (A) <- (A) + (Rn)
ADD A, direct ; (A) <- (A) + (direct)
ADD A, @Ri ; (A) <- (A) + ((Ri))
ADD A, #data ; (A) <- (A) + #data

带进位加法指令(4条):

ADDC A, Rn ; (A) <- (A) + (Rn) + (CY)
ADDC A, direct ; (A) <- (A) + (direct) + (CY)
ADDC A, @Ri ; (A) <- (A) + ((Ri)) + (CY)
ADDC A, #data ; (A) <- (A) + #data + (CY)

带借位减法指令(4条)(这个借位是指低位从当前这里借走,而不是自己从高位那里借来。因为运算是从低位算到高位的)

SUBB A, Rn ; (A) <- (A) - (Rn) - (CY)
SUBB A, direct ; (A) <- (A) - (direct) - (CY)
SUBB A, @Ri ; (A) <- (A) - ((Ri)) - (CY)
SUBB A, #data ; (A) <- (A) - #data - (CY)

乘法指令(仅1条合法,必须一字不差,空格数除外):

MUL AB ; (B)(A) <- (A) * (B)

除法指令(仅1条合法,必须一字不差,空格数除外):

DIV AB ; (A) <- (A) / (B) 的商
       ; (B) <- (A) / (B) 的余

自增指令(5条):

INC A ; (A) <- (A) + 1
INC Rn ; (Rn) <- (Rn) + 1
INC direct ; (direct) <- (direct) + 1
INC @Ri ; ((Ri)) <- ((Ri)) + 1
INC DPTR ; (DPTR) <- (DPTR) + 1

自减指令(4条)(DPTR不允许自减):

DEC A ; (A) <- (A) - 1
DEC Rn ; (Rn) <- (Rn) - 1
DEC direct ; (direct) <- (direct) - 1
DEC @Ri ; ((Ri)) <- ((Ri)) - 1

无DPTR减1指令。若要做DPTR-1,必须要用一段程序实现。

CLR   C
MOV   A,#DPL    
SUBB  A,#1  
MOV   DPL,A 
MOV   A,DPH 
SUBB  A,#0
MOV   DPH,A

十进制调整指令(仅1条合法,必须一字不差,空格数除外):

DA A

这条指令是在进行BCD码运算时,跟在ADD和ADDC指令之后,将相加后存放在累加器A中的结果进行修正。

不能用于BCD码减法结果调整

逻辑操作类指令

循环移位指令(4条)

RL   A   ; A的内容循环左移 
RR   A   ; A的内容循环右移 
RLC  A   ; A的内容带C位循环左移  
RRC  A   ; A的内容带C位循环右移

左移/右移可以和乘/除等效

求反指令(1条)

CPL   A 

清0指令(1条)

CLR   A 

逻辑与指令(6条)

ANL   A,#data   
ANL   direct,#data  
ANL   A,Rn  
ANL   A,direct  
ANL   direct,A  
ANL   A,@Ri

逻辑或指令(6条)

ORL   A,#data   
ORL   direct,#data  
ORL   A,Rn  
ORL   A,direct  
ORL   direct,A  
ORL   A,@Ri

逻辑异或指令(6条)

XRL   A,#data   
XRL   direct,#data  
XRL   A,Rn  
XRL   A,direct  
XRL   direct,A  
XRL   A,@Ri

控制转移类指令

无条件转移指令(4条)

LJMP跳转范围为64K

AJMP为绝对跳转指令,跳转11位地址,执行前PC会先加2,跳转范围为2K

SJMP为短跳转指令,跳转范围是-128——+127

LJMP   addr16   ; (PC) ← addr16,长跳转指令,跳转范围64K   
AJMP   addr11   ;  (PC) ← (PC)+ 2,                       
                ; (PC(10-0)) ← addr11,(PC(15-11))保持不变                       
                ; 绝对跳转指令,跳转范围2K                     
SJMP   rel      ;  (PC) ← (PC)+ 2 + rel                       
                ; 短跳转,跳转范围为-128~+127    
JMP    @A+DPTR  ; (PC) ←(A)+ (DPTR),散转指令                       
                ; A的内容为8位无符号数

条件转移指令(8条)

理解:

JZ——jump if zero

JNZ——jump if not zero(这两个后面都不会跟变量,所以默认的是累加器A)

CJNE——compare jump not equal,先对两个变量做减法,改变进位位,有借位C为1,无借位C为0;然后比较两个变量如果不等则跳转

DJNZ——decrement jump if not zero

JZ    rel   ; A=0时跳转,(PC) ← (PC)+ 2 + rel
            ; A≠0时不跳转,继续顺序向下执行,即(PC) ← (PC) + 2
JNZ   rel   ; A≠0时跳转,(PC) ← (PC)+ 2 + rel
            ; A=0时不跳转,继续顺序向下执行,即(PC) ← (PC) + 2
CJNE  A,direct,rel  ;  (A)≠(direct)时跳转,(PC) ← (PC) + 3 + rel
                     ;  (A) = (direct)不跳转,(PC) ← (PC) + 3 
                     ; 会影响进位标志,(A)>(direct)时, (C) ← 0
                     ;(A)<(direct)时, (C) ← 1                        
CJNE  A,#data,rel
CJNE  Rn,#data,rel
CJNE  @Ri,#data,rel
DJNZ  Rn,rel        ; (Rn)←(Rn)- 1
                    ; 若(Rn)≠0则跳转, (PC) ← (PC)+ 2 + rel
                    ; 若(Rn)=0则不跳转,(PC) ← (PC)+ 2

DJNZ  direct,rel  

子程序调用及返回指令(4条)

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))              
                ; (PC(10-0)) ← addr11,(PC(15-11))保持不变
RET    ; (PC(15~8)) ← ((SP)) , (SP) ← (SP) - 1       
       ; (PC(7~0)) ← ((SP)) ,  (SP) ← (SP) - 1
RETI   ; (PC(15~8)) ← ((SP)) , (SP) ← (SP) - 1        
       ; (PC(7~0)) ← ((SP)) ,  (SP) ← (SP) - 1        
       ; 中断子程序返回,除具有RET的功能外,还可以恢复中断逻辑
NOP    ;  (PC) ← (PC) + 1(延时用)  

RET和RETI不能互换使用

位操作类指令

在指令中,位地址的表达方式有以下4种:

1.直接用位地址表示:如 0D5H

2.点操作符方式:PSW.5

3.位名称方式:F0

4.用户使用伪指令事先定义的符号地址:USER-FLG bit F0

位数据传送指令(2条)

MOV   C,bit ; (C) ← (bit)
MOV   bit,C ; (bit) ← (C)
            ; bit表示可位寻址的各位(221位)的位地址

位状态控制指令(6条)

CLR   C      ; 清0
CLR   bit    ; 清0
CPL   C      ; 求反
CPL   bit    ; 求反
SETB  C      ; 置1
SETB  bit    ; 置1

位逻辑运算指令(4条)

ANL   C,bit  ; 与
ANL   C,/bit ; 与    
ORL   C,bit  ; 或
ORL   C,/bit ; 或

位条件转移指令(5条)

JC   rel        ;(C)=1,跳。 (PC) ← (PC) + 2 + rel
                ;(C)=0,不跳。 (PC) ← (PC) + 2 ,顺序执行
JNC  rel        ;(C)=0,跳。 (PC) ← (PC) + 2 + rel
                ;(C)=1,不跳。 (PC) ← (PC) + 2
JB   bit,rel    ; bit =1,跳。 (PC) ← (PC) + 3 + rel
                ; bit =0,不跳。 (PC) ← (PC) + 3
JNB  bit,rel    ; bit =0,跳。 (PC) ← (PC) + 3 + rel
                ; bit =1,不跳。 (PC) ← (PC) + 3
JBC  bit,rel    ; bit =1,则(bit)← 0, (PC) ← (PC) + 3 + rel
                ; bit =0,则顺序执行,(PC) ← (PC) + 3

伪指令

ORG、END、DB、DW、DS

EQU:把一个数据或汇编符号用自定义的字符代替 被定义的字符名称可用作数据地址、位地址、寄存器或立即数

DATA:把数据地址或代码地址用自定义的字符替代(DATA是数据不是地址)

BIT:把位地址用自定义的字符替代

指令的字节和周期

字节的判断:执行这件事需要一个字节,指令中含有的变量需要占用对应的字节(寄存器寻址、寄存器间接寻址不占字节,DPTR的16位数据占用两个字节)

共分为单字节、双字节、三字节指令三种

按照周期可分为单周期、双周期、四周期三种,四周期指令只有乘除,三字节一定是双周期,其他的似乎只能背了……