| 
 | 
 
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册  
 
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的时候, 
显然不可能匹配上, 
作者可谓考虑的十分周到了。 |   
 
 
 
 |