用MASM编写的Utils.dll(VB+MASM混合编程)

来源:互联网 发布:开淘宝店都需要什么 编辑:程序博客网 时间:2024/04/29 18:22

众所周知,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