当前课程知识点:微机原理与接口技术 > 第6周 串操作指令 > 第21讲 关于串操作指令的说明 > 串操作指令说明
大家好
这一讲我们来学习
8086指令系统中的第四大类指令 串操作
串操作指令跟我们之前学习的其他三大类指令
比较起来有这样一个很重要的特点
就是我们之前学的那些指令呢
我们指令的操作对象
都是一字节或者是两字节
那么在今天的计算机里
可能就有更长的比如四字节等等
但是串操作指令它所针对的操作对象呢
都是一个数据块
或者说是一个字符串
也就说都是一串数据
这样一串数据呢 意味着数据是很大的
这种大的数据在指令中间怎么样
能够作为一个操作数出现呢?
所以这一类指令呢
它就有了这样它自己的一些特点
所以下边我们对这类指令
在正式学习之前
我们先对它做一些简单的说明
首先
这一类指令就是针对数据块
或者字符串的操作
因为不论是数据块也好 字符串也好
都是比较意味着比较长的数据
所以这类数据呢
都不可能在一个寄存器里存放
所以它们一定是在内存中存放的
因此我们这一类指令所针对的都是
存储器操作数
或者说它的绝大多数情况下
它针对的操作对象都是在内存中的
我们前面所学到的
所有的双操作数格式的指令
都不允许两个操作数同时为存储器操作数
而串操作指令呢 正好不一样
也就是说它在很多时候
它要求两个操作数
必须同时为存储器操作数
这就是因为它操作的对象这个性质来决定的
在指令中我们说有源操作数有目标操作数
那么在串操作指令里头
既然它针对的是数据块或者字符串的操作
所以在这里呢我们把源操作数叫源串
而目标操作数
称为目标串
比如现在我们来看的这个例子
这个假设是我们要做一个这样的运算
就是将M1为首地址的这样一串数据
传送到内存
M2为首地址的这样一个区域中
其实这个工作
我们在前面讲Move指令的时候已经
做过类似的这样一个练习
当时我不知道大家还有没有记得
当时我们曾经讲我们要把Memory1为首地址的
100个字节的数据
传到Memory2为首地址的
那100个单元中
所以当时我们编写了一个简单的
循环结构的程序
来实现这个功能
那么现在呢我们还是做类似这样一个工作
如果用串操作指令来实现的话
我们后边会看到 它是很简单的
那么对应到我们前面的这个Move指令的例子
那么所以在这里呢我们就把M1
为首的这一块数据
我们称为源串
而把M2为首地址的这一块区域
称为目标串
如果仅仅是作为一个传送的目的地的话
这个目标串有时候我们也可以称为
目标串地址
因为这个串操作指令对于
的操作对象的这样一个特殊性
所以在串操作指令里头
它的操作数都是一个比较大的数据
就是一串数据或者一块数据
但是呢我们数据总线的宽度是有限的
即使在今天的计算机里头
数据总线的宽度也就是64位
所以不可能有更大数据一次性的通过
所以它还是要
一部分一部分的过
那么在我们这个8086指令集里边呢
不管这个数据块有多大或者字符串有多长
它的传送也好运算也好
它也都是按字节
或者是按双字节来进行的
所以呢这一类指令在执行中
就有了这样的一些特点
首先我们要确定这个数据
在哪里 也就是这个数据串在什么地方
它的头在哪里
它的长度值有多长
这些是我们
不论是之前所看到的那些练习也好
还是我们马上要看到的
串操作指令也好
这些工作对于一个大的数据块的操作
都是必须要做的一些初始化的工作
我们继续回忆我们前面讲Move指令的时候
我们讲的那个例子
既然100个字节数
从这块区传到另外一块区
除了我们要知道这两块数据存放的地方
以及它们的头在哪里
以及它们的长度值之外
我们还有一个重要的一点
就是刚才我们说 因为数据总线宽度的限制
我们不可能一块数据一次搬过来
所以如果按字节来搬
或者是按双字节来传送的话
都是要一次一次的来搬过来的
那么搬的时候我们可以先
从头到尾的搬还是从尾到头的搬
实际上都是可以的
对吧 所以这个操作的方向
在我们这个数据块的操作中
是必须要去确定的
我们在前面那个例子里头
我们通过利用INC指令来修改指针
我们实现了数据从低地址到高地址
方向的传送
也就是我们可以俗话的说
从头到尾的传送
那么在串操作指令里头
因为这种传送的工作
或者说其他运算类的工作
实际上经常都是由一条指令来完成的
那么也就是在这条指令的底层
还是必须要实现
这个操作方向的确定
所以串操作指令还很重要的一点
要确定它的操作方向
因为它无法用
INC或者DEC指令来
操作 人为的操作它的方向
而是它在指令本身
在内部就实现了这种自动的操作
所以在
使用串操作指令之前呢
我们必须要确定它的操作方向
我们还是用这个图来看
比如现在这个
我们要把M1为首的这样一串数据传到
M2为首的这块区域里头去
我们可以
按这样子的增地址方向走
我们也可以按减地址方向走
但是请大家注意一点的是
按增地址和按减地址
如果我们的首地址都确定在M1和M2的话
那么按增地址和按减地址传送的数据块
或者是它的目标区域就完全不一样
比如我们刚才按增地址方向的话
它可能传送它就传送的是这一块数据
而如果按减地址方向的话
它传送的就是这一块数据
这个是大家一定在使用的时候要注意的
那么如果你现在就想传送
这块数据
那么你又希望按减地址方向来走
那么我们的首地址
这个M1就不能设置在这个地方了
好 下边我们来具体的看一下有关串操作指令
它的一些
具体的要求
基于现在这样的分析
所以串操作指令在
正式的使用的时候
或者说串操作指令本身
它有着这样子的一些固定的要求
这些要求呢 很多是都是没有道理的
就是指令设计者
他们所设计的一些约定
所以我们在学习它的时候也只能是接受
就像我们一个
一个大字为什么要那样写?
实际上
就那么写了 所以你就记住就好了
所以串操作指令呢有这样一些约定
首先它约定
源串一般在数据段
源串的指针或者说
偏移地址必须由SI来给出
源串的指针
或者说它的偏移地址
必须由SI来给出
那么一般的意思就是 言下之意是可以改的
所以源串是可以段重设的
也就是说你可以
通过重设符
将源串重设到比如附加段
比如堆栈段
但是
绝对不能重设到代码段
因为这个操作数 它是操作的对象是数据
它是不能和指令代码放在一个区域的
但是目标串呢 它有严格的规定
目标串必须在附加段里
它的指针必须由DI来给定
也就说在串操作指令里头
我们必须要声明附加段
这一点我们会在下一章的课程学习中
介绍给大家
串的长度值
刚才我们说了 操作这个数据块要有多长
或者说操作多少次数
这个次数也就是它的数据块的大小
必须要由CX来指定
也就说它不能用其他的寄存器
来指定串的长度 不论这个长度是多长
哪怕它这个长度值小于255
你也必须送给CX
这几点就是
和我们前面所谓的初始化的工作去对应
也就说我们要
设定了源和目标它的区域
设定了源和目标的指针
设定了串的长度值
最后一点就是我们的操作方向
在串操作指令里 数据的操作方向
不是通过INC或者DEC这样的指令去实现的
而是通过标志位的状态来标识的
哪一个标志位呢?
就是我们第二章讲过的三个控制标志位之一
DF标志位
它用来设定在串操作指令的时候
设定操作的方向
当DF等于零的时候
表示它是按增地址方向操作的
当DF等于1的时候 就表示按减地址方向操作
那么DF为0还是为1 你怎么知道呢?
实际上我们是通过指令可以去设定的
我们在8086指令集的最后一大类指令里头
专门有两条去设定DF状态的指令
这两条指令虽然我们在讲串操作的时候
还没学到后头
但是我们等一下做练习的时候
我们必须要拿出来用
就是用它来确定DF的状态
这几点是我们串操作指令
使用之前必须要做的一些准备工作
也就是说可以说是初始化的工作
也就包括设置源和目标的区域
源和目标的指针
设置串的长度值以及串的操作方向
和前面学的三大类指令中
所有指令不同的还有一点
串操作的指令的前面可以
添加一个叫做所谓重复前缀的这样一个符号
通过加设了重复前缀
可以控制串操作指令
在满足重复条件的情况下
不断的重复执行下去
所以这一句话意味着什么?
意味着我们未来所看到的每一条串操作指令
如果它加了前缀的话
这一条指令就是一个循环程序
或者说一个循环结构
下边我们来看一下什么是重复前缀
重复前缀有两种大的类型
一种我们称为无条件重复
一种称为条件重复
无条件重复前缀呢 它的助记符是REP
也就是Repeat的缩写
这个前缀的含义是
当CX不等于零 也就说
串的操作没有结束
或者说串的长度值没有被减到零的时候
那么当然就意味着串的操作没结束了
那么这个时候它会控制
它后边跟的那条串操作指令
重复地执行下去
无条件重复前缀呢 因为它
没有任何其他的条件
它只要这个操作没有结束
也就是CX不等于零
它就会控制它后边的指令重复地执行
所以无条件重复前缀的后边
通常跟的是传送类的指令
也就说只要操作没有结束
这条传送类的指令就会一直重复地传送下去
直到传送结束为止
条件重复前缀呢 一共有两小条
一条叫做相等则重复的前缀
它的助记符的表现形式可以有两种
一种叫REPE 一种叫REPZ
它们是一样的意思
E是Equel的意思 Z就是Zero
那么就是Zero就是相减为零
那么就显然是相等了
所以它们的意思都有着一种运算的含义
在里头
相等则重复的前缀
控制它后边指令能够重复执行下去的条件
是这样
就说CX不等于零
并且ZF等于1
这个是它
在这种条件下
它后边的指令就会重复执行下去
另外一条条件重复前缀是
不相等则重复的前缀
它的助记符
是REPNE或者REPNZ
这个N就是Not的意思
它的重复条件是
CX不等于零并且ZF等于零
从这个重复条件的这个表达上
我们可以感觉到
条件重复前缀一定针对的是
有运算性质的指令
所以条件重复前缀的后边
一定跟的是一种运算类的操作指令
因为只有运算特别是有相减运算
它的才有可能去判断
它们是相等还是相减为零
这是这两种性质的前缀
这个前缀呢 在我们整个8086指令集里头
只有串操作指令的前边
可以加这样的前缀
好下边我们就来正式开始学习串操作指令
串操作指令一共有五条
分别是串传送 串比较
串扫描 串装入和串送存
大家先看前面两条
串传送和串比较
我们如果把后边这个S去掉
其实就是MOV指令和CMP指令
这里的S就是String的意思
因此
串传送和串比较指令
实际上它们的执行原理
就完全类似于MOV指令和CMP指令
我们后边学习完 大家会感觉到
这两条指令实际上也完全可以用
MOV指令和CMP指令去取代
当然在复杂性上
或者说指令代码的行数上
用MOVS和CMPS指令要相对简单一点
后边的这条串扫描指令
它执行的是和串比较指令
类似的工作
只不过串比较呢是实现的是
两个数据串的比较
而串扫描呢
是在一串数据中去查找关键字
因此这个时候它的源数据
不再是一个数据串
最后的两条串装入和串送存
它们执行的就是传送
也就说它的执行原理跟串传送也是
非常类似的
因为我们下边会重点的介绍
串传送和串比较
其他的三条指令
在上面两条学清楚的情况下
底下三条也就自然地就理解了
由于串操作指令所
它的操作对象的特殊性
因此在使用这些指令
编写程序的时候
会有一些
固定的一些格式
或者说它们有一些相近的
控制流程
下边我们在学习具体的串操作指令之前
我们首先来
看一下串操作的控制流程
按照我们之前的分析
我们需要首先确定串的区域
也就说源串存在哪个区
目标存在哪个区域
这里的区域实际上就是逻辑段
那么我们已经知道
串操作指令要求
目标操作数必须在附加段
指针必须由DI来给出
源串一般在数据段
指针必须由SI来指定
因此呢 我们在
真正利用这些指令编写程序的时候
我们通常不必要再去考虑
串的存放区域了
因为目标串已经没有可调整的空间了
源串呢 我们
在没有很特殊的需求的情况下
我们也都采用它默认的
这种设置 也就是说源串在数据段
因此呢 我们在程序控制流程里
我们首先需要考虑的是
取源串和目标串的首地址
然后就是设置它的长度值
以及它的操作方向
这四个步骤是所有串操作指令
都必须要有的共同的一些初始化的工作
在这些初始化的工作结束之后
我们下边就可以完成一次串操作了
虽然串操作指令针对的是一串数据
或者说一块数据的操作
我在这里一再地说这个一串或者一块
在高级语言里头字符串和一个数据
它还是有在表达形式上是不一样的
但是 到了底层
不论是数据也好字符也好
实际上都是二进制码
所以在我们这个低级指令系统中间
我们不再去区分到底它是字符还是数值
反正都是0和1
虽然串操作指令针对的是
这样一串数据的这种操作
但是呢
所有的CPU它的数据总线的宽度是受限的
不论是我们今天的64位的总线
还是我们现在学的8088这样的一个8位的总线
或者是8086的16位的总线
总而言之它都不可能是
无穷的或者是过大的
因此呢
虽然串操作指令可以针对的是
一串数据的操作
但是在底层它还是只能是
一字节或者两字节或者多个字节这样的操作
在我们这个8088或者8086这样的指令集里头
它一次只能完成一个字节
或者是两个字节的操作
因此在初始化工作结束之后
指令会先完成一个字节或者一个字的操作
我们用串传送来打个比方
我们现在先回忆一下我们用MOV指令
来实现将一串数据
传到另外一个区域中
那么它的工作过程
在初始化结束之后
首先就是完成一个字节或者一个字的传送
之后呢
因为要准备传送第二个字节或者第二个字
所以它要修改地址指针
因为已经完成了一个字节或者一个字的传送
所以它的长度值要修改
也就是要减
然后呢 我们要去判断
它到底传送完了没有
传送完还是没有完就看
长度值减到零或者没有减到零
所以下边的工作就是
去判断到底传送结束了没有
那么如果结束了 那这个工作就结束了
如果没有结束呢
因为这个时候指针已经经过修改
所以这个时候
程序要转回去 继续下一个字节或者字的传送
这个是我们如果用MOV指令来实现一个
一串数据到另外一个目标地址的传送的话
这个完整的一个控制流程就是这样
同样的 如果我们完成两个数据串的比较
也是一样的这样的一个步骤
在我们用MOV或者用
CMP指令来完成这种操作的时候
这里的地址指针的修改 我们之前看到的
通常是INC指令
对修改长度值我们通常是用DEC指令来实现的
那么在串操作指令中间
整个这样一个框
如果加上前缀的情况下
它就是一条指令来完成的
这两步是串操作指令本身来完成的
也就说如果我们去做串传送的话
它会首先完成一个字节或者一个字的传送
然后这条指令 这条串操作指令本身
就自动的实现指针的修改 就指针加1
或者指针加2
当然也可能指针减1或者减2
如果加前缀的话
前缀会完成这样两个步骤的工作
也就是说前缀会自动的修改CX的值
就相当于前缀会去执行一条DECCX
然后呢再去判断CX的值到底零还是没等于零
因为等于零 那么就是完成这个传送了
如果没等于零 那就没有完成
当然在串比较中
这里不仅仅
取决于到底是CX为不为零
它还有其他的条件 也就是前面我们说的
还要看ZF的状态
总之由前缀来完成对CX值的修改
并且去判断
到底现在还满足不满足
继续重复执行的条件
如果满足 那么程序会
自动地再回到原来的地方继续下一个
字节或者字的操作
如果不满足
那么就退出了
因此
在这里头我们可以看出来
如果不加前缀的话
一条串操作指令
是不能够构成一个循环结构的
只有加了重复前缀
这个循环结构才能够真正的构成
这是有关串操作指令的控制流程
从这个控制流程里我们还要看一点
就是说
我们每一次操作
都是先完成了一个字节或者一个字的操作
然后呢
它并没有马上去判断
是不是还满足重复执行的条件
而是要先修改地址指针
再修改串的长度值
然后再去判断是不是还可以继续重复
这一点非常重要
因此 我们用一个图来继续描述一下这个问题
假设我们现在
源串上面再是源串
指针SI指向源串的首地址
DI指向目标串的首地址
假设我们现在做一个串的传送
那么在传送到最后一个
字节的时候 SI会指向现在
黄颜色这个字符的地方
那么DI呢 当然也指向目标串最后一个单元
这个时候
CX会等于1
好 现在我们把刚才流程图右边这几个框
我们再继续拿过来看一下
因为现在CX修改完了以后等于1
那么现在再去判断满足不满足
继续重复的条件呢?
当然满足 因为CX还没有等于零
因此呢
它就会继续走向这个地方
完成下一个字节的传送
也就是说 这个时候会把黄颜色的这个字符
传到DI所指向的地址里
传送完了以后 这个时候它并没有判断
现在是不是还需要继续重复
而是首先会修改地址指针
也就是说这个时候SI会加1
DI也会再加1
这个时候
相当于指向了我们源串
最后一个单元加1的这个位置
目标的这个偏移地址或者说目标指针呢
也指向了目标串
最后一个单元加1的位置
这个时候才去修改
串的长度值也就说这个时候CX才等于零
然后接着去判断
还满足不满足重复条件呢?
显然这个时候就不满足了
程序才退出执行了
因此
在串操作指令里头
如果按增地址方向操作的话
串操作结束的时候
如果是串传送
指针会指向串尾加1的这个位置
如果是串比较类指令
因为串比较 不一定是因为
比较结束了 也就说它
不一定是因为CX等于零退出比较
而有可能是
虽然CX不等于零
但是ZF的状态不满足重复的条件
所以呢 这个时候
指针会指向结束位再加1的位置
如果按减地址方向操作
它们就会分别指向减1的位置
这一点在未来大家
具体学习串操作指令的时候
一定要注意 我们到时候还会通过示例
为大家强调这一点
-第1讲 关于本课程
--关于本课程
-第2讲 微型计算机系统
--微机系统_01
--微机系统_02
-第3讲 微型计算机一般工作过程
-第4讲 数制与编码
--计算机中的编码
-第5讲 计算机中数的表示与运算
--数的表示
--符号数的表示
--数的表示与运算
-第6讲 基本逻辑运算与逻辑电路
-第7讲 本周小结
--本周小结
-第1周 微型计算机基础概论--第一周单元测验
-第8讲 8088微处理器
-第9讲 8088 CPU主要引线及机构
-第2周 8088微处理器--第二周单元测验
-第10讲 实模式存储器寻址
-第11讲 8088系统总线
--8088系统总线
-第12讲 微处理器小结
--微处理器小结
-单元测验--作业
-第13讲 指令概述
--指令概述
-第14讲 寻址方式
--寻址方式
-第15讲 通用数据传送指令
-第16讲 地址传送指令
--地址传送指令
-第17讲 输入输出指令
--输入输出指令
-第4周 数据传送指令--第四周单元测验
-第18讲 算术运算指令
--加法运算指令
--减法指令
--乘除运算指令
-第19讲 逻辑运算指令
-第20讲 移位操作指令
--移位操作指令
-第5周 算术运算、逻辑运算与移位操作指令--第五周单元测验
-第21讲 关于串操作指令的说明
--串操作指令说明
-第22讲 串传送与串比较
--串传送与串比较
-第23讲 串扫描指令
--串扫描指令
-第24讲 串装入与串存储指令
-第六周单元测验--作业
-第25讲 程序控制指令说明
-第26讲 转移类指令
--无条件转移指令
--条件转移指令
-第27讲 循环控制指令
--循环控制指令
-第28讲 过程调用指令
--过程调用指令
-第29讲 中断指令
--中断指令
-第30讲 处理器控制指令
--处理器控制指令
-第31讲 指令系统小结
--指令系统小结
-第7周 程序与处理器控制--第七周单元测验
-第7周 程序与处理器控制--第七周作业
-第32讲 汇编语言源程序
-- 汇编语言源程序_01
-- 汇编语言源程序_02
-第33讲 伪指令
--数据定义伪指令
--其它伪指令
-第34讲 系统功能调用
-第35讲 汇编语言程序设计示例详解
--程序设计示例1
-第36讲 汇编语言程序设计小结
-第8周 汇编语言程序设计--第八周单元测验
-第8周 汇编语言程序设计--第八周作业
-第37讲 半导体存储器概述
--半导体存储器概述
-第38讲 内存单元编址
--存储单元编址
-第39讲 随机存取存储器RAM
-- RAM_01
--RAM_02
-第40讲 只读存储器ROM
--ROM_01
--ROM_02
-第九周单元测验--作业
-第41讲 半导体存储器扩展
--存储器扩展_2
-第42讲 半导体存储器小结
--半导体存储器小结
-第十周单元测验--作业
-第十周作业--作业
-第43讲 基本I/O接口
-第44讲 简单接口芯片
--简单接口芯片
-第45讲 基本输入输出方法
--基本I/O方法
-第46讲 简单I/O控制系统设计
-第47讲 中断技术
--中断技术1
--中断技术2
-第48讲 输入输出与中断技术小结
--本周小结
-第十一周单元测验--作业
-第49讲 可编程定时计数器
-第50讲 可编程并行接口
-第51讲 可编程接口小结
--本周小结_01
--本周小结_02
-第十二周单元测验
-第52讲 模拟量的输入输出
--模拟量的输入输出
-第53讲 D/A转换器
-第54讲 A/D转换器
-- A/D转换器_01
-第十三周单元测验--作业
-第55讲 I/O接口系统综合设计示例详解I
-第56讲 综合设计示例详解II
-第57讲 结束语
--结束语