众所周知,VB没有提供诸如shl、shr指令功能等价及相关进制转换函数。于是,在我的CCBAS项目中,我利用MASM写了一堆函数(包括字串,内存功能,超快的!已测试发现比WIN32 API 还要快。Utils.dll我正在使用中)。供VB程序调用。(最后更新:2006/01/07,增加了指针参数的检查及优化部分代码)
Utils.dll下载(只有4KB):http://dsdm.bokee.com/inc/Utils.dll
;//
VB Module declare:
Option Explicit
' bits
Declare Function MoveBitL Lib "Utils.dll" _
(ByVal dwVal As Long, _
ByVal dwMoveNum As Long) As Long
Declare Function MoveBitR Lib "Utils.dll" _
(ByVal dwVal As Long, _
ByVal dwMoveNum As Long) As Long
' numeric converter
Declare Function Bin2Dec Lib "Utils.dll" _
(ByRef pBin As Any) As Long
Declare Function Dec2Bin Lib "Utils.dll" _
(ByRef pBin As Any, _
ByVal dwVal As Long) As Long
Declare Function Dec2Hex Lib "Utils.dll" _
(ByRef pHex As Any, _
ByVal dwVal As Long) As Long
Declare Function Hex2Dec Lib "Utils.dll" _
(ByRef pHex As Any) As Long
' strings
Declare Function MStrLen Lib "Utils.dll" _
(ByRef pString As Any) As Long
Declare Function MStrCopy Lib "Utils.dll" _
(ByRef pDest As Any, _
ByRef pSrc As Any) As Long
Declare Function MStrCat Lib "Utils.dll" _
(ByRef pDest As Any, _
ByRef pSrc As Any) As Long
' by borland. return a pointer of position in pDest
Declare Function MStrPos Lib "Utils.dll" _
(ByRef pDest As Any, _
ByRef pSrc As Any) As Long
Declare Function MStrUpper Lib "Utils.dll" _
(ByRef pSrc As Any) As Long ' by borland.
Declare Function MStrLower Lib "Utils.dll" _
(ByRef pSrc As Any) As Long ' by borland.
' memory
Declare Function MMemCopy Lib "Utils.dll" _
(ByRef pDst As Any, _
ByRef pSrc As Any, _
ByVal nLength As Long) As Long
Declare Function MMemFill Lib "Utils.dll" _
(ByRef pDst As Any, _
ByVal cFill As Long, _
ByVal nLength As Long) As Long
Declare Function MMemZero Lib "Utils.dll" _
(ByRef pDst As Any, _
ByVal uCount As Long) As Long
;/
; MASM32 IN DLL:
.386 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include windows.inc
include masm32.inc
include gdi32.inc
include user32.inc
include kernel32.inc
includelib masm32.lib
includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
;includelib Comctl32.lib
;includelib comdlg32.lib
;includelib shell32.lib
DllEntry proto hInstance:DWORD, dwFunction:DWORD, lpReserve:DWORD
MoveBitL proto dwVal:DWORD, dwMoveNum:DWORD
MoveBitR proto dwVal:DWORD, dwMoveNum:DWORD
Bin2Dec proto pBin:DWORD
Dec2Bin proto pBin:DWORD, dwVal:DWORD
Dec2Hex proto pHex:DWORD, nDec:DWORD
Hex2Dec proto pHex:DWORD
MStrLen proto pString:DWORD ; for borland
MStrCopy proto pDest:DWORD, pSrc:DWORD ; for borland
MStrCat proto pDest:DWORD, pSrc:DWORD ; for borland
MStrPos proto pszDest:DWORD, pszSrc:DWORD ; for borland
MStrUpper proto pszSrc:DWORD ; for borland
MStrLower proto pszSrc:DWORD ; for borland
MMemCopy proto pDst:DWORD, pSrc:DWORD, nLength:DWORD
MMemFill proto pDst:DWORD, cFill:DWORD, nLength:DWORD
MMemZero proto pDest:DWORD, uCount:DWORD
;///
.code
align 4
;//
DllEntry proc hInstance:DWORD, dwFunction:DWORD, lpReserve:DWORD
xor eax, eax
inc eax
ret
DllEntry endp
;//
MoveBitL proc nDec:DWORD, dwMoveNum:DWORD
mov eax, dword ptr [nDec]
mov ecx, dword ptr [dwMoveNum]
shl eax, cl
ret
MoveBitL endp
;///
MoveBitR proc nDec:DWORD, dwMoveNum:DWORD
mov eax, dword ptr [nDec]
mov ecx, dword ptr [dwMoveNum]
shr eax, cl
ret
MoveBitR endp
;///
Bin2Dec proc pBin:DWORD
; argument check
mov eax, dword ptr [pBin]
test eax, eax
jz @Exit
push esi
mov esi, eax
xor eax, eax
xor edx, edx
cld
@@:
lodsb
test al, al
jz FinalFlag ; final
cmp al, 30h ; 0
jz IsBin
cmp al, 31h ; 1
jz IsBin
jnz @B
IsBin:
add edx, edx
lea edx, [edx + eax - 30h]
jmp @B
FinalFlag:
mov eax, edx
pop esi
@Exit:
ret
Bin2Dec endp
;///
Dec2Bin proc pBin:DWORD, nDec:DWORD
; argument check
mov eax, dword ptr [pBin]
test eax, eax
jz @Exit
push edi
mov edi, eax
mov edx, dword ptr [nDec]
mov ecx, 21h ; 33
mov al, 30h ; '0'
cld
@locate:
dec ecx
jz FinalFlag
shl edx, 1
jnc @locate
rcr edx, 1 ; set cf to left most, restore bit
mov ah, cl ; total bits
inc ecx
@@:
dec ecx
jz FinalFlag
shl edx, 1
jnc IsZero
inc al ; is 1
stosb ; cat in pBin
dec al ; reset as '0'
jmp @B
IsZero: ; is 0
stosb ;
jmp @B
FinalFlag:
movzx eax, ah
pop edi
@Exit:
ret
Dec2Bin endp
;///
Dec2Hex proc pHex:DWORD, nDec:DWORD
; argument check
mov eax, dword ptr [pHex]
test eax, eax
jz @Exit
mov edx, eax
push ebx
mov ebx, dword ptr [nDec]
xor ecx, ecx
mov [edx + 8], al ; put terminator at correct length
mov cl, 7 ; length of hexstring - 1
@@:
mov eax, ebx ; we're going to work on AL
and al, 0Fh ; mask out high nibble
cmp al, 10 ; CF
sbb al, 69h
das
mov [edx + ecx], al ; store the asciihex(AL) in the string
shr ebx, 4 ; next nibble
dec ecx ; decrease counter (one byte less than dec cl :-)
jns @B ; eat them if there's any more
pop ebx
@Exit:
ret
Dec2Hex endp
;///
Hex2Dec proc pHex:DWORD
; argument check
mov eax, dword ptr [pHex]
test eax, eax
jz @Exit
push esi
mov esi, eax
xor edx, edx
xor eax, eax
@next:
lodsb
test al, al
jz @final
cmp al, '0' ; '0'~'9' : 48~57
jb @next ; less than
cmp al, '9'
ja @range_af ; 'a' ~ 'f': 97~122
sub al, '0'
jmp @convert
@range_af:
or al, 20h ; 'A' 2 'a' offset value is 32, viz 10,0000
cmp al, 'a' ; 'a'~'f'
jb @next
cmp al, 'f'
ja @next
sub al, 'a'
add al, 10
@convert:
shl edx, 4
add edx, eax
jmp @next
@final:
mov eax, edx
pop esi
@Exit:
ret
Hex2Dec endp
;///
; borland uses the method
MStrLen proc pSrc:DWORD
; argument check
mov eax, dword ptr [pSrc]
test eax, eax
jz @Exit
mov edx, edi
mov edi, eax
mov ecx, 0ffffffffh
xor al, al
repne scasb
mov eax, ecx
not eax
dec eax
mov edi, edx
@Exit: ret
MStrLen endp
;///
; borland uses the method
MStrEnd proc pSrc:DWORD
; argument check
mov eax, dword ptr [pSrc]
test eax, eax
jz @Exit
mov edx, edi
mov edi, eax
mov ecx, 0ffffffffh
xor al, al
repne scasb
lea eax, [edi-1]
mov edi, edx
@Exit: ret
MStrEnd endp
;///
; borland uses the method
MStrCopy proc uses esi edi pDest:DWORD, pSrc:DWORD
; count length of pSrc
mov esi, dword ptr [pDest]
mov edi, dword ptr [pSrc]
; argument check
test esi, esi
jz @Exit
test edi, edi
jz @Exit
mov edx, edi
mov ecx, 0ffffffffh
xor al, al
repne scasb
not ecx
; moving data
mov edi, esi
mov esi, edx
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
@Exit:
ret
MStrCopy endp
;///
MStrCat proc uses esi edi pDest:DWORD, pSrc:DWORD
; goto end of pDest
mov edi, dword ptr [pDest]
mov esi, dword ptr [pSrc]
; argument check
test esi, esi
jz @Exit
test edi, edi
jz @Exit
cld
mov ecx, 0ffffffffh
xor al, al
repne scasb
dec edi
mov edx, edi ; backup the pDest
; count length of pSrc
mov edi, esi
mov ecx, 0ffffffffh
xor al, al
repne scasb
not ecx
; cat
mov edi, edx
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
@Exit:
ret
MStrCat endp
;///
MStrPos proc uses esi edi ebx pszDest:DWORD, pszSrc:DWORD
; check the destination string whether empty
mov eax, dword ptr [pszDest]
or eax, eax
jz @Error
; check the source string whether empty
mov edx, dword ptr [pszSrc]
or edx, edx
jz @Error
; search length of pszSrc
mov ebx, eax
mov edi, edx ; search pszSrc
xor al, al
mov ecx, 0ffffffffh
repne scasb
not ecx
dec ecx ; length of pszSrc
jz @Error ; if has not any chars then go to final
; check the length of destination string whether less than length of source string
mov esi, ecx ; length of pszSrc
mov edi, ebx ; pszDest
mov ecx, 0ffffffffh
repne scasb
not ecx
sub ecx, esi
jbe @Error
mov edi, ebx ; pszDest
lea ebx, [esi-1] ; length of pszSrc -1
; locate the first char of pszSrc in prcDest
@Next:
mov esi, edx ; pszSrc
lodsb
repne scasb
jne @Error ; not found
; compare the two strings
mov eax, ecx ; length of pszSrc
push edi
mov ecx, ebx ; length of pszSrc -1
repe cmpsb
pop edi
mov ecx, eax ; length of pszSrc
jne @Next ; not found then to find next first string
; RETURN address of pszSrc in pszDest
lea eax, [edi-1] ; found, luck!:)
; RETURN position of pszSrc in pszDest
; mov eax, edi
; sub eax, dword ptr [pszDest]
jmp @Exit
@Error:
xor eax, eax ; not found any chars
@Exit:
ret
MStrPos endp
;///
MStrUpper proc pszSrc:DWORD
; argument check
mov eax, dword ptr [pszSrc]
test eax, eax
jz @Exit
push esi
mov esi, eax
mov edx, esi
xor eax, eax
@Next:
lodsb
or al, al
je @Final
cmp al, 'a'
jb @Next
cmp al, 'z'
ja @Next
sub al, 20h ; set the six bits 10,0000 as zero
mov [esi-1], al
jmp @Next
@Final:
xchg eax, edx
pop esi
@Exit:
ret
MStrUpper endp
;///
MStrLower proc pszSrc:DWORD
; argument check
mov eax, dword ptr [pszSrc]
test eax, eax
jz @Exit
push esi
mov esi, eax
mov edx, esi
xor eax, eax
@Next:
lodsb
or al, al
je @Final
cmp al, 'A'
jb @Next
cmp al, 'Z'
ja @Next
or al, 20h ; set the six bits as 1
mov [esi-1], al
jmp @Next
@Final:
xchg eax, edx
pop esi
@Exit:
ret
MStrLower endp
;///
MMemZero proc pDest:DWORD, uCount:DWORD
; argument check
mov eax, dword ptr [pDest]
test eax, eax
jz @Exit
push edi
mov edi, eax
cld
mov ecx, dword ptr [uCount]
mov edx, ecx
shr ecx, 2 ; div 4
xor eax, eax
rep stosd
mov ecx, edx
and ecx, 3 ; mod of 4
rep stosb
pop edi
@Exit:
ret
MMemZero endp
;///
MMemCopy proc uses esi edi pDst:DWORD, pSrc:DWORD, nLength:DWORD
mov esi, dword ptr [pSrc]
mov edi, dword ptr [pDst]
; argument check
test esi, esi
jz @Exit
test edi, edi
jz @Exit
cld
mov ecx, dword ptr [nLength]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
@Exit:
ret
MMemCopy endp
;///
MMemFill proc pDst:DWORD, cFill:DWORD, nLength:DWORD
; argument check
mov eax, dword ptr [pDst] ; buffer address
test eax, eax
jz @Exit
mov edx, eax
mov eax, dword ptr [cFill] ; Fill chars
mov ecx, dword ptr [nLength] ; byte length
shr ecx, 5 ; divide by 32
cmp ecx, 0
jz rmndr
; ------------
; unroll by 8
; ------------
@@:
mov [edx], eax ; put Fill chars at address in edx
mov [edx+4], eax
mov [edx+8], eax
mov [edx+12], eax
mov [edx+16], eax
mov [edx+20], eax
mov [edx+24], eax
mov [edx+28], eax
add edx, 32
dec ecx
jnz @B
rmndr:
and dword ptr [nLength], 31 ; get remainder
cmp dword ptr [nLength], 0
je @Exit
mov ecx, dword ptr [nLength]
shr ecx, 2 ; divide by 4
@@:
mov [edx], eax
add edx, 4
dec ecx
jnz @B
@Exit:
ret
MMemFill endp
;///
;start
end DllEntry