串操作指令可以方便对一组连续的数据进行操作。串操作后自动根据DF标志位修改ESI和EDI,DF = 0时,ESI,EDI递增,DF = 1时,ESI,EDI递减。串操作指令有2组,1组实现数据串传送,另1组实现数据串检测。串操作指令通常需要反复执行,所以常与重复指令前缀联合使用,它通过计数器ECX控制重复执行串指令的次数。
1.串传送指令
这组指令实现对串的传送,它们有,MOVS,STOS,LODS,可以配合REP前缀,但不影响标志。
MOVSB ;BYTE PTR[EDI] = BYTE PTR[ESI]
MOVSW ;WORD PTR[EDI] = WORD PTR[ESI]
MOVSD ;DWORD PTR[EDI] = DWORD PTR[EDI]
STOSB ;BYTE PTR[EDI] = AL
STOSW ;WORD PTR[EDI] = AX
STOSD ;DWORD PTR[EDI] = EAX
LODSB ;AL = BYTE PTR[ESI]
LODSW ;AX = WORD PTR[ESI]
LODSD ;EAX = DWORD PTR[ESI]
REP重复指令前缀,可以表示为当ECX != 0时,则继续执行,直到ECX = 0。可以说,ECX指明了重复次数。如果不使用REP前缀,那么串指令其实是只被执行1次的,这是很多新手易出错的地方。
比如,我们可以使用串传送指令代替ZeroMemory。
结合上篇文章,我们可以定义一个宏,程序源码如下:
ZeroMem MACRO Addr,Size cld ;;CLD标志位清0,表示递增正向传输 xor al,al mov edi,Addr mov ecx,Size rep stosb endm
调用格式如下:
ZeroMem 数据串地址,长度
2.串检测指令
这组指令包含有CMPS和SCAS。由于串比较指令和减法的实质是一样的,所以它们也影响标志位。这两个串操作指令可以和REPE/REPZ和REPNE/REPNZ联合使用,通过ZF判断是否相等。
CMPSB ;BYTE PTR[ESI] - BYTE PTR[EDI]
CMPSW ;WORD PTR[ESI] - WORD PTR[EDI]
CMPSD ;DWORD PTR[ESI] - DWORD PTR[EDI]
SCASB ;AL - BYTE PTR[EDI]
SCASW ;AX - WORD PTR[EDI]
SCASD ;EAX - DWORD PTR[EDI]
REPE/REPZ ;每执行一次指令,ECX递减1。如果ECX = 0或ZF = 0,则结束重复执行
REPNE/REPNZ ;每执行一次指令,ECX递减1。如果ECX = 0或ZF = 1,则结束重复执行
实际运用时要注意区分,串操作指令结束时因为比较完了,还是因为标志位问题。
我根据串操作指令定义了一个宏,可以代替ComapreMemory,如下:
CmpMem MACRO Addr1,Addr2,Size LOCAL n xor eax,eax mov esi,Addr1 mov edi,Addr2 mov ecx,Size repe cmpsb ;;当ZF = 0时,结束是因为有不同 jnz n ;;当两数据串完全相等时,则EAX = 1 inc eax n: endm