[专业课笔记] 单片机 第三章 指令系统
正文
汇编语言
- 汇编
- 指令
此处指:让CPU按人的意图执行某个操作的命令
- 指令系统
指一台微机所能执行的全部指令的合集
指令格式
[标号]:操作码 {目的操作数}{,原操作数}[;注释]
[]括号内可有可无,{}内视使用的指令确定是否需要
符号注释
- rn(0`7)所选寄存器组的某个寄存器
- ri(0`1)所选寄存器组可做地址存储器的两个寄存器
- #data
- #data
- direct
- addr11
- addr16
- rel
- bit
- @
- /(非)
寻址方式
寻址, 指用一个符号指代一个操作数的地址, 便于cpu执行指令时寻找并使用这个操作数
此部分推荐配合高级语言的地址和指针的功能食用
8951的寻址方式一共有7种
- 寄存器寻址
- 直接寻址
- 立即数寻址
- 寄存器间接寻址
- 变址寻址
- 相对寻址
- 位寻址
寄存器寻址
用r0~r7或其他寄存器(的地址)存放这个操作数, 并在代码里用寄存器名字指代, cpu按寄存器名字和寄存器状态找操作数
例如
mov a, r0
mov p1,a
mov a,r0
直接寻址
直接在指令中填写这个操作数所在的地址, cpu按这个地址找操作数
例如
mov a, 40h
mov a, p1
注意, 对于特殊功能寄存器(高128位的SFR), 可以用寄存器名称(寄存器寻址), 也可以用所在地址(直接寻址)
立即数寻址
在指令中填写这个操作数本身, cpu不需要通过其他地址寻找即可立即使用操作数
例如
mov a, #40h
和 mov a, 40h里的40h不同, #40h表示40h这个数本身, 而40h则是表示一个存放数据的地址
寄存器间接寻址
将操作数的地址放到寄存器中, cpu通过寄存器名字获得寄存器所存的地址值, 再通过地址找到操作数, 突出一个从输入间接获得结果
例如
mov a, @r0
变址寻址
又叫: 基址寄存器+变址寄存器间接寻址
以某个寄存器所存数据为基地址, 在这个基地址的基础上加上地址偏移量形成真正的地址
8951没有专用变址寄存器, 多用累加器a等寄存器来
例如
mov a, @r0
相对寻址
相对寻址只出现在相对转移指令中, cpu利用pc和目标指令的相对距离找到操作数, 形成实际的(指令)转移地址
目的地址 = 源地址 + 2(即相对转移指令jc的字节数,其他指令可能不同) + rel
并不能把寄存器和立即数当作相对转移的目的地址
例如
jc tag
tag:
...
rel是relative的简写,表示相对当前地址的跳转偏移,它是一个有符号数
具体范围要参阅处理器的指令手册
以常见的51系列为例,它是一个8位有符号数,因此范围是-128至127
位寻址
cpu用位地址为目标寻址, 可以是位特殊寄存器, 也可以是RAM某一单元的某一个位的地址值
setb cy
setb p1.0
- [怪,setb可以给p1位寻址,clr不行]
C51和S51的指令系统
数据传送指令
-
以累加器a为目标操作数的指令
mov a,xx(xx可以是以下几种情况)
- 寄存器寻址:rn
- 直接(地址)寻址:direct
- 间接寻址:@rn
- 立即数寻址:# data
-
以寄存器rn为目的操作数的指令
大体上和以特殊寄存器为目标操作数的指令相同, 但是没有 mov rn,rn, 共三种mov a,xx(xx可以是以下几种情况)
- 直接(地址)寻址:direct
- 间接寻址:@rn
- 立即数寻址:# data
8951没有mov rn,rn的指令!!!
-
以直接地址为目的操作数的指令
mov direct,xx(xx可以是以下几种情况)
- 特殊寄存器寻址:a
- 通用寄存器寻址:rn
- 直接(地址)寻址:direct
- 间接寻址:@rn
- 立即数寻址:# data
-
以间接地址为操作数的指令
mov @rn,xx(xx可以是以下几种情况)
- 特殊寄存器寻址:a
- 直接(地址)寻址:direct
- 立即数寻址:# data
8951同样没有 mov @rn,@rn 和 mov @rn,rn 这样的指令!!!
-
16位数据(整个)传送的指令
- mov dptr, # data16
将16位的立即数放入16位寄存器dptr, dph存放了数据的高八位, dpl存放了数据的低八位
- mov dptr, # data16
-
查表指令(只占一字节)
movc a, @a + xx(xx可以是以下几种情况)
- dptr内的数据作为基地址:dptr
- pc作为基地址:pc
-
(累加器a与)片外RAM的数据传送指令
89C51仅支持寄存器间接访问方式对片外RAM或IO外设芯片进行数据传输( 并且有且只有以下四条指令)
-
非rd == 0 时(即read == 1), 允许读取指令
- movx a,@ri
- movx a,@DPTR
-
非wr == 0 时(即write == 1), 允许写入指令
- movx @ri,a
- movx @DPTR,a
-
-
栈操作指令
-
push direct
将直接地址寻址的单元中的数据入栈, 同时栈指针sp加一 -
pop direct
将栈顶数据保存到直接地址寻址的单元中, 同时sp减一
-
-
交换指令
-
字节交换
- xch a,rn
- xch a,direct
- xch a,@ri
-
半字节交换
xchd a,@ri
; 将ri间接寻址的单元的内容与a的内容的的低四位互换, 高四位不动
该操作只影响标志位 p
-
算术运算指令
-
加法
add a, xx(xx可以是以下几种情况)
- 特殊寄存器寻址:b(除 a 以外的寄存器)
- 通用寄存器寻址:rn
- 直接(地址)寻址:direct
- 间接寻址:@rn
- 立即数寻址:# data
指令将 a 的内容和 xx 的内容相加, 得到的和放入 a , 运算结果会将 cy(第7位进位标志位) , ac(第3位进位(低4进高4)标志位) , ov(溢出标志位, 多用于带符号数的运算) 三个标志位置位或复位
-
带进位加法
addc a, xx(xx可以是以下几种情况)
- 特殊寄存器寻址:b(除a以外的特殊功能寄存器)
- 通用寄存器寻址:rn
- 直接(地址)寻址:direct
- 间接寻址:@rn
- 立即数寻址:# data
指令将 a 的内容和 xx 的内容相乘, 得到的和放入 a
注意, 和add不同, 所谓带进位加法是会将执行本指令前的cy位, ac位, ov位也加入运算, 得出结果
多用于多字节数据运算
例如setb cy addc a, #00h setb ac addc a, #0fh
结果, a 的内容为10h, 也就是10进制的16
-
带借位减法
subb a, xx(xx可以是以下几种情况)
- 特殊寄存器寻址:b(除a以外的寄存器)
- 通用寄存器寻址:rn
- 直接(地址)寻址:direct
- 间接寻址:@rn
- 立即数寻址:# data
指令将 a 的内容和 xx 的内容相乘, 得到的差放入 a
注意, 8951不提供不带借位的减法指令, 如果需要, 在执行subb指令之前需将cy, ov, ac位置0 -
乘法
mul ab
指令将 a 的内容和 b 的内容相乘, 得到的高八位放入 a , 低八位放入 b
-
除法
div ab
指令将 a 的内容除以 b 的内容, 得到的商放入 a , 余数放入 b
-
加一指令
inc xx(xx可以是以下几种情况)
- 特殊寄存器寻址:a
- 通用寄存器寻址:rn
- 直接(地址)寻址:direct
- 间接寻址:@rn
- 16位寄存器寻址: dptr
-
减一指令
dec xx(xx可以是以下几种情况)
- 特殊寄存器寻址:a
- 通用寄存器寻址:rn
- 直接(地址)寻址:direct
- 间接寻址:@rn
注意, 以上加一减一指令不会改变cy标志位, 溢出不会置cy位等标志符为1( 00h 和 ffh )
8.十进制调整指令
da a
调整累加器中的数为BCD数, 多用在算术运算之后得到的二进制数调整为16进制数的过程中
逻辑运算指令
-
简单指令
清零
取反 -
移位指令
rl
rr
rlc
rrc -
累加器半字节交换指令
swap a
-
逻辑与
- anl
-
逻辑或
- orl
-
逻辑异或
- xrl
控制程序转移指令
无条件转移类指令
空操作指令
条件转移类指令
调用和返回指令
位操作(布尔处理)指令
- clr bit
将指定位 置0 - setb bit
将指定位 置1
bit 可以是位地址, 可以是寄存器某位名/位序号(PSW.0)