VB中未公开的两个内存操作函数

Eddy 发布于2010-7-7 15:11:1 分类: 程序设计 已浏览loading 网友评论0条 我要评论

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

记住我的信息,下次不用再输入 欢迎给Eddy Blog留言