串处理指令一般与REP指令配合。 因为串操作指令其实只是对 “串”主要就体现在REP上 REP是前缀,但它不是伪指令,REP有具体功能,它可以判断CX是否为0,还可以执行CX=CX-1 CX的递减不影响标识位
串传送类指令不影响标志位。 也就是说 MOVSB、MOVSW、MOVS; LODSB、LODSW、LODS; STOSB、STOSW、STOS 都不影响标志位。 但是它们受到方向标志位DF的影响。 很好的关于指令影响标志位的百度文档。
REP重复串操作直到CX的内容为0为止 请注意,REP是前缀,但它不是伪指令,因为它有具体功能。像上面列出的判断CX是否为0,让CX-1等都是它的功能。 还要注意CX的递减不影响标志位。
MOVSB和MOVSW不需要有操作数,因为他们的操作数都是定好了的。 就是ES:DI⬅DS:SI(注意箭头方向) 不同的就是转移的是字节还是字
注意BYTE PTR和WORD PTR 它们用于指明字节 MOV ES:DI DS:SI 有一个操作数写明WORD PTR或BYTE PTR就行了。
MOV这种指令,起码有一个操作数一定要是位数清晰的,如果不清晰明确,就要指明 像PUSH,POP这种指令,就不需要指明,因为它们就只做字操作。
方向标志位DF决定串传送的方向。 SI和DI加一或者减一,这是由DF决定的。 如果CLD了,DF=0了,那就是SI+1和DI+1
一般来说,源串存放在数据段中,目的串存放在附加段中。 使用REP重复前缀前,要把数据串长度放入CX 回忆一下移位操作,如果移位次数大于1,也要将移位次数放入CL
做准备工作不要忘记设置方向标志 CLD——使DF=0——增地址——先传小地址 STD——使DF=1——减地址——先传大地址
先判断是否为0,再减1,再执行传送操作 REP MOVSB REP MOVSW 这两条语句都不影响标志位。
例一 例二 17,也就是不包括$ $在汇编中是字符串结束的标志 $在字符串中显示不了,如果偏得要他显示那就得找别的方法。 REP MOVSB 先判断CX是否为0,CX=17,显然不为0,于是CX-1=16,再执行传送字节的操作,然后SI+1,DI+1,再判断CX是否为0,再减1,再执行传送字节操作,直到CX减到0,判断的时候发现CX是0,就停止操作 简洁的总结一下:
首先判断CX是否为0 不等于0的话
CX-1传送字节SI±1(或2),DI±1(或2)再判断CX是否为0 如此循环 一开始SI和DI指向要被复制和填充的第一个单元,最后SI和DI指向被复制和填充的最后一个单元的下一个单元。
注意存入字节的话,用的是AL 其实我感觉这种情况下,用的一般都是AL哈
STOS是存进去一堆一样的,可以用于初始化。 注意执行完之后,DI是指向最后一个单元的下一个单元。 20H是空格的ASCII码
LODS拿出来的只能存在AX里 所以与REP连用是没有意义的 最后AX中只有最后拿出来的那一个 就像狗熊掰苞米,最后夹在咯吱窝里的只有哪一个了。 注意高字节在高地址,低字节在低地址
与REPE/REPZ和REPNE/REPNZ联合工作的串比较指令CMPS和SCAS REPE/REPZ和REPNE/REPNZ中CX的递减不影响标志位(即使CX减到零,也不影响)。 CMPS/SCAS则根据减法的结果设置标志位。 说实话这里,还有前面的STOS之类的,可能基本概念你掌握了,但是应用还是不熟练的,这个我们之后再补充,比如说 LODS SRC 这个用法你还是不知道怎么用啊 (虽然这个用法可能也不常见) 总之我们之后再通过实践来补充吧。但是这块的实践可是也不简单!加油!
注意: 字符串比较,关键的唯一的条件是ZF 如果只有最后一个字节不同,CX=0后退出重复。这个时候你还是要看ZF!如果你看到CX=0就觉得比较完了他俩都一样,这是不行的,你必须看ZF,如果ZF=0,就说明最后一个字节不同;ZF=1,就说明最后一个字节相同。 其实不止是最后一个字节,每个字节的比较的结果都要看ZF才能看出来 关键在于CX=0是退出条件,CX不能体现字符串比较出的结果,CX=0只能说明每一个都比完了,至于结果,结果唯一的条件就是ZF
REPE和REPZ是完全相等的同义词!两者可以随意相互替换。 E-Equal 相等 Z-ZF 相等的话,结果为0,ZF就等于1(这里真的好容易犯糊涂),因此从字面上也能看出虽然指令有一个字母的不同,但它们的意思是一样的。 REPE/REPZ——相等则重复,也就是说 ZF=1且CX≠0时重复 ZF=1,表示结果为0,两数相等;CX≠0,表示任务还没结束,还没扫描到字符串的结尾。 常用于比较指令 如果一直扫描到最后,我们就可以说这两个字符串完全相等。 执行的操作是先判断CX是否为0,ZF是否为0,CX=0,ZF=0两个条件满足一个就退出。否则继续向下,CX=CX-1,执行其后的串指令。 重复上述过程。 注意CX的递减不影响标志位。 DF决定先查小地址还是先查大地址 DF=0:先查小地址,增地址 DF=1:先查大地址,减地址 CLD使DF置0 STD使DF置1
同样地,REPNE和REPNZ也是完全相等的同义词!两者可以随意相互替换。 REPNE/REPNZ——不相等则重复 ZF=0且CX≠0时重复 ZF=0,表示两数相减结果不为0,两数不相等;CX≠0,表示任务还没结束。 退出条件: 常用于查找指令 比如要在一个很长的字符串里找到空格,就用REPNE或REPNZ,不相等会重复,相等时就停下。 执行的操作是先判断CX是否等于0,ZF是否等于0,CX=0,ZF=1满足其中一个就退出,否则向下执行,CX=CX-1,执行其后的指令。 重复上述操作。 注意CX的递减不影响标志位。
用源串中的一个字节(或者字)减去目的串中的一个字节(或者字) 因为做了减法,结果很显然会对标志寄存器产生影响,如果结果为0,ZF标志位会等于1
用AL中的字节(或者字)和附加段中的字符串中的一个字节(或者字)做减法。 要记住8086的内存是以8位的字节为单位来组织的。
DS和ES重叠,注意要从下面开始传送,注意串传送是从数据段传到附加段。 所以它这里说的向前移动一个不是图片上的向前,指的是地址上向前,而且移动的是一个字,也就是两个单元。 如果从P开始传送,因为DS和ES是重叠的,P会覆盖掉R,SI和DI向下再向下后指向的单元的内容还是P,这就不对了。 如果从下面开始,S先放到比S大两个字节的地方(这个地方原来是空的),R再放到比S原来的地方大一个字节的地方,这样是对的。
源串首地址送DI 请注意EXIT后的内容 先DEC DI,再将DI送BX 因为REPNE中,先看CX是否为0,然后CX-1,然后做减法,然后DI+1 这一串都做完之后,判断是否达到退出重复的条件,如果达到了条件,就向下执行,然后才到 JZ EXIT 要明白,SCASB只是一条指令而已!做重复的是REPNE,REPNE是ZF等于0时重复,也就是结果不为零,相减的两个数不相等的时候重复。找到#的时候ZF=0了,REPNE就不重复了,就执行下面的JZ EXIT。 当然不重复还有一种可能是都扫描完了也没找到#,这个时候也结束重复,执行下面的JZ,但是因为此时ZF=0,所以不会跳转。 找到#的话,JZ EXIT会跳转。 但是此时DI指向的是#的后面一个单元,因为SCAS做完减法后紧接着就会让地址DI+1。 因此要让DI-1,这才得到#字符(一个8位的字符)所在的地址。
