最近在编写软件时老是为没有一个齐全的优良的框架而烦恼。所以,在一而再,再而三的打击、遍体鳞伤之下,在下才祭出屠龙宝刀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
xor ecx, ecx
dec ecx
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
; ; set nCount
; mov eax, DWORD PTR [nCount]
; inc eax
; je @IsWhole
; ;dec eax
; mov ecx, eax ; start pos from pszExpression
; jmp @NoSearchDstNull
; @IsWhole:
;
; ; check the length of pszExpression string whether less than length of pszFind string
; mov edi, ebx ; pszExpression
; xor ecx, ecx
; dec ecx
; xor eax, eax
; repne scasw
; not ecx
; mov eax, ecx
; @NoSearchDstNull:
; cmp eax, esi
; jbe @Error
; check the length of pszExpression string whether less than length of pszFind string
mov edi, ebx ; pszExpression
xor ecx, ecx
dec ecx
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
xor ecx, ecx
dec ecx
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]
test edi, edi
jz @RepStrIsNull
mov edx, edi
xor ecx, ecx
dec ecx
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
jmp @ReplaceOk
;//
@RepStrIsNull:
mov edi, ebx
mov WORD PTR [edi], 0000h
add edi, 2
xor edx, edx
add edx, 2
@ReplaceOk:
; 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
xor ecx, ecx
dec ecx
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
xor ecx, ecx
dec ecx
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
xor ecx, ecx
dec ecx
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]
test edi, edi
jz @RepStrIsNull
mov edx, edi
xor ecx, ecx
dec ecx
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
jmp @ReplaceOk
;//
@RepStrIsNull:
mov edi, ebx
mov BYTE PTR [edi], 00h
inc edi
xor edx, edx
inc edx
@ReplaceOk:
; 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版本