串操作指令
串处理:rep movs/stos/lods cmps/scas
格式:
REP string primitive
其中String Primitive可为MOVS, LODS或STOS指令
执行的操作:
1)如(CX)=0则退出REP ,否则往下执行。
2)(CX) <= (CX)-1
3)执行其中的串操作
4)重复1)~3)
CLD(Clear direction flag)该指令使DF=0,在执行串操作指令时可使地址自动增量;
STD(Set direction flag)该指令使DF=1,在执行串操作指令时可使地址自动减量。
REP MOVS BYTE PTR[DI],BYTE PTR[SI]
上面指令将[si]中的值拷贝到[di]位置,然后di和si同方向增加或者减少一个字节(由DF值决定),直到ecx中的值为0。
MOVS 串传送指令
格式:
MOVS DST,SRC
MOVSB(字节)
MOVSW(字)
其中第二、三种格式明确地注明是传送字节或字,第一种格式则应在操作数中表明是字还是字节操作,例如:MOVS ES:BYTE PTR[DI],DS:[SI]
执行的操作:
1)((DI)) <= ((SI))
2)字节操作:
(SI) <= (SI)+(或-)1,(DI) <=(DI)+(或-)1
当方向标志DF=0时用+,当方向标志DF=1时用-
3)字操作:
(SI) <= (SI)+(或-)2,(DI)
<= (DI)+(或-)2
当方向标志DF=0时用+,当方向标志DF=1时用-
该指令不影响条件码。
下面是通过汇编实现的字符串n个字节拷贝函数
void strncpy_asm(char *dst, char *src,size_t len)
{
_asm{
;mov edi,dst;
;mov esi,src;
;mov ecx,len;
mov edi, [ebp+8]//目标地址
mov esi, [ebp+0xc]//源地址
mov ecx,[ebp+0x10];//ecx里rep的次数
cld;//设置DF=0,ESI,EDI ++
rep movs byte ptr [edi],byte ptr[esi]
}
}
STOS 存入串指令
格式:
STOS DST
STOSB(字节)
STOSW(字)
执行的操作:
字节操作: ((DI)) <= (AL),(DI) <= (DI)+-1
字操作: ((DI))
<= (AX),(DI)
<= (DI)+-2
该指令把AL或AX的内容存入由(DI)指定的附加段的某单元中,并根据DF的值及数据类型修改DI的内容,当它与REP 联用时,可把AL或AX的内容存入一个长度为(CX)的缓冲区中。
LODS 从串取指令
格式:
LODS SRC
LODSB
LODSW
执行的操作:
字节操作:(AL) <= ((SI)),(SI) <= (SI)+-1
字操作:
(AX) <= ((SI)),(SI)
<= (SI)+-2
该指令把由(SI)指定的数据段中某单元的内容送到AL或AX中,并根据方向标志及数据类型修改SI的内容。指令允许使用段跨越前缀来指定非数据段的存储区。该指令也不影响条件码。一般说来,该指令不和REP 联用。有时缓冲区中的一串字符需要逐次取出来测试时,可使用本指令。
lea edi,[ebp
mov ecx,30h
mov eax,0CCCCCCCCh
rep stos dword
ptr es:[edi];
上面这段代码是C中函数调用的时候,将栈上局部变量空间,统一设置为CC的汇编代码。CC就是INT
3指令的机器码,所以,一旦有程序出现异常,执行到栈上位置,就会被中断下来,以便发现问题。
与REPE/REPZ和REPNZ/REPNE联合工作的CMPS和SCAS指令
REPE/REPZ 当相等/为零时重复串操作
格式: REPE(或REPZ)
String Primitive
其中String
Primitive可为CMPS或SCAS指令。
执行的操作:
1)如(CX)=0或ZF=0(即某次比较的结果两个操作数不等)时退出,否则往下执行
2)(CX)ß(CX)-1
3)执行其后的串指令
4)重复1)~3)
REPNE/REPNZ 当不相等/不为零时重复串操作
格式: REPNE(或REPNZ) String Primitive
其中String Primitive可为CMPS或SCAS指令
执行的操作: 除退出条件(CX==0)或ZF==1外,其他操作与REPE完全相同。
CMPS 串比较指令
格式:
CMP SRC,DST
CMPSB
CMPSW
执行的操作:
1)((SI))-((DI))
2)字节操作:(SI) <= (SI)+-1,(DI) <= (DI)+-1
字操作:
(SI) <= (SI)+-2,(DI)
<= (DI)+-2
指令把由(SI)指向的数据段中的一个字(或字节)与由(DI)指向的附加段中的一个字(或字节)相减,但不保存结果,只根据结果设置条件码,指令的其他特性和MOVS 指令的规定相同。
SCAS 串扫描指令
格式:
SCAS DST
SCASB
SCASW
执行的操作:
字节操作:(AL)-((DI)),(DI) <= (DI)+-1
字操作:
(AL)-((DI)),(DI)
<= (DI)+-2
该指令把AL(或AX)的内容与由(DI)指定的在附加段中的一个字节(或字)进行比较,并不保存结果,只根据结果置条件码。指令的其他特性和MOVS 的规定相同。
int strcmp_asm(char *s1, char *s2)
{
__asm{
mov esi,s1;
mov edi,s2;
L1:
lodsb;lodsb:[esi]<=al,esi=esi+1
scasb;scasb:al-[edi],edi = edi+1
jne L2;
test al,al;判断esi中是否到达字符串末尾
jne L1;
xor eax,eax
jmp L3;
L2:
sbb eax,eax;
or al,1;
L3:
}
}