代碼摘自delphi的Pos函數。。。總的來說,若我了解無誤的話,該函數才用的搜尋機制并不是非常高明。。。隻是簡單的使用了一個倒序搜尋,僅此而已。。。但其速度優于BM,應該是由于其對CPU的優化。。。
首先先介紹一下register 調用約定: 從左到右,優先使用寄存器(EAX,EDX,ECX),然後使用堆棧!這個調用約定和C++裡面的__fastcall有些類似,不同的是__fastcall優先使用的隻有ECX和EDX。這兩種調用約定應該說是最快速的調用約定。。
再貼一部分比較重要的源碼,,源碼都注釋過,,也沒什麼解釋的。。
開始為準備做工作:
push ebx ;保護ebx esp-4
push esi ;保護esi esp-4
add esp, -16 ;esp-16 char* i,j,b,p;
test edx, edx ;測試被搜尋字元串
jz @NotFound
test eax, eax ;測試要搜尋的子串
mov esi, [ebp+8] ;esi = strLen
mov ebx, ecx ;ebx = substrLen
cmp esi, ebx ;strLen < substrLen 則跳出
jl @NotFound
test ebx, ebx ;substrLen == 0 則跳出
jle @NotFound
dec ebx ;substrLen--
add esi, edx ;
add edx, ebx ;指向開始比較的位置。str偏移為strlen(substr)的位置,比較關鍵,後期字元串搜尋和這個指針有密切的關系
mov [esp+8], esi ;j指向被搜尋字元串的尾部
add eax, ebx
mov [esp+4], edx ;i指向要搜尋子串的尾部位置
neg ebx ;ebx,substrLen長度減一的補碼
movzx ecx, byte ptr [eax] ;ecx = substrLen[0]
mov [esp], ebx ;[esp] = ecxc
jnz @FindString
開始具體的搜尋:
@FindString:
sub esi, 2 ;
mov [esp+12], esi ;p = strLen-2,指向被搜尋字元串後輸2的位置
@FindString2:
cmp cl, [edx] ;
jz @Test0 ;
@AfterTest0:
cmp cl, [edx+1]
jz @Test1
@AfterTest1:
add edx, 2 ;str = str + 2;
cmp edx, [esp+12] ;
jb @FindString4 ;從後向前比較如果在從後數兩位以上則執行每四位比較一次的操作
cmp edx, [esp+8] ;
jb @FindString2 ;如果後面隻剩了兩位,則隻能進行最後兩位的操作。
xor eax, eax
jmp @Exit1
(Test0 , Test1 , Test2 , Test3操作相同,隻是調整了一下指針的位置,隻是調整了一下指針的位置)
其它的感覺也沒什麼好注釋的,在上面可以看到,這個算法其實思路非常簡單,個人感覺,如果用這種優化方式來實作sunday算法的話,還可以讓速度再次增加。。。