文章目录
一、重复指令(REP、REPE、REPZ、REPNE、REPNZ)
满足条件就一直重复执行(重复前缀后边的)串操作指令
分为:
无条件重复前缀 ——> 用于 传送类
指令
条件重复前缀 ——>用于 比较类
指令
二、串操作指令
2.1使用串操作注意点
针对字符串或数据块
的操作。源操作数称为源串,目标操作为目标串
- 目标串必须在
附加段
,源串默认在数据段
(允许段重设)。 - 源串和目标串指针分别为
SI
和DI
- 串长度值必须由
CX
给出 - 需要通过设置
DF
的状态,确定数据的操作方向 - 串操作指令前可以加
重复前缀
(重复前缀必须与串指令一块使用,不能单独使用)
2.2 串操作指令流程
2.3 CLD 和 STD 指令
CLD 表示将 DF 清零; STD 表示将 DF 置1
2.4 正题
① 串传送指令 MOVS
首先是串传送:MOVS ,更具体地说,应该分成两种: MOVSB
和 MOVSW
MOVSB
顾名思义就是传送1个字节(也就是8位)的串;
而 MOVSW
则是传送 1个字的串。
我们看一个例子学习它的用法:
使用 MOVS指令,将200个字节数据从内存数据段 MEM1 为首地址的区域送到一个逻辑段 MEM2为首地址的区域:(我们下面给出程序的分析):
方案一:
LEA SI, MEM1 //源串的串首地址 给SI寄存器
LEA DI MEM2 //目标串的串首地址 给 DI 寄存器
MOV CX 200 //给 串的长度赋初值(要赋值给 CX)
CLD //令 DF = 0,说明是从低地址向高地址执行
REP MOVSB //无条件重复:只要 CX ≠0 就一直执行串的传输
HLT //当REP跳出来了,就结束
当然也是可以用 MOVSW
的,这样的话,我们的 CX 就要赋初值为 100 了,因 MOVSW
一次操作16位
方案二:
② 串比较指令 CMPS
同样地,CMPS 也分为:CMPSB
, CMPSW
。
它执行的是啥呢?—— 目标串 - 源串,但是结果并不返回目标串。就是实现两串的比较。
对于串比较指令,我们一般在它前面加条件前缀。
那么,依旧是刚刚的例子,我们在传输完了 200 个字节的串之后,想要检测一下是否正确传输,我们就需要比较两个串了:下面是程序分析:
LEA SI, MEM1
LEA DI MEM2
MOV CX, 200
CLD //上面四条语句全都是初始化
REPE CMPSB
JZ STOP //JZ 表示当 ZF = 1 时执行跳转,执行到这里如果ZF仍然为1说明两串一样
DEC SI //完成SI的自减,回顾上面的流程图,SI现在是在串低的后一位
MOV AL, [SI] //取出SI中地址所指向的内容 就是不同数据的值
MOV BX, SI //取出SI寄存器中的地址 就是不同数据的所指向的地址
STOP: HLT
首先,我们明确一件事情:REPE 的意思是相同即重复( CX≠0,且 ZF = 1 ),也就是说当比较的串一样时,就继续比
。那么 REPE 退出的情况有什么呢?
- CX = 0(说明比完了,那么就是两个串完全一样)
- CX ≠ 0 ,但是 ZF = 0 (说明在中间有两个串不一样的地方了)
JZ 表示当 ZF = 1 时执行跳转,跳转到 STOP
CMPS 例题2
到黑色箭头就不在执行REPZ后面的串比较指令CMPSB,并且 指针+1 —>所以SI= DATA1 +5 、DI= DATA1 +5
执行一次比较,cx就减1,故还剩1
ZF=0说明不相等
③ 串扫描指令 SCAS
SCAS也分为 SCASB
,SCASW
。
当我们使用时,源操作数是不用写出来的,但是要在程序的前面声明。源操作数是 AL 或者 AX。
当使用 SCASB时,一次操作一个字节单元,源操作数就是 AL
当使用 SCASW时,一次操作一个字单元,源操作数就是 AX
另外,说一下 SCASB,SCASW 都干了什么:
以 SCASB 为例,它执行的是将 AL 里面存放的字节
依次和串内的每一个字节单元
相减,但是结果不返回,影响标志位 ZF
用于搜索串里面,有没有哪个字节单元的内容和 AL 的一样。
举一个例子:在 ES段中从 2000H 单元开始存放了 10 个字符,寻找其中有没有字符 ‘A’,若有则记录搜索次数,将搜索次数写入 DATA1 单元,并将 ‘A’ 写入 DATA2 单元。
首先,我们要明确一件事情:目标串地址在 ES:DI 里面。
MOV DI, 2000H //先给DI 赋值
MOV BX, DI //地址备份,用于后面计算搜索次数
MOV CX, 10 //因为如果采用SCASB,那么就是一个字节一个字节搜索,10次
MOV AL, 'A'
CLD
REPNE SCASB //“若不相等则重复”,如果不相等,即ZF = 0 ,那么就一直搜索
JZ FOUND //若 ZF = 1 就跳转到 FOUND(ZF=1 说明找到一样的了)
MOV DI, 0
JMP DONE
FOUND: DEC DI //因为 DI 是先自增之后才进入判断的,所以在跳出之后DI 会在 'A' 的后一个单元
MOV DATA2, DI //‘A’ 写入 DATA2 单元。
INC DI
SUB DI, BX //计算搜索次数
DONE: MOV DATA1,DI
HLT
④ 串加载 LODS 与 串存储 STOS
如果使用的是 LODSB
,那么它执行的操作是:将数据段中地址为SI 的单元装入 AL;
如果使用的是LODSW
,那么它执行的操作是:将数据段中地址为 SI 的单元装入 AX;
如果使用的是 STOSB
,那么它执行的是:将 AL 里面的内容存储进 [ES:DI] 内
如果使用的是 STOSW
,那么它执行的是:将 AX 里面的内容存储进 [ES:DI] 内