单片机原理及应用 - 指令系统
指令概述
指令即按照人们意图完成某种操作的命令,采用英文名称或者缩写形式作为助记符
按照所占字节分为:
- 单字节指令 49 条,操作码和操作数同在一个字节中。
- 双字节指令 45 条,1 字节为操作码,另 1 字节是操作数
- 三字节指令 17 条,操作码占 1 个字节,操作数占 2 个字节
按执行时间分为:
- 1 个就机器周期(12 个时钟振荡周期)的指令 49 条
- 2 个机器周期指令 45 条
- 4 个机器周期 - 乘和除指令
按指令功能分为 5 类(112条):
- 数据传送类(28条)
- 算术运算类(24条)
- 逻辑操作类(25条)
- 控制转移类(17条)
- 位操作类(17条)
指令格式
指令格式即指令的表示方法,通常由操作码和操作数两部分组成,指令长度不同,格式也就不同
操作码:指令进行什么操作
操作数:指令操作的对象,可能是一具体数据,也可能是指出到哪里取得数据的地址或符号
指令系统的寻址方式
寻址方式即指令中说明操作数所在地址的方法,也就是如何在整个存储器和寄存器的寻址空间内快速地找到指定的地址单元,一般说,寻址方式越多,功能就越强,灵活性则越大,指令系统就越复杂
寄存器寻址
指令中操作数为某一寄存器的内容,如:MOV A, Rn; n = 0 ~ 7
寻址范围:
- 4 组通用工作寄存器共 32 个工作寄存器,只对当前工作区域的 8 个工作寄存器寻址
- 部分特殊功能寄存器,如累加器 A,寄存器 B 以及数据指针寄存器 DTPR
直接寻址
指令中直接给出操作数的单元地址,该单元地址中的内存就是操作数,如:MOV A, direct
,把操作数的单元地址 direct 的数据传送到 A 中,指令中两个操作数都可由直接寻址方式给出
直接寻址是访问片内所有特殊功能寄存器和内部 RAM(128个单元)的唯一寻址方式
寄存器间接寻址
寄存器中存的的是操作数地址,先从寄存器中找到操作数的地址,再按照地址找到操作数,如:MOV A, @Ri; i = 0 或 1
,为了和寄存器寻址方式区分,在操作数前加 @ 符号
立即数寻址
直接在指令中给出操作数(立即数),为了区别直接寻址和立即数,需要在操作数前加前缀 #,如:MOV A, #80H
基址寄存器加变址寄存器间接寻址
以 DPTR(数据指针寄存器,16 位) 或 PC(程序寄存器,8 位)作为基址寄存器,以累加器 A 作为变址寄存器,两个内容相加形成的 16 位地址作为目的地址进行寻址,如:MOVC A, @A+DPTR
,其中 (A)=05H, (DTPR)=0400H 相当于把程序存储器 0405H 单元的内容传送给 A
本寻址方式的三种指令:MOVC A, @A+DPTR
, MOVC A, @A+PC
, JMP @A+DPTR
相对寻址
解决程序转移和跳转,该寻址是以该转移指令的地址(PC值)加上它的字节数(下一条指令),再加上相对偏移量(rel),形成新的转移目的地址,从而程序转移到该目的地址
转移的目的地址用下式计算:目的地址=转移指令所在的地址+转移指令字节数+rel
位寻址
对具有位(一个二进制数)寻址功能的某位内容进行置 1 和清 0 操作,位地址一般以直接位地址给出,位地址符号为 bit(0 或 1),如:MOV C, bit
,其具体指令:MOV C, 40H
把位地址为 40H 的值送到进位位 C
可以进行位寻址的是内部 RAM 和 SFR
位处理功能,可直接对数据位置 1、清 0、求反、传送、判跳和逻辑运算等操作
指令系统
数据传送类(28条)
把源操作数传送到目的操作数(复制),运行后源操作数不变,目的操作数修改为源操作数,格式:MOV <目的操作数>, <源操作数>
- 以累加器为目的:把源操作数内容送累加器A,源操作数有寄存器寻址、直接寻址、间接寻址和立即数寻址等方式
- 以 寄存器 Rn 为目的:把源操作数送入当前寄存器区的 R0~R7 中的某一寄存器
- 以直接地址 direct 为目的:把源操作数送入直接地址指定的存储单元。direct 指的是内部 RAM 或 SFR 地址。
- 以寄存器间接地址目的:功能是把源操作数内容送入 R0 或 R1 指定的存储单元中
- 16 位数传送指令:把 16 位立即数送入 DPTR,用来设置数据存储器的地址指针
- 堆栈操作指令:内部 RAM 中设定一个后进先出的区域叫做堆栈,特殊功能寄存器中有一个堆栈指针 SP 指向堆栈的栈顶位置,分别为进栈和出栈功能设计两个指令:
PUSH
和POP
- 累加器 A 与外部数据存储器 RAM/IO 传送指令:访问外部存储器能力,使用
MOVX
指令,高低位分别放到 R1 和 R0 中 - 查表指令:仅有的两条读程序存储器中表格数据的指令,程序存储器只能读,不能写,因此该指令是单向的,两条指令均采用基址寄存器加变址寄存器间接寻址方式,使用
MOVC
- 字节交换指令:累加器 A 的内容和源操作数的内容相互交换
- 字节半交换指令:累加器低 4 位与内部 RAM 低 4 位交换
算术运算类(24条)
算数运算的结果将会使 PSW 中的进位(Cy)、辅助进位(AC)、溢出(OV)三种标志位置 1 或清 0,增 1 或减 1 指令不会影响这些标志
加法指令
加法指令一个加数总是来自累加器 A,另一个加数可有寄存器寻址、直接寻址、寄存器间接寻址和立即数寻址等方式得到,相加的结果总是放到累加器 A 中,如:ADD A, 加数
A 中运算结果对各个标志位的影响:
- 如果位 7 有进位,则进位标志位 Cy 置 1,否则 Cy 清 0
- 如果位 3 有进位,则辅助进位标志 Ac 置 1,否则 Ac 清 0
- 如果位 6 有进位而位 7 没有进位,或者位 7 有进位而位 6 没有进位,则溢出标志位 OV 置 1,否则 OV 清 0
带进位加法指令
带进位加法指令的特点是进位标志位 Cy 参与运算,因此带进位加法指令是三个数相加,分别是累加器 A,加数和进位标志位,指令格式为:ADDC A, 加数
源操作数可以为:寄存器寻址、直接寻址、寄存器间接寻址和立即数寻址
A 中运算结果对各个标志位的影响:
- 如果位 7 有进位,则进位标志位 Cy 置 1,否则 Cy 清 0
- 如果位 3 有进位,则辅助进位标志 Ac 置 1,否则 Ac 清 0
- 如果位 6 有进位而位 7 没有进位,或者位 7 有进位而位 6 没有进位,则溢出标志位 OV 置 1,否则 OV 清 0
带借位的减法指令
带进位减法指令的特点是进位标志位 Cy 参与运算,因此带进位减法指令是三个数相加,分别是累加器 A,加数和进位标志位,指令格式为:SUBB A, 加数
源操作数可以为:寄存器寻址、直接寻址、寄存器间接寻址和立即数寻址
A 中运算结果对各个标志位的影响:
- 如果位 7 需借位,则进位标志位 Cy 置 1,否则 Cy 清 0
- 如果位 3 需借位,则辅助进位标志 Ac 置 1,否则 Ac 清 0
- 如果位 6 需借位而位 7 不需借位,或者位 7 需借位而位 6 不需借位,则溢出标志位 OV 置 1,否则 OV 清 0
增 1 指令
增 1 指令会把指令中所指向的变量加 1,但不会改变 PSW 寄存器中任何标志位,即使溢出也不会改变标志位,指令格式为:INC DPTR
源操作数可以为:寄存器寻址、直接寻址、寄存器间接寻址和立即数寻址
减 1 指令
减 1 指令会把指令中所指向的变量减 1,但不会改变 PSW 寄存器中任何标志位,即使溢出也不会改变标志位,指令格式为:DEC DPTR
源操作数可以为:寄存器寻址、直接寻址、寄存器间接寻址和立即数寻址
乘法指令
乘法指令把累加器 A 和寄存器 B 中的无符号 8 位整数相乘,其 16 积高 8 位放到寄存器 B 中,低 8 位放到累加器 A 中,如果积大于 255 则溢出标志位 OV 置 1,否则清 0,进位标志位 Cy 始终清 0,指令格式为:MUL AB; (A*B->A)
除法指令
乘法指令把累加器 A 中无符号 8 位整数(被除数)和寄存器 B 中的 8 位无符号整数(除数)相乘,所得商放到累加器 A 中,余数放到寄存器 B 中,且 Cy 和溢出标志位 OV 清 0,如果 B 为 0,除数不能为 0,则溢出标志位 OV 为 1,指令格式为:DIV AB;A/B->A(商),B(余数)
十进制调增指令
用于对于 BCD 码(用 4 位二进制数来表示 1 位十进制数中的 0~9 这 10 个数码)十进制数加法运算结果的内容进行修正,指令格式为:DA A
逻辑操作类(25条)
- 累加器 A 字节清 0 指令:累加器 A 清 0,不影响 Cy,AC,OV 标志位,指令格式:
CLR A
- 累加器 A 字节求反指令:将累加器 A 的内容按位逻辑取反,不影响标志位,指令格式:
CPL A
- 左环移指令:将累加器 A 的 8 位向左循环移位,位 7 移向位 0,指令格式:
RL A
- 带进位左环移指令:将累加器 A 的内容和进制标志位 Cy 向左移位一位,位 7 移向 Cy,Cy 移向位 0,指令格式:
RLC A
- 右环移指令:将累加器 A 的 8 位向右循环移位,位 0 移向位 7,指令格式:
RR A
- 带进位右环移指令:将累加器 A 的内容和进制标志位 Cy 向右移位一位,位 0 移向 Cy,Cy 移向位 7,指令格式:
RRC A
- 累加器半字节交换指令:将累加器 A 高半字节和低半字节互换,指令格式:
SWAP A
- 逻辑与指令:将目的操作数和源操作数进行与操作,将结果放到目的操作数中,指令格式:
ANL <目的操作数>, <源操作数>
- 逻辑或指令:将目的操作数和源操作数进行或操作,将结果放到目的操作数中,指令格式:
ORL <目的操作数>, <源操作数>
- 逻辑异或指令:将目的操作数和源操作数进行异或操作,将结果放到目的操作数中,指令格式:
XORL <目的操作数>, <源操作数>
控制转移类指令(17条)
- 长转移指令:指令的第一和第二字节分别装入 PC 的高位和低位,无条件转向给定地址,指令格式:
LJMP addr16
- 相对转移指令:rel 为相对偏移量,单字节带符号 8 位二进制补码数,可以实现双向转移,执行指令时 PC 加 2,然后把 rel 加到 PC 上,跳转到该地址,指令格式:
SJMP rel
- 绝对转移指令:提供了 11 位地址去替换 PC 的低 11 位指令,形成新的 PC 值,即为转移地址,指令格式:
AJMP addr11
- 间接跳转指令:转移地址为 A 中 8 位无符号数与 DPTR 的 16 位无符号内容之和,该指令以 DPTR 为基址,A 为变址,即可实现程序的多分支转移,指令格式:
JMP @A+DPTR
- 条件转移指令:执行条件转移指令时,如不满足条件则,顺序执行下一条指令;如不满足条件,跳转至下一条指令起始地址加上 rel 偏移量,指令格式:累加器为 0 进行跳转
JZ rel;
累加器非 0 进行跳转JNZ rel;
- 比较不相等转移指令:比较目的操作数和源操作数的值是否相同,如果不相同进行跳转下一条指令起始地址加上 rel 偏移量,如果目的数小于源操作数,则 Cy 置 1,否则 Cy 置 0,指令格式:
CJNE 目的操作数,源操作数,rel
- 减 1 不为 0 转移指令:将操作数减 1,如果不为 0 则转移,主要用于循环控制,指令格式:
DNJZ 操作数,rel
- 调用子程序指令:长调用指令:先把 PC 设置为下一条指令地址,然后把 PC 低位和高位存放到堆栈中,SP + 2,然后把 addr16 装入 PC 中执行子程序,指令格式:
LCALL addr16
;绝对调用指令:PC 设为下一条指令的地址,把 PC 低位和高位存放到堆栈中,SP + 2,然后把 addr11 存放到 PC 低 11 位中,指令格式:ACALL addr11
- 子程序的返回指令:执行本指令时,从堆栈中退出 PC 的高 8 位和低 8 位字节,把栈指针减 2,从 PC 值处开始继续执行程序,指令格式:
RET
- 中断返回指令:和 RET 指令相似,不同之处在于该指令清除了在中断响应时被置 1 的 AT89S51 内部中断优先级寄存器的中断优先级状态,指令格式:
RET1
- 空指令:CPU 不进行任何操作,只消耗一个机器周期的时间,且只执行
(PC)+1->PC
操作,指令格式:NOP
位操作类指令
AT89S51 内部有一个位处理机,对位地址空间有丰富的位操作指令
- 数据位传送指令:由源操作数指定的位标量送到目的操作数指定的单元,指令格式:
MOV C, bit
- 位变量修改指令:
CLR C
Cy 位清 0;CPL C
Cy 位求反;SETB C
Cy 位置 0; - 位变量逻辑与指令:
ANL C, /bit
Cy 的值与取反(/)后的 bit 进行与操作 - 位变量逻辑或指令:
ORL C, bit
Cy 的值与 bit 进行异或操作 - 条件转移类指令:
JC
JNC
JB
JNB
JBC