天天看點

對pos搜尋函數的研究以及優化思路···

代碼摘自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算法的話,還可以讓速度再次增加。。。

繼續閱讀