`
omygege
  • 浏览: 1357766 次
文章分类
社区版块
存档分类
最新评论

REPNE SCAS BYTE PTR ES:[EDI] 指令详解

 
阅读更多

在OD中看到一段汇编中有如下指令:
REPNE SCAS BYTE PTR ES:[EDI]
查了下.说是 扫描 ES:[EDI]字符串中的 AL值.值到找到AL值后停止.
听得一知半解.自已用VC写段类似的汇编跟了一下.才算是明白了.

LPSTR pstr="12345678";
DWORD strCount=0;
__asm{
xor eax,eax ;清0 eax.因为这个指令经常是用来得到字符串长度的.C中的字符串又是根据 /0来判断结束的.
or ecx,0xFFFFFFFF;//不明白.... 我是理解为 ecx=-1
mov edi,pstr;// EDI中现在是字符串的首地址了
repne scas BYTE PTR ES:[EDI];//在字符串中查找 AL值(AL=0) 这个指令会让ECX增加,也会让EDI增加.
mov strCount,ecx;//这时的ECX不是长度.是 0xFFFFFFF6 (这应该是表示一个负数)
not ecx ;//这才是正确的数了.这才是正数.(ECX=0x9) 为什么是9 ?因为把最后一个空字符也算进去了.
//所以一般下面都会跟一句 dec ecx. 来减一.这样才是字符的长度.
sub edi,ecx ;//把EDI 指回字符串的首地址.
mov strCount,ecx
}


今天在分析一个crackme的时候遇到一条指令感觉不是很熟悉,查询了一些资料进行了学习,顺便做下笔记,方便以后查看,也方便给需要的人。
具体的代码如下:
004015E9 . 8D7C24 20 lea edi,dword ptr ss:[esp+0x20]
004015ED . 83C9 FF or ecx,-0x1 ; 将ecx 赋值为FFFFFFFF
004015F0 . 33C0 xor eax,eax ; EAX 清零
004015F2 . 895424 28 mov dword ptr ss:[esp+0x28],edx
004015F6 . 33F6 xor esi,esi ; ESI清零
004015F8 . F2:AE repne scas byte ptr es:[edi]
004015FA . F7D1 not ecx
004015FC . 49 dec ecx
看到上面有一条指令repne scas byte ptr es:[edi],原来一直很少见到,于是查询了一番,在看雪找到了相关的解答,原地址:
原文
有下面的一些解答,总结如下:
1、即:repnz scasb(32位地址操作)。扫描es:edi指向的一系列字节数据,扫描长度由ecx指定,当遇到与al中的数据相等时停止扫描。
2、最经典的求字符串长度的代码,strlen()在VC优化编译模式是这段代码。
3、得到的字符串最后存放在ecx中。
详细分析步骤如下(修改了论坛中的一点错误):
重复前缀指令
任何一个串操作指令,都可以在前面加一个重复前缀,以实现串操作的重复执行,重复次数隐含在CX寄存器中
REP;REP前缀用在MOVS、STOS、LODS指令前,每次执行一次指令,CX减1;直到CX=0,重复执行结束
REPZ ;也可以表把为REPE,用在CMPS、SCAS指令前,每执行一次串指令CX减1,并判断ZF标志是否为0
;只要CX=0或ZF=0,则重复执行结束
REPNZ ;也可以表达为REPNE,用在CMPS、SCAS指令前,每执行一次串操作指令CX减1,并判断ZF标志是否为1,只要CX=0 或ZF=1,则重复执行结束。

串扫描指令SCAS
SCASB ;字节串扫描:AL-ES:[DI],DI←DI+/-1
SCASW ;字串扫描:AX-ES:[DI],DI←DI+/-2
串扫描指令SCAS将附加段中的字节或字内容与AL/AX寄存器内容进行比较,根据比较的结果设置标志,每次比较后修改DI寄存器的值,使之指向下一个元素。

解释:
假设esp+10指向字符串如:"xqiang",长度为6,以0结尾
ecx=FFFFFFFF
eax=0,则al=0
执行repne scas时候:
第一次:
al-'x',di=di-1,即byte ptr es:[edi]指向'q',并置相应的标志位
然后cx-1,则ecx=FFFFFFFE,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第二次:
al-'q',di=di-1,即byte ptr es:[edi]指向'i',并置相应的标志位
然后cx-1,则ecx=FFFFFFFD,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第三次:
al-'i',di=di-1,即byte ptr es:[edi]指向'a',并置相应的标志位
然后cx-1,则ecx=FFFFFFFC,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第四次:
al-'a',di=di-1,即byte ptr es:[edi]指向'n',并置相应的标志位
然后cx-1,则ecx=FFFFFFFB,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第五次:
al-'n',di=di-1,即byte ptr es:[edi]指向'g',并置相应的标志位
然后cx-1,则ecx=FFFFFFFA,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第六次:
al-'g',di=di-1,即byte ptr es:[edi]指向'0',并置相应的标志位
然后cx-1,则ecx=FFFFFFF9,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第七次:
al-0,di=di-1,即byte ptr es:[edi]指向'未知字符',并置相应的标志位
然后cx-1,则ecx=FFFFFFF8,判断是否cx=0或ZF=1,此时ZF=1,停止串搜索
现在ecx从FFFFFFFF到FFFFFFF8记录了字符串'xqiang'和0的长度
然后not ecx得到ecx=00000007
dec ecx得到ecx=00000006 该长度就是字符串'xqiang'的实际长度

分享到:
评论

相关推荐

    android 脱壳视频教程

    0040E9F4 F2:AE repne scas byte ptr es:[edi] 0040E9F6 55 push ebp 0040E9F7 FF96 A4EC0000 call dword ptr ds:[esi+ECA4] 0040E9FD 09C0 or eax,eax 0040E9FF 74 07 je short NOTEPAD.0040EA08 0040EA01 8903 mov...

    8086寻址方式及指令系统

    3.设DS=2000H,ES=3000H,SI=200H,指令MOV ES:[SI],AL的目的操作数的物理地址为( )。 A.20200H B.30200H C.50200H D.200H 4.指令MOV MEM[BX],AX中的MEM是( )。 A.原码 B.反码 C.补码 D.移码 5....

    汇编指令(chm格式)

    REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复. REPC 当CF=1且CX/ECX<>0时重复. REPNC 当CF=0且CX/ECX<>0时重复. 五、程序转移指令 ──────────────────────────────...

    Microsoft Library MSDN4DOS.zip

    REP/REPE/REPZ/REPNE/REPNZ Repeat Following String Operation RET Return from Procedure SAHF Store AH into Flags SAL/SAR/SHL/SHR Shift Instructions SBB Integer Subtraction with Borrow SCAS/SCASB/SCASW/...

    The Art of Assembly Language Programming

    Declaring and Accessing Scalar Variables 5.3.1 - Declaring and using BYTE Variables 5.3.2 - Declaring and using WORD Variables 5.3.3 - Declaring and using DWORD Variables 5.3.4 - ...

Global site tag (gtag.js) - Google Analytics