Option Explicit
'
' 未公开的内存操作函数
' -----------------------------
'
' 这2个函数分别取自微软的VB支持库 msvbvm60.dll 中
'函数名为 __vbaCopyBytes and __vbaCopyBytesZero.
'
'vbaCopyBytesZero :
'该函数功能是从一个内存块(存储单元)中复制字节到
'另一个内存块(存储单元)中,并把源内存块(存储单元)填充零.
'vbaCopyBytes :
'该函数功能是从一个内存块(存储单元)中复制字节到另一个内存块(存储单元)中.
'
' 入口参数
' 1.param -> 复制字节数
' 2.param -> 目标内存指针
' 3.param -> 源内存指针
'
' 以上是您需要了解的 ;-)
' 顺便说一句,如果您懂得汇编,可以看一下下面的汇编代码,以便更加了解这2个函数的意义。
'
'
' ---> __vbaCopyBytes <---
'
'public __vbaCopyBytes
'.text:660D9B6B __vbaCopyBytes proc near
'.text:660D9B6B
'.text:660D9B6B arg_0 = dword ptr 4 ;1.param - number of bytes to copy
'.text:660D9B6B arg_4 = dword ptr 8 ;2.param - pointer to the destination memory
'.text:660D9B6B arg_8 = dword ptr 0Ch ;3.param - pointer to the source memory
'.text:660D9B6B
'.text:660D9B6B mov ecx, [esp+arg_0] ;ecx = 1.param
'.text:660D9B6F push esi ;save esi
'.text:660D9B70 mov esi, [esp+4+arg_8] ;esi = 3.param
'.text:660D9B74 push edi ;save edi
'.text:660D9B75 mov edi, [esp+8+arg_4] ;edi = 2.param
'.text:660D9B79 mov eax, ecx ;eax = ecx
'.text:660D9B7B mov edx, edi ;edx = edi
'.text:660D9B7D shr ecx, 2 ;ecx = ecx/2
'.text:660D9B80 rep movsd ;perform dword copy
'.text:660D9B82 mov ecx, eax ;ecx = eax
'.text:660D9B84 mov eax, edx ;eax = edx
'.text:660D9B86 and ecx, 3 ;ecx = ecx mod 4
'.text:660D9B89 rep movsb ;perform byte copy
'.text:660D9B8B pop edi ;restore edi
'.text:660D9B8C pop esi ;restore esi
'.text:660D9B8D retn 0Ch ;return
'.text:660D9B8D
'.text:660D9B8D __vbaCopyBytes endp
'
'
' ---> __vbaCopyBytesZero <---
'
'public __vbaCopyBytesZero
'.text:660D9B90 __vbaCopyBytesZero proc near
'.text:660D9B90
'.text:660D9B90 arg_0 = dword ptr 8 ;1.param - number of bytes to copy
'.text:660D9B90 arg_4 = dword ptr 0Ch ;2.param - pointer to the destination memory
'.text:660D9B90 arg_8 = dword ptr 10h ;3.param - pointer to the source memory
'.text:660D9B90
'.text:660D9B90 push ebp ;save ebp
'.text:660D9B91 mov ebp, esp ;ebp = esp
'.text:660D9B93 mov ecx, [ebp+arg_0] ;ecx = 1.param
'.text:660D9B96 push esi ;save edi
'.text:660D9B97 mov esi, [ebp+arg_8] ;esi = 3.param
'.text:660D9B9A mov eax, ecx ;eax = ecx
'.text:660D9B9C push edi ;save edi
'.text:660D9B9D mov edi, [ebp+arg_4] ;edi = 2.param
'.text:660D9BA0 shr ecx, 2 ;ecx = ecx/4
'.text:660D9BA3 rep movsd ;perform dword copy
'.text:660D9BA5 mov ecx, eax ;ecx = eax
'.text:660D9BA7 and ecx, 3 ;ecx = ecx mod 4
'.text:660D9BAA rep movsb ;perform byte copy
'.text:660D9BAC mov edi, [ebp+arg_8] ;edi = 3.param
'.text:660D9BAF mov ecx, eax ;ecx = eax
'.text:660D9BB1 mov edx, ecx ;edx = ecx
'.text:660D9BB3 xor eax, eax ;eax = 0
'.text:660D9BB5 shr ecx, 2 ;ecx = ecx/4
'.text:660D9BB8 rep stosd ;store eax to [edi]
'.text:660D9BBA mov ecx, edx ;ecx = edx
'.text:660D9BBC and ecx, 3 ;ecx = ecx mod 4
'.text:660D9BBF rep stosb ;store eax to [edi]
'.text:660D9BC1 mov eax, [ebp+arg_4] ;eax = 2.param
'.text:660D9BC4 pop edi ;restore edi
'.text:660D9BC5 pop esi ;restore esi
'.text:660D9BC6 pop ebp ;restore ebp
'.text:660D9BC7 retn 0Ch ;return
'.text:660D9BC7
'.text:660D9BC7 __vbaCopyBytesZero endp
'
'函数声明
Private Declare Sub vbaCopyBytes Lib "msvbvm60.dll" Alias "__vbaCopyBytes" (ByVal Length As Long, Destination As Any, Source As Any)
Private Declare Sub vbaCopyBytesZero Lib "msvbvm60.dll" Alias "__vbaCopyBytesZero" (ByVal Length As Long, Destination As Any, Source As Any)
'vbaCopyBytesZero 函数演示:
'该函数功能是从一个内存块(存储单元)中复制字节到
'另一个内存块(存储单元)中,并把源内存块(存储单元)填充零.
Private Sub cmdvbaCopyBytesZero_Click()
Dim a(1 To 15) As Byte '源内存块
Dim b(1 To 15) As Byte '目标内存块
Dim s As String, i As Long
'先填满第一个内存区域
For i = LBound(a) To UBound(a)
a(i) = i
s = s & vbCrLf & i & ". a = " & a(i) & " ; b = " & b(i)
Next i
MsgBox "操作vbaCopyBytes之前:" & s
vbaCopyBytesZero LenB(a(1)) * 15, b(1), a(1)
s = ""
'检查第二个内存区域
For i = LBound(a) To UBound(a)
s = s & vbCrLf & i & ". a = " & a(i) & " ; b = " & b(i)
Next i
MsgBox "操作vbaCopyBytesZero之后:" & s
End Sub
'vbaCopyBytes 函数演示:
'该函数功能是从一个内存块(存储单元)中复制字节到另一个内存块(存储单元)中.
Private Sub cmdvbaCopyBytes_Click()
Dim a(1 To 15) As Byte '源内存块
Dim b(1 To 15) As Byte '目标内存块
Dim s As String, i As Long
'先填满第一个内存区域
For i = LBound(a) To UBound(a)
a(i) = i
s = s & vbCrLf & i & ". a = " & a(i) & " ; b = " & b(i)
Next i
MsgBox "操作vbaCopyBytes之前:" & s
vbaCopyBytes LenB(a(1)) * 15, b(1), a(1)
s = ""
'检查第二个内存区域
For i = LBound(a) To UBound(a)
s = s & vbCrLf & i & ". a = " & a(i) & " ; b = " & b(i)
Next i
MsgBox "操作vbaCopyBytes之后:" & s
End Sub
有人说这个和CopyMemory函数相比效率如何,CopyMemory函数调用的是ntdll.RtlMoveMemory这个函数,下面是它的汇编代码:
7C922C94 > 56 PUSH ESI
7C922C95 57 PUSH EDI
7C922C96 8B7424 10 MOV ESI,DWORD PTR SS:[ESP+10]
7C922C9A 8B7C24 0C MOV EDI,DWORD PTR SS:[ESP+C]
7C922C9E 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+14]
7C922CA2 FC CLD
7C922CA3 3BF7 CMP ESI,EDI
7C922CA5 76 1A JBE SHORT 7C922CC1
7C922CA7 8BD1 MOV EDX,ECX
7C922CA9 83E2 03 AND EDX,3
7C922CAC C1E9 02 SHR ECX,2
7C922CAF F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
7C922CB1 0BCA OR ECX,EDX
7C922CB3 75 05 JNZ SHORT 7C922CBA
7C922CB5 5F POP EDI
7C922CB6 5E POP ESI
7C922CB7 C2 0C00 RETN 0C
7C922CBA F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
7C922CBC 5F POP EDI
7C922CBD 5E POP ESI
7C922CBE C2 0C00 RETN 0C
7C922CC1 ^ 74 F9 JE SHORT 7C922CBC
对比分析可知,两者基本一样,因此我认为两者效率一样,只不过换了个说法而已^_
已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/program/413.html 欢迎订阅Eddy Blog。