成就更好的自己
目录
指令系统概述
AT89S51指令系统简明,共111条;
单字节指令49条,双字节指令45条,三字节指令17条;
12MHz晶振的情况下,每个机器周期1us;
指令格式
指令通常由两部分组成:操作码和操作数;
操作码——指令进行什么操作;操作数——指令操作的对象;
(1)单字节指令:操作码和操作数同在一个字节中;
(2)双字节指令:一个字节为操作码,另一个字节是操作数;
(3)三字节指令:操作码占一个字节,操作数占二个字节;
寻址方式
寻址方式概述
寻址方式——在指令中说明操作数所在地址的方法。
一般说,寻址方式越多,功能就越强,灵活性则越大,指令系统就越复杂。
寻址方式就是如何在整个存储器和寄存器的寻址空间内快速地找到指定的地址单元;
系统7种寻址方式:
1.寄存器寻址方式
指令中的操作数为某一寄存器的内容。
例如:MOV A,Rn ;(Rn)→A,n =0~7
把Rn中的源操作数送入到累加器A中。由于指令指定了从寄存器Rn中取得源操作数,所以称为寄存器寻址方式。
2.直接寻址方式
指令中直接给出操作数的单元地址,该单元地址中的内容就是操作数,直接的操作数单元地址用“direct”表示。
例如: MOV A,direct
“direct”就是操作数的单元地址。
例如: MOV A,40H
表示把内部RAM 40H单元(direct)的内容传送到A。指令中源操作数(右边的操作数)采用的是直接寻址方式。
指令中两个操作数都可由直接寻址方式给出。
例如: MOV direct1,direct2
具体指令:MOV 42H,62H
把片内RAM中62H单元的内容送到片内RAM中的42H单元中。
直接寻址是访问片内所有特殊功能寄存器的唯一寻址方式。
3. 寄存器间接寻址方式
寄存器中存的是操作数地址,即先从寄存器中找到操作数的地址,再按该地址找到操作数。
为了区别寄存器寻址和寄存器间接寻址,在寄存器间接寻址方式中,应在寄存器名称前面加前缀标志“@”。
例如:MOV A,@Ri ;i=0或1
其中, Ri的内容为40H,即把内部RAM 40H地址单元中的内容传送给A。
4.立即数寻址方式
直接在指令中给出操作数——也称立即数。为了与直接寻址指令中的直接地址加以区别,需在操作数前加前缀标志“#”。
例如: MOV A,#40H
第一个字节是操作码,第二字节是立即数,就是放在程序存储器内的常数。
5.基址寄存器加变址寄存器间址寻址方式
以DPTR或PC作为基址寄存器,以累加器A作为变址寄存器,以两者内容相加形成的16位地址作为目的地址进行寻址。例如指令: MOVC A,@A+DPTR
其中,(A)=05H,(DPTR)=0400H,指令执行结果是把程序存储器0405H单元的内容传送给A。
本寻址方式的指令有3条:
MOVC A,@A+DPTR
MOVC A,@A+PC
JMP A,@A+DPTR
前两条指令适用于读程序存储器中固定的数据。例如,将固定的、按一定顺序排列的表格存放在程序存储器中,在程序运行中由A的动态参量来确定读取对应的表格参数。
第3条为散转指令,A中内容为程序运行后的动态结果,可根据A中不同内容,实现跳向不同程序入口的跳转。
6.相对寻址方式
解决程序转移。该寻址是以该转移指令的地址(PC值)加上它的字节数,再加上相对偏移量(rel),形成新的转移目的地址,从而程序转移到该目的地址。转移的目的地址用下式计算:
目的地址=转移指令所在的地址+转移指令字节数+rel
其中,偏移量rel是带符号8位二进制补码数,–128~+127。
程序转移范围是以转移指令的下条指令首地址为基准地址,相对偏移在–128~+127之间。
例如, SJMP rel
程序要转移到该指令的PC值加3再加上rel的目的地址处。编写程序时,只需在转移指令中直接写要转向的地址标号。
例如: SJMP LOOP
“LOOP” 为目的地址标号。汇编时,由汇编程序自动计算和填入偏移量。但手工汇编时,偏移量的值由手工计算。
7.位寻址方式
对内部RAM和特殊功能寄存器具有位寻址功能的某位内容进行置1和清0操作。
位地址一般以直接位地址给出,位地址符号为“bit”。
例如:MOV C,bit 其具体指令: MOV C,40H
把位地址为40H的值送到进位位C。
由于AT89S52具有位处理功能,可直接对数据位方便地实现置1、清0、求反、传送、判跳和逻辑运算等操作,为测控系统的应用提供了最佳代码和速度,增强了实时性。
寻址方式总结:
当一条指令给定后,如何来确定该指令的寻址方式?例如: MOV A,#40H,属于立即数寻址还是寄存器寻址?
要看以哪个操作数作为参照系。
操作数分为源操作数和目的操作数。对于源操作数“#40H”来说,是“立即数寻址”方式,但对目的操作数“A”来说,是属于“寄存器寻址”方式。
一般而言,寻址方式指的是源操作数,所以此例为立即数寻址方式。
对指令系统7种寻址方式总结,概括见下表:
8051指令集分类介绍
指令集概述
共111条指令,按功能分为五类:
(1)数据传送类(28条)
(2)算术运算类(24条)
(3)逻辑操作类(25条)
(4)控制转移类(17条)
(5)位操作类(17条)
先简单介绍指令用到的符号:
Rn | 当前寄存器区的8个工作寄存器R0~R7(n=0~7)。 |
Ri | 当前寄存器区中作为间接寻址寄存器的2个寄存器R0、R1(i=0,1)。 |
direct | 直接地址,即8位内部数据存储器单元或特殊功能寄存器的地址。 |
#data | 指令中的8位立即数。 |
#data16 | 指令中的16位立即数。 |
rel | 偏移量,8位的带符号补码数。 |
DPTR | 数据指针,可用作16位数据存储器单元地址的寄存器。 |
bit | 内部RAM或特殊功能寄存器中的直接寻址位。 |
C或Cy | 进位标志位或位处理机中的累加器。 |
addr11 | 11位目的地址。 |
addr16 | 16位目的地址。 |
@ | 间接寻址寄存器前缀,如@Ri,@A+DPTR。 |
(х) | 表示х地址单元或寄存器中的内容。 |
((х)) | 表示以х单元或寄存器中的内容作为地址间接寻址单元的内容。 |
→ | 箭头右边的内容被箭头左边的内容所取代。 |
数据传送类指令
使用最频繁。一般数据传送类指令的助记符为“MOV”,通用格式如下:
MOV <目的操作数>,<源操作数>
数据传送类指令是把源操作数传送到目的操作数。指令执行之后,源操作数不改变,目的操作数修改为源操作数。所以数据传送类操作属“复制”性质,而不是“搬家”。
本类指令不影响标志位:Cy、Ac和OV,但不包括奇偶标志位P。
1.以累加器为目的操作数的指令
MOV A,Rn ; (Rn)→A,n =0~7
MOV A,@ Ri ; ((Ri))→A i =0,1
MOV A,direct ; (direct)→A
MOV A,#data ; #data→A
把源操作数内容送累加器A,源操作数有寄存器寻址、直接寻址、间接寻址和立即数寻址等方式,例如:
MOV A,R6 ;(R6)→A,寄存器寻址
MOV A,@R0 ;((R0))→A,间接寻址
MOV A,70H ;(70H)→A,直接寻址
MOV A,#78H ;78H→A,立即数寻址
2.以Rn为目的操作数的指令
MOV Rn ,A ;(A)→Rn ,n =0~7
MOV Rn ,direct ;(direct)→Rn ,n =0~7
MOV Rn ,#data ;#data→Rn ,n =0~7
把源操作数送入当前寄存器区的R0~R7中的某一寄存器。
3.以直接地址direct为目的操作数的指令
MOV direct,A ; (A)→direct
MOV direct,Rn ; (Rn)→direct,n =0~7
MOV direct1,direct2 ;(direct2)→direct1
MOV direct,@Ri ; ((Ri))→direct,i =0,1
MOV direct,#data ; #data→direct
把源操作数送入直接地址指定的存储单元。direct指的是内部RAM或SFR地址。
4.以寄存器间接地址为目的操作数的指令
MOV @Ri,A ;(A)→((Ri)), i=0,1
MOV @Ri,direct ;(direct)→((Ri)),i=0,1
MOV @Ri,#data ;#data→((Ri)), i=0,1
功能是把源操作数内容送入R0或R1指定的存储单元中。
5.16位数传送指令
MOV DPTR,#data16;#data16→DPTR
功能是把16位立即数送入DPTR,用来设置数据存储器的地址指针。
AT89S52有两个DPTR,通过设置特殊功能寄存器AUXR1中的DPS位来选择。当DPS=1,则指令中的DPTR即为DPTR1,DPTR0被屏蔽,反之亦然。
DPTR为16位的数据指针,分为DPH和DPL。操作十分灵活方便。设有两个DPTR后,就可避免频繁的出入堆栈操作。
对于所有MOV类指令,累加器A是一个特别重要的8位寄存器,CPU对它具有其他寄存器所没有的操作指令。后面将要介绍的加、减、乘、除指令都是以A作为目的操作数。
Rn为所选择的寄存器组中的R0~R7,直接地址direct为内部RAM的00H~7FH和特殊功能寄存器(地址范围80H~FFH)
在间接地址中,用R0或R1作为内部RAM的地址指针,可访问内部RAM的00H~7FH共128个单元。
6.堆栈操作指令
内部RAM中设定一个后进先出(LIFO,Last In First Out)的区域,称为堆栈。在特殊功能寄存器中有一个堆栈指针SP,指示堆栈的栈顶位置。堆栈操作有进栈和出栈两种,因此,在指令系统中相应有两条堆栈操作指令。
(1)进栈指令
PUSH direct
首先将栈指针SP加1,然后把direct中的内容送到SP指示的内部RAM单元中。
例如:当(SP)=60H,(A)=30H,(B)=70H时,执行下列指令
PUSH Acc ;(SP)+1=61H→SP,(A)→61H
PUSH B ;(SP)+1=62H→SP,(B)→62H
结果:(61H)=30H,(62H)=70H,(SP)=62H。
(2)出栈指令
POP direct
将SP指示的栈顶单元的内容送入direct字节中,SP减1。
例如:当(SP)=62H,(62H)=70H,(61H)=30H时,执行指令
POP DPH ;((SP))→DPH,(SP)-1→SP
POP DPL ;((SP))→DPL,(SP)-1→SP
结果为(DPTR)=7030H,(SP)=60H。
7.累加器A与外部数据存储器RAM/IO传送指令
MOVX A,@DPTR ;((DPTR))→A,读外部RAM/IO
MOVX A,@Ri ;((Ri))→A,读外部RAM/IO
MOVX @DPTR,A ;(A)→((DPTR)),写外部RAM/IO
MOVX @Ri ,A ;(A)→((Ri)),写外部RAM/IO
MOV的后面加“X”,表示访问的是片外RAM或I/O口,在执行前两条指令, (P3.7)有效;后两条指令, (P3.6)有效。
采用16位的 DPTR间接寻址,可寻址整个64KB片外数据存储器空间,高8位地址(DPH)由P2口输出,低8位地址(DPL)由P0口输出。
采用Ri(i =0,1)进行间接寻址,可寻址片外256个单元的数据存储器。8位地址由P0口输出,锁存在地址锁存器中,然后P0口再作为8位数据口。
8.查表指令
共两条,仅有的两条读程序存储器中表格数据的指令。由于程序存储器只读不写,因此传送为单向,从程序存储器中读出
数据到A中。两条查表指令均采用基址寄存器加变址寄存器间接寻址方式。
(1)MOVC A,@A+PC
以PC作为基址寄存器,A的内容(无符号数)和PC的当前值(下一条指令的起始地址)相加后得到一个新的16位地址,把该地址的内容送到A。
例如:当 (A)=30H时,执行地址1000H处的指令
1000H: MOVC A,@A+PC
该指令占用一个字节,下一条指令的地址为1001H,(PC)=1001H再加上A中的30H,得1031H,结果把程序存储器中1031H的内容送入累加器A。
优点:不改变特殊功能寄存器及PC的状态,根据A的内容就可以取出表格中的常数。
缺点:表格只能存放在该指令所在地址的+256个单元之内,表格大小受到限制,且表格只能被一段程序所用。
(2)MOVC A,@A+DPTR
DPTR为基址寄存器,A的内容(无符号数)和DPTR的内容相加得到一个16位地址,把由该地址指定的程序存储器单
元的内容送到累加器A。
例如:(DPTR)=8100H,(A)=40H,执行指令
MOVC A,@A+DPTR
将程序存储器中8140H单元内容送入A中。
本指令执行结果只与指针DPTR及累加器A的内容有关,与该指令存放的地址及常数表格存放的地址无关,因此表格的大小和位置可以在64KB程序存储器空间中任意安排,一个表格可以为各个程序块公用。
两条指令的助记符都是在MOV的后面加“C”,是CODE的第一个字母,即表示程序存储器中的代码。
执行上述两条指令时,单片机的 PSEN*引脚信号(程序存储器读)有效,这一点读者要牢记。
9.字节交换指令
XCH A,Rn ; (A) ( Rn),n =0~7
XCH A,direct ; (A) ( direct)
XCH A,@Ri ; (A) (( Ri)),i=0,1
这组指令的功能是将累加器A的内容和源操作数的内容相互交换。源操作数有寄存器寻址、直接寻址和寄存器间接寻址等方式。例如:
(A)=80H,(R7)=08H,(40H)=F0H
(R0)=30H,(30H)=0FH
执行下列指令:
XCH A,R7 ;(A) ((R7)
XCH A,40H ;(A) ((40H)
XCH A,@R0 ;(A) (((R0))
结果为(A)=0FH,(R7)=80H,(40H)=08H,(30H)=F0H。
结果为(A)=0FH,(R7)=80H,(40H)=08H,(30H)=F0H。
10.半字节交换指令
XCHD A,@Ri
累加器的低4位与内部RAM低4位交换。
例如:(R0)=60H,(60H)=3EH,(A)=59H
执行完“XCHD A,@R0”指令,则(A)=5EH,(60H)=39H。
算术运算类指令
指令系统中,有单字节的加、减、乘、除法指令,算术运算功能比较强。
算术运算指令都是针对8位二进制无符号数的,如要进行带符号或多字节二进制数运算,需编写具体的运算程序,通过执行程序实现。
算术运算的结果将使PSW的进位(Cy)、辅助进位(Ac)、溢出(OV)3种标志位置1或清0。
但增1和减1指令不影响这些标志。
1.加法指令
4条指令:
ADD A,Rn ;(A)+(Rn)→A ,n=0~7
ADD A,direct ;(A)+(direct)→A
ADD A,@Ri ;(A)+((Ri))→A,i=0,1
ADD A,#data ;(A)+#data→A
8位加法指令的一个加数总是来自累加器A,而另一个加数可由寄存器寻址、直接寻址、寄存器间接寻址和立即数寻址等不同的寻址方式得到。加的结果总是放在累加器A中。
使用本指令时,要注意累加器A中的运算结果对各个标志位的影响:
(1)如果位7有进位,则进位标志Cy置1,否则Cy清0。
(2)如果位3有进位,辅助进位标志Ac置1,否则Ac(Ac为PSW寄存器中的一位)清0。
(3)如果位6有进位,而位7没有进位,或者位7有进位,而位6没有进位,则溢出标志位OV置1,否则OV清0。
溢出标志位OV的状态,只有带符号数加法运算时才有意义。当两个带符号数相加时,OV=1,表示加法运算超出了累加器A所能表示的带符号数的有效范围(-128~+127),即产生了溢出,表示运算结果是错误的,否则运算是正确的,即无溢出产生。
【例】 (A)=53H,(R0)=FCH,执行指令
ADD A,R0
运算式为
结果:(A)=4FH,Cy=1,Ac=0,OV=0,P=1(A中1的位数为奇数)。
注意:在上面的运算中,由于位6和位7同时有进位,所以标志位OV=0。
【例】 (A)= 85H,(R0)=20H,(20H)=AFH,执行指令
ADD A,@R0
运算式为
结果:(A)=34H,Cy=1,Ac=1,OV=1,P=1。
注意:由于位7有进位,而位6无进位,所以标志位OV=1。
2.带进位加法指令
特点是进位标志位Cy参加运算,三个数相加。 4条指令:
ADDC A,Rn ;(A)+(Rn)+C→A ,n =0~7
ADDC A,direct ;(A)+(direct)+C→A
ADDC A,@Ri ;(A)+((Ri))+C→A,i =0,1
ADDC A,#data ;(A)+#data+C→A
如果位7有进位,则进位标志Cy置“1”,否则Cy清“0”;
如果位3有进位,则辅助进位标志Ac置“1”,否则Ac清“0”;
如果位6有进位而位7没有进位,或者位7有进位而位6没有进位,则溢出标志OV置“1”,否则标志OV清“0”。
【例】 (A)=85H,(20H)=FFH,Cy=1,执行指令
ADDC A,20H
运算式为
结果为 (A)=85H,Cy=1,Ac=1,OV=0,P=1 (A中1的位数为奇数)
3.增1指令
5条指令:
INC A
INC Rn ;n=0~7
INC direct
INC @Ri ;i =0,1
INC DPTR
把指令中所指出的变量增1,且不影响PSW中的任何标志。
指令“INC DPTR”,16位数增1指令。首先对低8位指针DPL执行加1,当溢出时,就对DPH的内容进行加1,不影响标志Cy。
4.十进制调整指令
用于对BCD码加法运算结果的内容修正,指令格式为: DA A
是对压缩的BCD码(一个字节存放2位BCD码)的加法结果进行十进制调整。
两个BCD码按二进制相加之后,必须经本指令的调整才能得到正确的压缩BCD码的和数。
(1)十进制调整问题
对BCD码加法运算,只能借助于二进制加法指令。但二进制数加法原则上并不适于十进制数的加法运算,有时会产生错误结果。例如:
上述的BCD码运算中:
(a)结果正确。
(b)结果不正确,因为BCD码中没有1111这个编码。
(c)结果不正确,正确结果应为17,而运算结果却是11。
可见,二进制数加法指令不能完全适用于BCD码十进制数的加法运算,要对结果做有条件的修正,这就是所谓的十进制调整问题。
(2)出错原因和调整方法
出错原因在于BCD码共有16个编码,但只用其中的10个,剩下6个没用到。这6个没用到的编码(1010,1011,1100,1101,1110,1111)为无效编码。
在BCD码加运算中,凡结果进入或者跳过无效编码区时,结果出错。因此1位BCD码加法运算出错的情况有两种:
① 加结果大于9,说明已经进入无效编码区。
② 加结果有进位,说明已经跳过无效编码区。
无论哪种错误,都因为6个无效编码造成的。因此,只要出现上述两种情况之一,就必须调整。方法是把运算结果加6调整,即十进制调整修正。
十进制调整方法如下:
① 累加器低4位大于9或辅助进位位Ac=1,则低4位加6修正。
② 累加器高4位大于9或进位位Cy=1,则高4位加6修正。
③ 累加器高4位为9,低4位大于9,高4位和低4位分别加6修正
上述调整修正,是通过执行指令“DA A”来自动实现的。
【例】 (A)=56H,(R5)=67H,把它们看作两个压缩的BCD数,进行BCD加法。执行指令:
ADD A,R5
DA A
高4位和低4位分别大于9,所以“DA A”指令要分别加6,对结果修正。
结果为(A)=23H,Cy=1。
由上可见,56+67=123,结果正确。
5.带借位的减法指令
4条指令:
SUBB A,Rn ; (A)-(Rn)-Cy→A,n =0~7
SUBB A,direct ; (A)-(direct)-Cy→A
SUBB A,@Ri ; (A)-((Ri))-Cy→A, i =0,1
SUBB A,#data ; (A)-#data-Cy→A
从A的内容减去指定变量和进位标志Cy的值,结果存在A中。
如果位7需借位则Cy置1,否则Cy清0;
如果位3需借位则Ac置1,否则Ac清0;
如果位6借位而位7不借位,或者位7借位而位6不借位,则溢出标志位OV置“1”,否则OV清“0”。
【例】 (A)=C9H,(R2)=54H,Cy=1,执行指令
SUBB A,R2
运算式为
结果: (A)=74H,Cy=0,Ac=0,OV=1(位6向位7借位)。
6.减1指令
DEC A ;(A)-1→A
DEC Rn ;(Rn)-1→Rn,n=0~7
DEC direct ;(direct)-1→direct
DEC @Ri ;((Ri))-1→(Ri),i =0,1
功能是指定的变量减1。若原来为00H,减1后下溢为FFH,不影响标志位(P标志除外)。
【例3-6】 (A)=0FH,(R7)=19H,(30H)=00H,(R1)=40H,(40H)=0FFH,执行指令
DEC A ;(A)-1→A
DEC R7 ;(R7)-1→R7
DEC 30H ;(30H)-1→30H
DEC @R1 ;((R1))-1→(R1)
结果:(A)=0EH,(R7)=18H,(30H)=0FFH,(40H)=0FEH,P=1,不影响其他标志。
7.乘法指令
MUL AB ;A×B→BA
积的低字节在累加器A中,高字节在B中。如果积大于255,则OV置1,否则OV清0。Cy标志总是清0。
8.除法指令
DIV AB ;A/B→A(商),余数→B
商(为整数)存放在A中,余数存放在B中,且Cy和溢出标志位OV清“0”。
如果B的内容为0(即除数为0),则存放结果的A、B中的内容不定,并溢出标志位OV置1。
【例】(A)=FBH,(B)=12H,执行指令
DIV AB
结果: (A)=0DH,(B)=11H,Cy=0,OV=0。
逻辑操作类指令
1.累加器A 清“0”指令
CLR A
累加器A清0。不影响Cy、Ac、OV等标志位。
2.累加器A求反指令
CPL A
将累加器A的内容按位逻辑取反,不影响标志位。
3.左环移指令
RL A
功能是A向左循环移位,位7循环移入位0,不影响标志位,如图所示:
4.带进位左环移指令
RLC A
将累加器A的内容和进位标志位Cy一起向左环移一位,如
图3-2 所示。
5.右环移指令
RR A
这条指令的功能是A的内容向右环移一位不影响其他标志位,如图所示。
6.带进位右环移指令
RRC A
A的内容和进位标志Cy一起向右环移一位,如图所示。
7.累加器半字节交换指令
SWAP A
是将累加器A的高半字节(Acc.7~Acc.4)和低半字节(Acc.3~Acc.0)互换。
【例】(A)= 95H,执行指令
SWAP A 结果为 (A)=59H。
8.逻辑与指令
ANL A,Rn ;(A)∧(Rn)→A,n=0~7
ANL A,direct ;(A)∧(direct)→A
ANL A,#data ;(A)∧#data→A
ANL A,@Ri ;(A)∧((Ri))→A,i =0~1
ANL direct,A ;(direct)∧(A)→direct
ANL direct,#data ;(direct)∧#data→direct
是在指定的变量之间以位为基础进行“逻辑与”操作,结果存放到目的变量所在的寄存器或存储器中。
【例】 (A)=07H,(R0)=0FDH,执行指令
ANL A,R0
运算式为
结果: (A)=05H。
9.逻辑或指令
ORL A,Rn ;(A)∨(Rn)→A ,n =0~7
ORL A,direct ;(A)∨(direct)→A
ORL A,#data ;(A)∨ #data→A
ORL A,@Ri ;(A)∨((Ri))→A,i =0,1
ORL direct,A ;(direct)∨(A)→direct
ORL direct,#data ;(direct)∨#data→direct
是在所指定的变量之间执行位的“逻辑或”操作,结果存到目的变量寄存器或存储器中。
【例】 (P1)=05H,(A)=33H,执行指令
ORL P1,A
运算式为
结果:(P1)=35H。
10.逻辑异或指令
XRL A,Rn ;(A)⊕(Rn)→A,n=0~7
XRL A,direct ;(A)⊕(direct)→A
XRL A,@Ri ;(A)⊕((Ri))→A ,i =0,1
XRL A,#data ;(A)⊕#data→A
XRL direct,A ;(direct)⊕(A)→direct
XRL direct,#data ;(direct)⊕#data →direct
功能是在所指定的变量之间执行以位的“逻辑异或”操作,结果存到目的变量寄存器或存储器中。
【例】 (A)=90H,(R3)=73H,执行指令
XRL A,R3
运算式为
结果: (A)=E3H。
剩余内容见下一篇博客:
优秀文章推荐:
SCDN博主hhhhorrible指令系统思维导图https://blog.youkuaiyun.com/weixin_38071135/article/details/82958704