微机原理与系统设计笔记3 | 8086cpu指令系统
打算整理汇编语言与接口微机这方面的学习记录。本部分介绍8086的指令系统(一些与程序设计密切相关的如子程序调用指令放在下一部分)。
参考资料
- 西电《微机原理与系统设计》周佳社
- 西交《微机原理与接口技术》
- 课本《汇编语言与接口技术》王让定
- 小甲鱼《汇编语言》
1. 汇编语言指令
1.1 8086汇编语言程序中语句种类
指令语句
汇编后翻译为二进制代码,CPU可以执行的语句。
伪指令语句
CPU并不直接执行的语句,如上一篇笔记中提到的DD和DB。
宏指令语句
8086指令系统中没有的指令,是由用户使用宏指令定义伪指令来自定义的新指令。
1.2 汇编语言中语句的组成
(变量名、标号名:) 助记符 操作数 ;注释
- 变量名、标号名不一定有,两者都代表一个地址。
- ;后的是注释,不参加汇编过程,相当于C语言中的"//"
- 这部分不重要,老师只是在讲汇编的大体印象。
1.3 汇编语言中的常数及表达式
突然感觉还是这门课虽然评价很高,但还是一种知识清单式的讲解...
- 常数
- 十进制常数、十六进制常数、字符常数、字符串常数、?(随机数)
- 表达式
- 操作符—算术操作符、逻辑操作符、关系操作符、属性操作符、其他操作符
- 这里有个汇编过程进行的计算和CPU执行的计算,挺好分辨的,前者就好是简单的计算式,后者需要CPU结构。
1.4 标号、变量与伪指令
标号在指令语句左侧,代表指令的地址,常用于指令跳转。
标号一旦定义,三个属性:
NEXT:
......
JZ NEXT
这里的NEXT就是标号。
标号有三个属性(或者说信息):
段地址属性
SEG
偏移地址属性
OFFSET
前两者加起来其实就是标号代表此处的地址(16位),但是实际上经常会分别单独获取两个属性,比如获取偏移属性
MOV BX,OFFSET NEXT
类型
TYPE
有两种,NEAR近程(段内转移,值为-1)和FAR远程(段间转移,值为-2)
虽说TYPE有值,但是是在汇编过程中根据程序跳转的种类赋予的,自己写代码获取type值就并没有意义。
变量定义伪指令
DB 定义字节型变量,DW 定义字型变量,DD 双字型变量
变量定义后,具有5个属性
- 段地址 SEG
- 段内偏移地址(经常使用,OFFSET)
- 类型(DB=1,DW=2,DD=4,字节数)TYPE
- 长度 LENGTH
- 大小 SIZE
在MASM汇编器中有一个
$
16位的位置计数器,在汇编过程中指向存储的位置。应用举例:DATA1 DB 0CH,12H
DATA2 DW $+2
这里存储空间由低到高分别是0CH,12H和两字节的$+2,其值为0004H(高字节地址空间为00H,低字节为04H)
一个注意事项——用变量定义来定义字符串时:
DB定义的字符串可以在存储器允许范围无限扩充
DD和DW定义字符串,单引号之间最多两个字符。
字符数据定义举例:
DATA1 DB 'this'
;在存储器中为 't' 'h' 'i' 's'
DATA2 DW 'AB'
;在存储器中为 'B' 'A
;这是因为前者是字节型,没有高低8位之分
用变量定义变量:
DATAX DW DATA1
;也就是这个字单元存放DATA1的偏移地址
DUP操作符:重复操作符,允许嵌套
;常规
DATA5 DB 4 DUP(?)
;嵌套:课本P87-1.4
BUF1 DB 7 DUP(5 DUP(55H), 10 DUP(F0H))
表示4个字节单元(重复4次),其中的值是随机的。
长度:在变量定义语句中,定义的变量的个数。如果出现DUP这种,最外层DUP左侧的数字就是个数,比如上面的嵌套就是7。
大小属性:所有变量所占的总的字节数。SIZE=TYPE*LENGTH
属性操作符和 PTR 操作符
属性操作符就是上面提到了的 SIZE TYPE LENGTH SEG OFFSET这些,不多介绍了。
PTR用于类型转化,是属性临时修改操作符(仅在PTR作用的语句中发生类型转换)。例子:
;例子1
MOV AX,DATA1;这不对,因为AX16位,DATA1是8位,所以应当转换为字变量:
MOV AX, WORD PTR DATA1
;例子2
MOV [BX],10H;这不对,因为不确定DS:BX对应的存储内容是什么形式的变量,有可能不匹配,汇编器不知道如何处理10H。
MOV BYTE PTR [BX],10H
2. 8086指令分类
《微机原理与接口技术》P31,这部分属于查表。
- 数据传送类指令
- 算术运算类指令
- 逻辑运算类指令
- 移位类指令
- 标志位操作指令
- 转移指令
- 有条件转移
- 无条件转移
- 循环控制指令
- 子程序调用和返回指令
- 中断调用返回指令
- 字符串操作指令
- 输入输出指令
- 其他指令
- 宏指令
3. 数据与转移地址的寻址方式
这部分很熟悉了,这是指令集在设计之初决定的寻找操作数的方法。
3.1 数据寻址方式
立即数寻址
MOV AX,1234H
MOV WORD PTR [0200H],56H
;类型要明确:一方明确,双方都明确
立即数只能做源操作数,且只能传送给存储器和通用寄存器,不能直接给段寄存器。
寄存器寻址
MOV AX,DX
源寄存器和目的寄存器的类型要一样。
注意事项
- 立即数不能直接放到段寄存器DS,SS等。
- CS IP不能当目的操作数。
- 堆栈必须按字操作
存储器寻址
要寻找的操作数在存储器中。
存储单元的段内偏移地址,又有五种方式给出
直接:
如
MOV AL,[2000H]
,注意这里不需要PTR。实际使用过程中经常使用MOV AL,DATA1
也就是变量来直接寻址。存储单元之间不能互相直接操作数据。如果将data2处数据放到data1,需要AL这种通用寄存器来过渡。
此外,寄存器->data1,需要考虑类型匹配:
MOV DATA1,AX;错误
MOV WORD PTR DATA1,AX;正确
寄存器间接寻址:
只能用BX,SI,DI,如
[BX]
,具体语句:MOV BX, OFFSET DATA1
MOV AL,[BX]
同理,寄存器间接寻址也存在一个类型问题:
MOV [BX],12H;×
MOV BYTE PTR [BX],12H
寄存器相对寻址:
BX BP SI DI + 8/16位偏移
(有效地址的一部分在寄存器中),如
[BX]+1
这里的1是指偏移一个字节(一个存储单元)。等效为:[BX]+3
和3[BX]
这里BP默认是在SS段。用于不破坏栈顶指针的相对寻址栈中元素(也就是不出栈)。
这里老师又融会贯通了:
MOV DATA1[BX],AL
;等效为 OFFSET DATA1+(BX),此时段寄存器取决于DATA1定义在的段,如果data1在DS段,则应为
;DS:OFFSET DATA1+(BX)<--AL
;也即,如果偏移disp是一个变量,那么就取它的OFFSET
基址 变址寻址:
基址寄存器:BX BP; 变址寄存器: SI DI。
如:
[BX][SI]
同理,BX默认DS,BP默认SS。
基址变址且相对寻址:
3、4两种的组合。
隐含寻址
- 隐藏目的操作数或源操作数的寻址方式,指令集默认指定。
3.2 转移地址寻址方式
段内转移
只有IP发生变化。有两种寻址方式:
段内直接寻址
直接给出转移到的地址,这里还有一些细致的情况划分(但也合乎情理),老师讲解了三字节指令跳转和两字节指令跳转(这跟寻址范围有关)。
这里提了一下短寻址,段内短寻址,意思是
jmp
到的目标地址并不在jmp前,而在jmp后,但程序设计者能够保证目标地址在当前ip后的127字节之内,此时可以用jmp short DST
来寻址该指令后面的目标地址。而此时由于设计者保证其距离不超过127字节,所以此时这个指令语句仍为2字节,否则为3字节:- -128~0之内:2字节段内寻址
- \(-2^{15}\) ~ -128, +127 ~ \(2^{15}-1\):3字节段内寻址
- 0~127且有short短跳转标记:2字节段内寻址。
CPU如何计算转移的目标地址:转移位置的IP = 当前IP + DISP
DISP就在操作码后,区别是DISP放在一个字节里还是两个字节里。
- 8086指令系统中,所有的条件转移指令,只能在段内转移,且转移范围为当前IP为基准,范围为+128~-127;可以使用无条件转移指令搭桥,实现二级转移,达到更大范围的转移。
- 所有的条件转移指令,都是直接寻址。
段内间接寻址
使用寄存器或者存储单元来存放段内地址。
MOV BX OFFSET L2;
JMP BX;
...
L2:... ;;;;或者
TABLE DW L2
JMP TABLE
;或者L2先放到BX里再放到TABLE里再jmp
;此例一开就跟前面接起来了,方式就多了去了
MOV BX,OFFSET TABLE
JMP WORD PTR [BX]
段间转移
8086不涉及,不过我记得386就涉及了,但我们老师也说非重点,先不操心这个了。
4. 传送类指令
- 除了标志传送指令SHAF和堆栈操作指令POPF外,其余传送指令不影响状态标志。
- 语法规则:
- 立即数只能做源操作数
- 类型要一致
- 类型要明确
- DS SS ES 做目的操作数时,立即数不能做源操作数
- CS、IP不能做目的操作数
- 两存储器单元之间不能互相操作,指令语句中两变量也不能直接运算
4.1 通用传送指令
MOV DST,SRC
4.2 取有效地址指令
LEA REG16,MEM
;将源操作数的有效地址放到16位寄存器中,为了方便使用,REG16最好使用BX BP SI DI
MOV BX,OFFSET DATA1
;等价于下面
LEA BX,DATA1
;但要与下面这个语句区分开
MOV BX,DATA1;这个意思是将DATA1处内容放到BX
;此时data1处类型不明确,所以
MOV BX,WORD PTR DATA1
4.3 取地址指针指令
不是很常用。
LDS REG16,MEM
;将双字变量MEM内容高16位放入DS,低16位放入REG
LES REG16,MEM
;将双字变量MEM内容高16位放入ES,低16位放入REG
注意,这里的REG不能是段寄存器,放几个合法的实例:
TABLE DB 10H,20H
POINT1 DD 02001000H
POINT2 DD TABLE
LDS DI,POINT1
;DS<-0200H,DI<-1000H
LES SI,POINT2
;ES<-TABLE段地址,SI<-TABLE偏移地址
LDS BX,[SI]
LES DI,[BX-5]
4.4 标志传送
LAHF;(AH)<--PSW寄存器的低8位
SAHF;PSW寄存器的低8位-->(AH)
隐含寻址了,因为默认指定。
4.5 数据交换指令
XCHG DST,SRC
可以完成两个操作数之间的数据交换:
- 不能使用段寄存器
- 不能完成存储器单元之间交换
4.6 字节转换
XLAT;(AL)<- (DS: (BX)+(AL) )
;将有效地址为 (BX)+(AL)存储单元的内容放入AL,如果输入AL,输出AL就是转换后的结果,这就是按字节转换:
MOV AL,4
LEA BX,TABLE
XLAT
;完成的工作就是将AL的内容4改为TABLE中的偏移量为4处的内容,相当于查表了。
4.7 堆栈操作
PUSH SRC;
POP DST;
PUSHF;
POPF;
;必须按字操作
5. 算术运算类指令
- CPU执行运算类指令,就会影响状态寄存器
- 段寄存器不能参加运算。
5.1 加法指令
有三种。
ADD DST,SRC; DST<--DST+SRC
ADC DST,SRC; DST<--DST+SRC+CF
;ADD和ADC均影响6个标志位
INC DST;DST增1,放到DST
;根据结果设置除了CF以外的5个状态标志,一定注意
一个例子,不想打字了,是老师讲过的双字变量如何相加(当时在学校没有好好听)。
5.2 减法指令-跳转指令
有5条。
SUB DST,SRC; DST<--(DST)-(SRC)
SBB DST,SRC; DST<--(DST)-(SRC)-CF
;SUB和SBB均影响6个标志位
DEC DST; DST-1放回DST
;根据结果设置除了CF以外的5个状态标志
CMP DST,SRC ;DST-SRC,结果不放回,直接设置状态寄存器,常用于比较-条件-跳转
这个CMP单说没什么意思,它总是配合跳转指令形成if-else的汇编语块:
表里指令太多,基本上常用的也就JZ
。后面的JA/JNBE是无符号数的高低比较。JG/JNLE是有符号数的高低比较。
最后一条减法指令是求负指令
NEG DST;取负并设置6个状态寄存器
5.3 乘法指令
;无符号数乘法:
MUL SRC
;有符号数乘法:
IMUL SRC
;SRC不能是立即数
- 如果SRC字节型,DST在AL中,两者运算结果放在AX中(AH:AL)
- 如果SRC字型,DST在AX中,两者运算结果放在DX:AX中
- 无符号数乘法只影响CF OF,如果CF OF同为0,则高位为0(AH或DX);相反同为1,高位有有效积。
- 有符号乘法如果CF OF同为0,则高位积无效(AH或DX),也即高位是低位的符号扩展:如果AL符号为负,则AH为8个1。同为1,高位有有效积。
5.4 除法指令
; 无符号除法
DIV SRC
; 有符号除法
IDIV SRC
- SRC不能是立即数
- 无符号字节除法:DST是AX,运算结果的高低位分别放到AL和AH中。
- 无符号字除法:DST高低位分别放在DX AX,运算结果的高低位分别放在DX AX。
- 有符号数除法:余数正负与被除数相同。商正常运算,结果放到的位置与上述相同。
5.5 符号扩展指令
在一些运算中,为了使类型一致而设计的指令,比如a*b+c,a乘以b之后就32位,c需要扩展。
CBW ;AL扩展到AX中,AH是AL符号位的扩展
CWD ;AX扩展到DX中,DX是AX符号位的扩展
5.6 BCD数调整指令
这部分我是不太熟悉的,老师不是很常提这个,BCD以及组合BCD、分离BCD,见笔记1的3.6节。
加法BCD数调整
;加法组合BCD码调整
DAA
;加法分离BCD码调整
AAA
都是对 AL 进行调整。
举例:56+73=129
; 组合
MOV AL,56H ;01010110
ADD AL,73H ;01110011
;现在结果:C9H 1100 1001
DAA ;组合加法BCD码调整
; 1 0010 1001;也就是129
分离BCD的例子:
分离BCD 的调整比 组合BCD 麻烦。
此外,解释一下AAA(ASCII Adjust for Addition),为什么会有ASCII呢?原因就是上面图中的第二步:ASCII的'4'和'8'相较于04H和08H的区别在于高四位的末两位为1,相加之后高4位为0110,而第二步仍然清0,然后第三步就与上图一致。
减法BCD数调整
;减法 组合BCD调整:
DAS ;有借位则-6
;减法 分离BCD调整:
AAS
例子:
乘法分离BCD码调整
AAM ;对MUL的运算结果进行调整
;只影响ZF SF
例子在课本3.18,不贴了,理解就行。
除法分离BCD码调整
AAD ;除法分离BCD码,先调整后运算DIV
; AH*10 + AL --> AX
6. 逻辑运算指令
- CPU执行运算类指令,就会影响状态寄存器
- 段寄存器不能参加运算。
逻辑与指令
AND DST,SRC
CF=0,OF=0,其余状态位正常设置
逻辑或指令
OR DST,SRC
CF=0,OF=0,其余状态位正常设置
异或运算
XOR DST,SRC;
CF=0,OF=0,其余状态位正常设置
逻辑测试指令
TEST DST,SRC
两者与但结果不放回两个寄存器,仅设置状态寄存器。
非运算指令
NOT DST
不影响六个状态标志
7. 移位类指令
无符号数移动就是逻辑移位,有符号数是算术移位。正常设置除AF外的5个标志。
逻辑移位
逻辑右移
SHR DST,CNT
;cnt=1时可以写出来,如果>1则放到CL中
逻辑左移
SHL DST,CNT
;cnt=1时可以写出来,如果>1则放到CL中
算术移位
算术右移
最高位不变,最高位移动到次高位其余位向右移动,最低位移到CF
SAR DST,CNT
算术左移
最高位变了,全部位左移,最高位交给CF。
SAL DST,CNT
循环移位
只影响OF,其他位不定义
不带CF的
左移:
ROL DST,CNT
右移:
ROR DST,CNT
带CF的循环
左移
RCL DST,CNT
右移
RCL DST,CNT
- 这个老师每个指令都要举例,刚想说循环移位有啥用,例子就给了我震撼。
- 41讲的指令系统实在太多了,吐了。
7. 标志位操作指令
重要的是CLI和STI,这个经常用,老师这里跳过了,微机里也不会使用这个的。
8. 转移指令
段内转移指令在5.2部分讲了,这里就只看段间的转移指令。
;===直接寻址:===
JMP FAR PTR ABC
...
ABC:...
;汇编成操作码(1字节)+OFFSET ABC(2字节)+SEG ABC(2字节)
;===间接寻址:===
;定义DS段
TABLE DD ABC;OFFSET ABC:SEG ABC---->地址指针
;定义代码段1
//JMP TABLE
LEA BX,TABLE
JMP DWORD PTR [BX];需要双字,包含OFFSET和SEG
;定义代码段2
ABC:...
10. 循环控制指令
LOOP 标号
- CX-1再放回CX,不影响标志寄存器
- 如果CX≠0,继续跳到标号处执行,否则向下运行
p43看完转p65,看到p67之后再转p44。
LOOPZ(LOOPE) 标号
CX-1再放回CX,不影响标志寄存器
若CX!=0并且ZF==1,转移到标号处
适合在指定区域中查找不同的字符,如果找到不同的,会退出循环。
LOOPNZ(LOOPNE) 标号
与上一个相反,CX!=0并且ZF=0时跳转到标号,适合找指定的字符,找到则退出循环。
JCXZ 标号
若 CX == 0,转移,测试cx开始时是否为0.
微机原理与系统设计笔记3 | 8086cpu指令系统的更多相关文章
- 80x86/Pentium微机原理及接口技术-微处理器-学习笔记
80x86/ Pentium微机原理及接口技术 1. 计算机基础... 1 1.1常用术语... 1 1.2计算机中数与编码的表示方法... 1 1.2.1进制表示及进制转换... 1 1.2 ...
- TCP/IP协议原理与应用笔记18:构成子网和超网
1. 引言: (1)类别IP编址(Classful IP)的缺陷 • 固定的3种IP网络规模 C类地址:少于255台主机的网络 B类地址:介于255~65535台主机的网络 ...
- TCP/IP协议原理与应用笔记17:IP编址(重点)
1. IP地址(通用标识符) 对于同一个网络设备(主机或路由器)的不同网络连接,需要不同的IP地址进行标识 2. 主机标识符 主要有下面三种方式的主机标识方式: (1)Name:是什么,可读性强(了解 ...
- 单片微机原理P0:80C51结构原理
本来我真的不想让51的东西出现在我的博客上的,因为51这种东西真的太low了,学了最多就所谓的垃圾科创利用一下,但是想一下这门课我也要考试,还是写一点东西顺便放博客上吧. 这一系列主要参考<单片 ...
- Java 多线程与并发【原理第二部分笔记】
Java 多线程与并发[原理第二部分笔记] 什么是Java内存模型中的happens-before Java内存模型,即JMM,本身是一种抽象的概念,并不是真实存在的,他描述的是一组规则或者说是一种规 ...
- Java 多线程与并发【原理第一部分笔记】
Java 多线程与并发[原理第一部分笔记] Synchronized synchronized的基本含义以及使用方式 在Java中线程安全问题的主要诱因就是存在共享数据(也称为临界资源)以及存在多条线 ...
- 单片微机原理P1:80C51指令系统和编程方法
0. 寻址方式 寻址方式在汇编中是很重要的,汇编所有的操作都是和和内存或者寄存器打交道的,在80C51里面一共7种寻址方式. 1. 立即寻址: 这个没什么好说的,就是往寄存器或者内存里面写立即数, ...
- 转:HashMap的工作原理,及笔记
HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此 ...
- TCP/IP协议原理与应用笔记01:OSI网络参考模型
1.OSI参考模型 第7层应用层:直接对应用程序提供服务,应用程序可以变化,但要包括电子消息传输 第6层表示层:格式化数据,以便为应用程序提供通用接口.这可以包括加密服务 第5层会话层:在两个 ...
- TCP/IP协议原理与应用笔记06:OSI参考模型全称
1. ISO是一个组织,OSI是一个模型. 2. OSI不是协议,是网络体系结构的概念模型 3. OSI参考模型全称为: Open System Interconnection Reference M ...
随机推荐
- Pycharm自定义实时模板
pycharm添加模板 添加装饰器模板 # 1.file-->Setting-->Editor-->Code Style -->Live Templates# 2." ...
- 解决 net core 3.x 跨域问题
跨域:指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制. 以下几种情况是造成跨域的原因: 域名相同,端口不同 域名相同,协议不同(即,一个 ...
- 记录redis集群连接超时问题及解决方案
下午同事反馈,某业务场景性能测试过程中,出现异常,提供日志报: Redis command timed out 1. 先看下日志 org.springframework.dao.QueryTimeou ...
- Java安全之CC2
前言 由于在2015年底commons-collections反序列化利⽤链被提出时,Apache Commons Collections有以下两个分⽀版本: commons-collections: ...
- 重学c#系列——动态类型[二十二]
前言 该系列准备继续完善,一共108篇,持续更新. 正文 为什么有动态类型呢? 是因为很多东西天生就是动态类型的. 比如xml 和 json.cvs.数据库表,这些本来就是数据类型的. 在反射系列中提 ...
- DevExpress中GridControl控件焦点改变时触发事件
FocusedRowObjectChanged 事件.可以在焦点改变一行的时候触发对应的事件. 做一个记录 大家如果有问题可以 Console.WriteLine("加群"+&qu ...
- 一行代码实现shell if else逻辑
前言 前几天学习 shell 脚本,发现这种好用的写法,简单记录一下. if else 一行实现 if [ 1=1 ] ;then echo "条件成立";else echo &q ...
- esp-01和esp-01s烧录固件和程序
准备工具 USB-TTL 杜邦线若干 esp-01s烧录固件 我烧录的固件是 micropython, 使用的软件是 uPyCraft esp-01s烧录固件接线方法: esp-01s usb-ttl ...
- 关于linux mint新增加的鼠标样式的示例图片不能正确显示的解决办法
前言 我相信你在linux mint 做鼠标主题美化的时候一定遇到过这样的问题 没错!!! 下载的鼠标的主题的示例图片不能正确显示,当然这样虽然不影响正常的鼠标主题更换使用,但是对于我这种强迫症来说简 ...
- day 19 分组查询 & having和where区别
day19 分组查询group by having用法 用于分组关键字(group by)后面 用于对分组之后的结果集进行筛选 having关键字后面可以使用聚合函数 having和where的区别 ...