单片机的学习总结(三)

4、指令

指令(Instruction):指示CPU执行某种规定操作的命令。
指令集或指令系统(Instruction Set):某一种CPU所能执行的全部指令的集合。

指令的组成

指令由操作码和操作数组成。其中操作码决定CPU执行何种操作。操作数是指参与运算的数。操作数及操作对象可以是一个数,也可以是数所在的地方。

寻址方式

51单片机有7种寻址方式。
1、立即寻址
2、直接寻址
3、REG寻址
4、REG间接寻址
5、变址寻址
6、相对寻址
7、位寻址

立即寻址

操作数包含在指令字节中。 紧跟在操作码后面,存放于ROM中 。跟在指令操作码后面的数就是参加运算的数, 称该操作数为立即数。
例:MOV A,#01H ;

直接寻址

在指令中直接给出操作数的地址, 这种寻址方式就属于直接寻址方式。在这种方式中, 指令的操作数部分直接是操作数的地址。
例:MOV A,30H;

REG寻址

在该寻址方式中, 参加操作的数存放在寄存器里。
例:MOV A,R0 ;

REG间接寻址

在这种寻址方式中, 寄存器的内容为操作数的地址
例:MOV A,@ R0 ;
寄存器间接寻址只能使用寄存器R0、R1 作为地址指针,寻址内部RAM区的数据; 当访问外部RAM时, 可使用R0、 R1及DPTR作为地址指针。 寄存器间接寻址符号为“@”。

变址寻址

用于访问程序存储器中的数据表格, 它以寄存器DPTR或PC的内容为基本地址, 加上累加器A里的地址偏移量,作为操作数的地址。
例: MOVC A, @A+DPTR
MOVC A, @ A+PC
注意:只能从ROM中读数据,不可能对ROM写入

相对寻址

相对转移指令执行时,是以当前的PC值再加上指令中规定的偏移量rel而构成实际的转移地址。这里说的当前PC值是指执行完相对转移指令后的PC值。
例:SJMP rel
目的地址 = 源地址 + 转移指令字节数 + rel

位寻址

该种寻址方式中, 操作数是内部RAM单元中某一位的信息。
例:MOV C,30H ;

5、指令系统

数据传送类

数据传送类指令可以实现片内RAM之间;A与片外RAM及ROM之间的数据传送,不影响标志位。

内部RAM数据传送指令

(1)以累加器A为目的操作数的数据传送指令
MOV A, #data8 ; A ← data8
MOV A, direct ; A ← (direct)
MOV A, Rn ; A ← (Rn)
MOV A, @Ri ; A ← ((Ri))
(2)以寄存器Rn为目的操作数的数据传送指令
MOV Rn, A ; Rn ← (A)
MOV Rn, #data8 ; Rn ← data8
MOV Rn, direct ; Rn ← (direct)
(3)以直接地址为目的操作数的数据传送指令
MOV direct, A ; direct ← (A)
MOV direct, #data ; direct ← data
MOV direct1, direct2 ; direct1 ← direct2
MOV direct, Rn ; direct ← (Rn)
MOV direct1, @Ri ; direct1 ← ((Ri))
(4)以间接地址@Ri为目的操作数的数据传送指令
MOV @Ri, A ; (Ri) ← (A)
MOV @Ri, #data8 ; (Ri) ← data8
MOV @Ri, direct ; (Ri) ← (direct)
(5)以DPTR为目的操作数的数据传送指令
MOV DPTR, #data16 ; DPTR ← data16
唯一一条16位立即数传送指令,高8位送DPH,低8位送DPL

访问外部RAM的数据传送指令

必须采用寄存器间接寻址方式,要用到MOVX指令。
MOVX A, @DPTR ; A ← ((DPTR))
MOVX @DPTR , A ; (DPTR) ← A
MOVX A, @Ri ; A ← ((Ri))
MOVX @Ri , A ; (Ri) ← A

例:将片外RAM的2020H单元内容送入片外RAM的1000H单元中。
MOV DPTR,#2020H;
MOVX A,@DPTR;
MOV DPTR,#1000H;
MOVX @DPTR,A;

ROM向累加器A传送数据指令

源操作数为变址寻址方式
MOVC A, @A+DPTR ; A ← ((DPTR)+(A))
MOVC A, @A+PC ; A ← ((DPTR)+(PC))

例:在外部ROM中2000H单元开始存放(0~9)的平方值0,1,4,9,…,81,要求根据累加器A中的值,来查找所对应的平方值,并存入30H单元中。
MOV DPTR,#2000H;
MOVC A,@DPTR;
MOV 30H,A;

数据交换指令

