|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
挂下代码先,
- ;注释修改&中文注释添加 by 老刘
- ; #########################################################################
- ; 这个算法的子循环代码被EKO重新设计来反向执行比较,
- ; 这种比较方法通过分支比较减少了需要执行的指令数。
- ; #########################################################################
- .486
- .model flat, stdcall ; 32 bit memory model
- option casemap :none ; case sensitive
- StrLen PROTO :DWORD
- .code
- ; ########################################################################
- InString proc startpos:DWORD,lpSource:DWORD,lpPattern:DWORD
- ; ------------------------------------------------------------------
- ; InString函数在一个更大的“源字符串”中寻找“匹配字符串”,
- ; 如果找到了的话,“匹配字符串”在“源字符串”的位置会被放在eax中。
- ;
- ; "StartPos"即“起始位”参数和返回值均使用1来作为首个字符的索引。
- ; (第一个字符是1,第二个字符是2,等等……)
- ;
- ;
- ; 返回值:
- ; 如果函数执行成功,它将会返回“源字符串”的位置。
- ; 0 = 没找着
- ; -1 = “匹配字符串”的长度不短于“源字符串”
- ; -2 = "StartPos"参数越界。
- ; ------------------------------------------------------------------
- LOCAL sLen:DWORD
- LOCAL pLen:DWORD
- push ebx
- push esi
- push edi
- invoke StrLen,lpSource
- mov sLen, eax ;源字符串长度
- invoke StrLen,lpPattern
- mov pLen, eax ;匹配字符串长度
- cmp startpos, 1
- jge @F
- mov eax, -2
- jmp isOut ;如果“起始位”参数为0则退出。
- @@:
- dec startpos ;改成0为第一个字符的索引。
- cmp eax, sLen ;这里的eax依旧=pLen
- jl @F
- mov eax, -1
- jmp isOut ;匹配字符串不短于源字符串,退出。
- @@:
- sub sLen, eax ;sLen-=pLen源字符串去尾
- inc sLen
- mov ecx, sLen
- cmp ecx, startpos
- jg @F
- mov eax, -2
- jmp isOut ;不可能匹配上,退出
- @@:
- ; ----------------
- ; setup loop code
- ; ----------------
- mov esi, lpSource
- mov edi, lpPattern
- mov al, [edi] ;al=匹配字符串中的第一个字符
- add esi, ecx ;源字符串地址加上源字符串长(使esi指向源字符串末尾,以便倒序比较)
- neg ecx ;ecx=-ecx
- add ecx, startpos ;加上起始位参数
- jmp Scan_Loop
- align 16 ;使下条指令的地址从0x10倍数处开始,提升速度
- ; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- Pre_Scan:
- inc ecx
- Scan_Loop:
- cmp al, [esi+ecx] ;判断esi+ecx指向的第一个字符是否=匹配字符串中的第一个字符
- je Pre_Match ;如果匹配,则跳到Pre_Match继续判断
- inc ecx
- js Scan_Loop ;ecx为负时继续循环
- jmp No_Match
- Pre_Match:
- lea ebx, [esi+ecx] ;ebx=第一个匹配的字符的地址
- mov edx, pLen
- Test_Match:
- mov ah, [ebx+edx-1] ;ah=ebx+edx-1指向的字符
- cmp ah, [edi+edx-1] ;与匹配字符串中对应的字符比较
- jne Pre_Scan ;不匹配,跳到Pre_Scan
- dec edx
- jnz Test_Match ;edx非0时继续倒序循环判断
- ; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- Match:
- add ecx, sLen
- mov eax, ecx
- inc eax
- jmp isOut
-
- No_Match:
- xor eax, eax
- isOut:
- pop edi
- pop esi
- pop ebx
- ret
- InString endp
- ; ########################################################################
- end
复制代码
那么什么条件下可以直接判断不可能匹配呢?
我们设
a=startpos
b=sLen
c=pLen
令d=b-(a-1)
则d即为实际需要进行查找的字符串的长度,
那么当被查找的字符串长小于需要查找的字符串长度的时候,即
当(a-1)+c>b的时候,
显然不可能匹配上,
作者可谓考虑的十分周到了。 |
|