• 昨天用MASM32写了一个查找替换的字串函数!ANSI及UNICODE两个版本(原创)

    2007-01-13

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://dreamerate.blogbus.com/logs/4281010.html

    最近在编写软件时老是为没有一个齐全的优良的框架而烦恼。所以,在一而再,再而三的打击、遍体鳞伤之下,在下才祭出屠龙宝刀MASM v8.0,于深山老林中,月圆之夜,潜修武林密决!终于,经过一些高级语言的RTL的冲撞及抛砖引玉之下,在下悟出了一些所谓的盖世神功武林密决——Utils函数……

    话音锋回路转,我们将话题扭转到至今,刚才在整理ANSI及UNICODE的字符串函数时,感觉MStrRepA及MStrRepW应该对同道中人或许还能取到旷世之神效,所以就贴了上来。由于在下才舒学浅,还得请前辈大侠们多多关照和包函,如果还能指点小的一二,吾将不胜感激!

    原理我想大家都知道了,那么我就不废话了,以下是代码。希望对有用得着的同道中人有所帮助,或是取到抛砖引玉之功效!

    1、UNICODE Version:

    MStrRepW proc uses esi edi ebx pszExpression:DWORD, pszFind:DWORD, pszReplaceWith:DWORD, nStart:DWORD, nCount:DWORD

        local szBuf[1024]:word

        ; check the pszExpression string whether empty
        mov     eax, DWORD ptr [pszExpression]
        or      eax, eax
        jz      @Error
       
        ; check the pszFind string whether empty
        mov     edx, DWORD ptr [pszFind]
        or      edx, edx
        jz      @Error
       
        cld
       
        ; add nStart
        mov     ebx, eax                    ; first addr of pszExpression
        mov     eax, DWORD PTR [nStart]
        inc     eax
        je      @IsZeroSide
        dec     eax
        lea     ebx, [ebx+eax*2]            ; start pos from pszExpression
      @IsZeroSide:
     
        ; search length of pszFind
        mov     edi, edx                    ; search pszFind
        or      ecx, 0ffffffffh
        xor     eax, eax
        repne   scasw
        not     ecx
        dec     ecx         ; length of pszSrc
        jz      @Error      ; if has not any chars then go to final
       
        mov     esi, ecx    ; backup the length of pszFind

        ; check the length of pszExpression string whether less than length of pszFind string
        mov     edi, ebx    ; pszExpression
        or      ecx, 0ffffffffh
        xor     eax, eax
        repne   scasw
        not     ecx
        mov     eax, DWORD PTR [nCount]
        inc     eax
        je      @IsWhole
        cmp     eax, ecx
        ja      @IsWhole
        mov     ecx, eax
      @IsWhole:
        mov     eax, ecx
        cmp     eax, esi
        jbe     @Error
       
        mov     edi, ebx        ; pszExpression
        lea     ebx, [esi-1]    ; length of pszFind -1
       
        ; locate the first char of pszFind in pszExpression
     @Next:
        mov     esi, edx        ; pszFind
        lodsw
        repne   scasw
        jne     @Error          ; not found
       
        ; compare the two strings
        mov     eax, ecx        ; length of pszExpression
        push    edi
        mov     ecx, ebx        ; length of pszFind -1 
        repe    cmpsw

        pop     edi
        mov     ecx, eax        ; length of pszExpression
        jne     @Next           ; not found then to find next first string
       
        ; ok! we're found the pszFind string in pszExpression,then we'll protected following registers
        ;
        ; name  content
        ; ----  --------------------------------------------------------------
        ; edi   destination string
        ; edx   pszFind
        ; ebx   length of pszFind -1
        ; ecx   length of remaining pszExpression after executed repne scasb
        push    edi
        push    edx
        push    ebx
        push    ecx
        ;/////////////////////////////////
       
        ; start replace
        lea     eax, [edi-2] ; protect pszExpression next
       
        ;////////////////////////////
        ; store the string to memory which back of pszFind string in remaining pszExpression
       
        ; search NULL in remaining pszExpression
        lea     edi, [edi+ebx*2]
        mov     edx, edi        ; end of pszExpression
        or      ecx, 0ffffffffh
        mov     ebx, eax        ; protect pszExpression next
        xor     eax, eax
        repne   scasw
        not     ecx
        shl     ecx, 1
       
        push    ecx
       
        ; proected string to memory which back of pszFind string in remaining pszExpression
        lea     edi, szBuf
        mov     esi, edx
        mov     edx, ecx
        shr     ecx, 2
        rep     movsd
        mov     ecx, edx
        and     ecx, 3
        rep     movsb
        ;/////////////////////////////
       
        ;/////////////////
        ; replace the pszFind string with pszReplaceWith in remaining pszExpression
        ;
        ; search NULL in pszReplaceWith
        mov     edi, DWORD ptr [pszReplaceWith]
        mov     edx, edi
        or      ecx, 0ffffffffh
        xor     eax, eax
        repne   scasw
        not     ecx
        dec     ecx
        shl     ecx, 1
       
        ; replace pszFind string in remaining pszExpression with pszReplaceWith
        mov     edi, ebx
        mov     esi, edx
        mov     edx, ecx
        shr     ecx, 2
        rep     movsd
        mov     ecx, edx
        and     ecx, 3
        rep     movsb
        ;//////////////////////////
       
        ; move remaining pszExpression in memory to pszExpression new position
     
        ; search NULL in pszReplaceWith
        pop     ecx
       
        ; replace pszFind string in remaining pszExpression with pszReplaceWith
        lea     esi, szBuf
        mov     ebx, ecx
        shr     ecx, 2
        rep     movsd
        mov     ecx, ebx
        and     ecx, 3
        rep     movsb
       
        mov     eax, edx    ; length of pszReplaceWith
       
        pop     ecx
        pop     ebx
        pop     edx
        pop     edi
       
        lea     edi, [edi+eax-2]
       
        mov     eax, ecx ; remaining bits of pszExpression to no complete search task
        dec     eax
        cmp     eax, ebx
        ja      @Next    ; continue
        jmp     @Exit
       
     @Error:
        xor     eax, eax    ; not found any chars

     @Exit:
        ret
       
    MStrRepW endp
    ;///////////////////////////////////////////////////////////////////////////////////

    2、ANSI version:

    ;///////////////////////////////////////////////////////////////////////////////////
    MStrRepA proc uses esi edi ebx pszExpression:DWORD, pszFind:DWORD, pszReplaceWith:DWORD, nStart:DWORD, nCount:DWORD

        local szBuf[1024]:byte

        ; check the pszExpression string whether empty
        mov     eax, DWORD ptr [pszExpression]
        or      eax, eax
        jz      @Error
       
        ; check the pszFind string whether empty
        mov     edx, DWORD ptr [pszFind]
        or      edx, edx
        jz      @Error
       
        cld
       
        ; add nStart
        mov     ebx, eax                    ; first addr of pszExpression
        mov     eax, DWORD PTR [nStart]
        inc     eax
        je      @IsZeroSide
        dec     eax
        lea     ebx, [ebx+eax]            ; start pos from pszExpression
      @IsZeroSide:
     
        ; search length of pszFind
        mov     edi, edx                    ; search pszFind
        or      ecx, 0ffffffffh
        xor     al, al
        repne   scasb
        not     ecx
        dec     ecx         ; length of pszSrc
        jz      @Error      ; if has not any chars then go to final
       
        mov     esi, ecx    ; backup the length of pszFind

        ; check the length of pszExpression string whether less than length of pszFind string
        mov     edi, ebx    ; pszExpression
        or      ecx, 0ffffffffh
        xor     al, al
        repne   scasb
        not     ecx
        mov     eax, DWORD PTR [nCount]
        inc     eax
        je      @IsWhole
        cmp     eax, ecx
        ja      @IsWhole
        mov     ecx, eax
      @IsWhole:
        mov     eax, ecx
        cmp     eax, esi
        jbe     @Error
       
        mov     edi, ebx        ; pszExpression
        lea     ebx, [esi-1]    ; length of pszFind -1
       
        ; locate the first char of pszFind in pszExpression
     @Next:
        mov     esi, edx        ; pszFind
        lodsb
        repne   scasb
        jne     @Error          ; not found
       
        ; compare the two strings
        mov     eax, ecx        ; length of pszExpression
        push    edi
        mov     ecx, ebx        ; length of pszFind -1 
        repe    cmpsb

        pop     edi
        mov     ecx, eax        ; length of pszExpression
        jne     @Next           ; not found then to find next first string
       
        ; ok! we're found the pszFind string in pszExpression,then we'll protected following registers
        ;
        ; name  content
        ; ----  --------------------------------------------------------------
        ; edi   destination string
        ; edx   pszFind
        ; ebx   length of pszFind -1
        ; ecx   length of remaining pszExpression after executed repne scasb
        push    edi
        push    edx
        push    ebx
        push    ecx
        ;/////////////////////////////////
       
        ; start replace
        lea     eax, [edi-1] ; protect pszExpression next
       
        ;////////////////////////////
        ; store the string to memory which back of pszFind string in remaining pszExpression
       
        ; search NULL in remaining pszExpression
        lea     edi, [edi+ebx]
        mov     edx, edi        ; end of pszExpression
        or      ecx, 0ffffffffh
        mov     ebx, eax        ; protect pszExpression next
        xor     al, al
        repne   scasb
        not     ecx
       
        push    ecx
       
        ; proected string to memory which back of pszFind string in remaining pszExpression
        lea     edi, szBuf
        mov     esi, edx
        mov     edx, ecx
        shr     ecx, 2
        rep     movsd
        mov     ecx, edx
        and     ecx, 3
        rep     movsb
        ;/////////////////////////////
       
        ;/////////////////
        ; replace the pszFind string with pszReplaceWith in remaining pszExpression
        ;
        ; search NULL in pszReplaceWith
        mov     edi, DWORD ptr [pszReplaceWith]
        mov     edx, edi
        or      ecx, 0ffffffffh
        xor     al, al
        repne   scasb
        not     ecx
        dec     ecx
       
        ; replace pszFind string in remaining pszExpression with pszReplaceWith
        mov     edi, ebx
        mov     esi, edx
        mov     edx, ecx
        shr     ecx, 2
        rep     movsd
        mov     ecx, edx
        and     ecx, 3
        rep     movsb
        ;//////////////////////////
       
        ; move remaining pszExpression in memory to pszExpression new position
     
        ; search NULL in pszReplaceWith
        pop     ecx
       
        ; replace pszFind string in remaining pszExpression with pszReplaceWith
        lea     esi, szBuf
        mov     ebx, ecx
        shr     ecx, 2
        rep     movsd
        mov     ecx, ebx
        and     ecx, 3
        rep     movsb
       
        mov     eax, edx    ; length of pszReplaceWith
       
        pop     ecx
        pop     ebx
        pop     edx
        pop     edi
       
        lea     edi, [edi+eax-1]
       
        mov     eax, ecx ; remaining bits of pszExpression to no complete search task
        dec     eax
        cmp     eax, ebx
        ja      @Next    ; continue
        jmp     @Exit
       
     @Error:
        xor     eax, eax    ; not found any chars

     @Exit:
        ret
       
    MStrRepA endp
    ;///////////////////////////////////////////////////////////////////////////////////

    注意!由于在下的机器是NT内核的XP SP2系统,故主要都是编写倾向于UNICODE软件,所以推荐大家使用UNICODE版本,因为ANSI的没有测试过。*_* sorry

    如需转载或收藏,请注明出处及作者,谢谢。


    历史上的今天:


    收藏到:Del.icio.us




    评论

  • ANSI的也可以测试啊,