整字节交换指令:
XCH A, Rn ; (A) ↔ (Rn)
XCH A, direct ; (A) ↔ (direct)
XCH A, @Ri ; (A) ↔ (Ri)
半字节交换指令
XCHD A, @Ri ; A和Rn的低四位互换
累加器高低半字节交换指令
SWAP A ; (A)7~4 ↔ (A) 3~0

堆栈操作指令

PUSH direct ;SP ← (SP)+1, (SP) ← (direct)
POP direct ;direct ← ((SP)), SP ← (SP)-1
注意:进栈、出栈指令只能以直接寻址方式来取得操作数,应注意指令的书写格式。例如把累加器A的内容送入堆栈,应使用指令:PUSH ACC
这里ACC表示累加器A的直接地址E0H
再比如:PUSH R0 ;是错误格式
应写为:PUSH 00H ;00H是R0的地址

算术运算类

加法运算

1) ADD A, #data8\direct@Ri\Rn
2) ADDC A, #data8\direct@Ri\Rn ;要加上Cy的值
3) INC A\direct@Ri\Rn\DPTR 不影响标志位

例:将内部RAM中20H,21H,22H三个单元中的无符号数相加,然后把和存入R0(高位)和R1(低位)寄存器中。
CLR C;
MOV A,20H;
ADD A,21H;
MOV R1,A
MOV A,#00H
ADDC A,#00H;记得此时A要清零
MOV R0,A
MOV A,R1;
ADD A,22H;
MOV R1,A
MOV A,R0;
ADDC A,#00H;
MOV R0,A;

减法运算

1) 带借位的减法:
SUBB A , #data8\direct@Ri\Rn
2) DEC A\direct@Ri\Rn 不影响标志位

乘法运算

两个8位无符号数相乘 MUL AB
1、将累加器A的内容与寄存器B的内容相乘, 乘积的低8 位存放在累加器A中, 高 8 位存放于寄存器B中。
2、对标志位的影响:
Cy=0 执行乘法指令后,进位标志Cy一定被清零; P 由A中1的个数决定

除法运算

两个8位无符号数相除 DIV AB
1、将累加器 A中的内容除以寄存器 B中的8位无符号整数, 所得商的整数部分存放在累加器A中, 余数部分存放在寄存器 B中。
2、对标志位的影响:
Cy=0 进位标志Cy一定被清零; P 由A中1的个数决定;OV溢出标志只是在除数B=0时才置1,其他情况OV = 0
下面用一个例子来加深印象。
例:被乘数为16位无符号数,乘数为8位无符号数,编制相应的乘法程序。被乘数的地址为20H和21H(低8位先存),乘数地址为30H,积存入R2,R3,R4三个寄存器里。
MOV R0,#20H;被乘数地址存R0
MOV A, @R0 ;取16位被乘数低8位
MOV B, 30H ;取乘数,B <- (M2)
MUL AB ;(M1)x (M2)
MOV R4, A ;积的低8位
MOV R3, B ;暂存
INC R0 ;指向16位被乘数高8位
MOV A, @R0 ;取被乘数高8位
MOV B, 30H ;取乘数
MUL AB ;(M1+1)x (M2)
ADD A, R3 ;得到积的第二个字节
MOV R3, A ;存入R3
MOV A, B ;
ADDC A, #00H ;得到积的第三个字节
MOV R2, A ;存入R2

逻辑运算及移位类

与运算

1) ANL A , #data8\direct@Ri\Rn
2) ANL direct , #data8\A

或运算

1) ORL A , #data8\direct@Ri\Rn
2) ORL direct , #data8\A

异或运算

1) XRL A , #data8\direct@Ri\Rn
2) XRL direct , #data8\A

非运算

1) CPL A ;累加器取反
2) CLR A ;累加器清零

移位运算

1) RL A 循环左移
2) RR A 循环右移
3) RLC A 带进位循环左移
4) RRC A 带进位循环右移

控制转移类

转移类

(1)无条件转移指令

长转移指令 LJMP addr16 :将 16 位目标地址addr16 装入PC, 程序无条件转向指定的目标地址。转移的目标地址可以在 64 KB程序存储器地址空间的任何地方, 不影响任何标志

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

SJMP rel :rel—— 8 位带符号的偏移量字节, 用于SJMP和所有条件转移指令中。 偏移量相对于下一条指令的第一个字节计算, 在-128~+127 范围内取值。用8位补码表示。执行该指令时, 先将 PC+2, 再把指令中带符号的偏移量加到PC上, 得到跳转的目标地址送入PC。
需要注意的是, 目标地址与SJMP后面一条指令的第一个字节必须在同一个 256B区域的存储器区内。

JMP @A+DPTR:执行该指令时, 把累加器 A中的 8 位无符号数与数据指针中的 16 位数相加, 结果作为下条指令的地址送入PC, 不改变累加器 A和数据指针DPTR的内容, 也不影响标志。 利用这条指令能实现程序的散转。

(2)条件转移指令
由条件决定是否转移。若满足条件就转移;若不满足条件就顺序执行。
1)累加器判零条件转移指令
JZ rel ;若A=0则转移
JNZ rel ;若A≠0则顺序执行下一条指令

2)比较条件转移指令
CJNE A,#data8,rel ;累加器内容与立即数不相等就转移
CJNE A,direct,rel ;累加器内容与内部RAM内容不等就转移
CJNE Rn,#data8,rel ;工作寄存器内容与立即数不等就转移
CJNE @Ri,#data8,rel ;内部RAM128单元内容与立即数不等转 ;移
注意Cy的变化
操作:
若目的操作数 = 源操作数,则PC←PC+3(继续执行)
若目的操作数 > 源操作数,则Cy=0,PC←PC+3+rel(转移)
若目的操作数 < 源操作数,则Cy=1,PC←PC+3+rel(转移)

3)减1 条件转移指令
DJNZ Rn, rel ;Rn ← Rn -1
;若Rn = 0,则PC←PC+2(继续执行)
;否则, PC←PC+2+rel(转移)
DJNZ direct, rel ;(direct) ← (direct) -1
;若(direct) = 0,则PC←PC+3(继续执行)
;否则, PC←PC+3+rel(转移)

4)Cy条件指令
JC rel ; 若Cy=1则转移 ;若Cy≠1则顺序执行下一条指令
JNC rel ;若Cy=0则转移 ;若Cy≠0则顺序执行下一条指令
5)
JB bit, rel 若bit =1则转移 ;若bit ≠1则顺序执行下一条指令
JNB bit, rel;若bit =0则转移 ;若bit ≠0则顺序执行下一条指令
JBC bit, rel;若bit =1则转移 ,并使bit清零;若bit ≠1则顺序执行下一条指令

调用/返回类

1)调用指令
长调用指令:
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

2)返回指令
子程序返回指令:
RET; PC15~8← ((SP)) ,(SP) ← (SP) -1
; PC7~0 ← ((SP)) ,(SP) ← (SP) -1
中断程序返回指令:
RETI ; (PC)15~8 ← ((SP)), SP ← (SP)-1
(PC)7~0 ← ((SP)), SP ← (SP)-1

位操作类

一位微处理器 —— 布尔处理器
累加器(借用进位标志Cy)
储存器(位寻址区中的各位)

可以按位操作的区域是: 内部RAM中20H–2FH单元,一些SFR,如A,PSW,B,P0,P1,P2,P3,IP,IE,TCON,SCON。

位地址在指令中用bit来表示
操作类

位传类

MOV C,bit ;Cy ← (bit)
MOV bit,C ;(bit) ← Cy

位置位和复位

CLR C ;Cy ← 0
CLR bit ;(bit) ← 0
SETB bit ;Cy ← 1
SETB C ;(bit) ← 1

位运算

与:
ANL C,bit
ANL C,/bit
或:
ORL C,bit
ORL C,/bit
非:
CPL C
CPL bit

位控制转移指令

1)以Cy内容为条件的转移指令:
JC rel ;Cy=1时就转移
JNC rel ;Cy=0时就转移
2)以位地址内容为条件的转移指令
JB bit, rel ;(bit)=1时就转移
JNB bit, rel ;(bit)=0时就转移
JBC bit, rel ;(bit)=1就转移,并使该位清零移

下面这个例子比较有意思,分享给大家看。
例:判别累加器A和30H单元内容的大小,若(A)=(30H),转向标号LOOP1,若(A)>(30H),则转向标号LOOP2,若(A)<(30H),则转向标号LOOP3.

MOV R0, A ;暂存
ANL A, #80H ;判别A的正负
JNZ NEG ;A<0则转至NEG
MOV A, 30H ;
ANL A, #80H ;判别(30H)的正负
JNZ LOOP2 ;(30H)<0, A>(30H)
SJMP CMP ;(30H)>0,转向COMP
NEG: MOV A, 30H
ANL A, #80H ;再次判别(30H)的正负
JZ LOOP3 ;(30H)>0, A<(30H)
COMP: MOV A, R0 ;取出原A值
CJNE A, 30H, NEXT ;比较A与(30H)
SJMP LOOP1 ;A=(30H),转LOOP1
NEXT: JNC LOOP2 ;A>(30H),转LOOP2
JC LOOP3 ;A<(30H),转LOOP3

**注意:**这个例子首先要分别判断正负,分别讨论不同情况。而且通过CJNE指令的前提是这两个数同符号才能通过执行完指令时的Cy的数值来比较大小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值