smitest 发表于 2020-2-18 21:03:57

【MASM,VB6】论坛老大VB6指针的拓展

本帖最后由 smitest 于 2020-2-18 21:29 编辑

最近做一个进程内存共享的项目,出于VB访问数据方便,想到了VB变量与内存绑定的问题,花了大约一周的时间学习了VB的数据类型结构,通过多方比较,最后采用了variant类型作为指针,实际使用起来更加方便。
直接上代码和说明:

特点:1一个指针,随时可以改变指向数据的类型2 具备指针增量可任意指定特性,对于内存不对齐的数据搜索很有用,比如一个4字节内存(1234),可以映射成3个Integer(12 23 34)
需要进一步探讨,可联系QQ 347895961.

主文件,没啥好解释的。
.686p
.model flat, stdcall
option casemap :none
.mmx
.XMM
include windows.inc
include MyFun.asm

.const
.data
.data?
        hInstance dd ?
.CODE
LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD
        .if reason == DLL_PROCESS_ATTACH                                       
                mov eax,hInstDLL
                mov hInstance,eax
               
                mov eax,TRUE
                ret
        .endif
ret
LibMain Endp
End LibMain

DEF文件,Aogo的IDE用的很舒服,可惜不更新了
LIBRARY VB6Ex
DESCRIPTION This DLL by MASMPlus
EXPORTS
int3
stBindVar
stUnBindAll
stUnBind

处理代码

int3 proto   ;调试VB程序用的,对这个主题没啥意义
stBindVar protopVar:DWORD,pMem:DWORD,nSize:DWORD,nType:DWORD,nStep:DWORD
stUnBindAll proto
stUnBindproto pVar:DWORD
;以下的暂时写的支持的VB数据类型,该常数对应于VB的VBVARTYPE枚举结构
vbInteger equ 2
vbLong   equ 3
vbSingle equ 4
vbDouble equ 5
vbCurrency equ 6
vbBoolean equ 11
vbByte equ17
;以上变量对应的内存字节数据
vbIntegerSize equ 2
vbLongSize   equ 4
vbSingleSize equ 4
vbDoubleSize equ 8
vbCurrencySize equ 8
vbBooleanSize equ 2
vbByteSize equ1

;安全数组结构
SafeArray1D struct
        cDims dw 0
        fFeatures dw 0
        cbStep dd 0
        cLocks dd 0
        pvData dd 0
        Elements dd 0
        Lbound dd 0
        reserved0 dd 0
        reserved1 dd 0
SafeArray1D ends
;Variant数据类型
Variant struct
        vType db 0
        vArray db 0
        reserved1 dw 0
        BindID dd 0
        pSafeArray dd 0
        reserved2 dd 0
Variant ends

;最大指针数目
MaxSize equ 16

.DATA
align 16
Varptr dd MaxSize dup(0)
align 16
VarStructVariant MaxSize dup (<>)
align 16
VarSA SafeArray1D MaxSize dup(<>)

.code

;指针绑定内存数据    参数分别为:要绑定的指针,内存地址,内存大小,指针类型,指针增量
stBindVar proc uses edx ecx esi edi pVar:DWORD,pMem:DWORD,nSize:DWORD,nType:DWORD,nStep:DWORD
local mType,mStep,mElements

   mov eax,nType
   .if eax==vbByte
       mov mStep,vbByteSize
   .elseif eax==vbInteger
       mov mStep,vbIntegerSize
   .elseif eax==vbLong
       mov mStep,vbLongSize
   .elseif eax==vbSingle
       mov mStep,vbSingleSize
   .elseif eax==vbDouble
       mov mStep,vbDoubleSize
   .elseif eax==vbBoolean
       mov mStep,vbBooleanSize
   .elseif eax==vbCurrency
       mov mStep,vbCurrencySize
   .else
       mov mStep,vbByteSize
       mov nType,vbByte
   .endif

   .if nStep!=0
       mov eax,nStep
       mov mStep,eax
   .endif
   xor edx,edx
   mov eax,nSize
   div mStep
   .if edx!=0
       inc eax
   .endif
   mov mElements,eax


        mov eax,pVar
        mov edi,offset Varptr
        mov ecx,MaxSize
        cld
        repnz scasd
        .if !Zero?
                xor eax,eax
                mov edi,offset Varptr
                mov ecx,MaxSize
                repnz scasd
                .if !Zero?
                        mov eax,-1
                        ret
                .endif
                mov eax,pVar
        .endif
        sub ecx,MaxSize
        not ecx
        mov ,eax
       
        pxor xmm0,xmm0
        mov edi,pVar
        movupd ,xmm0
        shl ecx,4

        lea esi,
        assume esi:ptr SafeArray1D
        mov WORD ptr .cDims,1
        mov WORD ptr .fFeatures,92h
        mov eax,mStep
        mov .cbStep,eax
        mov .cLocks,0
        mov eax,pMem
        mov .pvData,eax
        mov eax,mElements
   mov .Elements,eax
        mov .Lbound,0


        lea esi,
        assume esi:ptr Variant
        mov eax,nType
        mov BYTE ptr .vType,al
        mov BYTE ptr .vArray,32
        mov .reserved1,0
        mov .BindID,'xEBV'
        mov .reserved2,'TSyb'
        lea eax,
        mov .pSafeArray,eax       

   assume esi:nothing

        movupd xmm0,
        movupd ,xmm0
       
fclex
ret
stBindVar endp




;解除绑定
stUnBindAllproc   uses edi ecx
        mov edi,offset Varptr
        xor ecx,ecx
        pxor xmm0,xmm0
        @@:
        mov eax,
        .if eax!=0
          movupd ,xmm0
          mov DWORD ptr ,0
        .endif
        inc ecx
        cmp ecx,MaxSize
        jb @B
        ret
stUnBindAll endp

;解除单个变量的绑定
stUnBind proc uses edi ecx pVar:DWORD

        mov eax,pVar
        mov edi,offset Varptr
        mov ecx,MaxSize
        cld
        repnz scasd
        .if Zero?               
                pxor xmm0,xmm0
                mov eax,
                movupd ,xmm0
                mov DWORD ptr ,0
                xor eax,eax
        .endif
        ret
stUnBind endp


;调试VB程序用,研究VB数据存储访问结构就这个发挥了巨大作用
int3 proc
int 3
ret
int3 endp


系统消息 发表于 2020-2-25 10:16:41

smitest 发表于 2020-2-23 21:55
跟踪了一下,PtrLng还是被VB翻译成GetMem4,不知道咋回事。

是这样的,PtrXXX属性的Property Get就是GetMemN,Property Let就是PutMemN、Property Set就是SetMemN。
这几组函数本质上是VB6给类成员Public变量生成属性用的。

smitest 发表于 2020-2-23 23:02:39

好像理解了,猜想是GetMem4定义成属性的效果。

smitest 发表于 2020-2-23 22:03:30

系统消息 发表于 2020-2-20 19:26
msvbvm60.dll其实给我们提供了内存操作函数,只不过没有公开而已,我们直接写tlb声明这个未公开函数就行了 ...

还有请问大佬,entry(0x60000000)里0x60000000是啥意思呢

smitest 发表于 2020-2-23 21:55:49

跟踪了一下,PtrLng还是被VB翻译成GetMem4,不知道咋回事。

smitest 发表于 2020-2-18 21:20:22

VB6使用例子

Public Declare Function stUnBindAll Lib "vb6ex" () As Long
Public Declare Function stUnBind Lib "vb6ex" (ByRef Var As Variant) As Long
Public Declare Function stBindVar Lib "vb6ex" (ByRef Var As Variant, ByVal lpMem As Long, ByVal nMemSize As Long, ByVal nType As Long, ByVal nStep As Long) As Long

Public aa(1 To 16) As Byte, b As Long
Public ptr, ptr2, ptr3

Sub Main()

For I = 1 To 16 Step 2
aa(I) = I
Next
b = 45

   stBindVar ptr, VarPtr(aa(1)), 16, vbInteger, 2
   stBindVar ptr2, VarPtr(aa(1)), 16, vbByte, 3
   stBindVar ptr3, VarPtr(b), 4, vbLong, 0
   
   ptr(3) = 88: ptr3(0) = 99
   
   stUnBind ptr
stUnBindAll

End Sub

smitest 发表于 2020-2-18 21:31:15

本帖最后由 smitest 于 2020-2-18 21:33 编辑

最终库文件,引用TLB就不需要声明了。

BUG菌 发表于 2020-2-20 15:57:22

来给大佬暖帖

系统消息 发表于 2020-2-20 19:26:49

msvbvm60.dll其实给我们提供了内存操作函数,只不过没有公开而已,我们直接写tlb声明这个未公开函数就行了,这样根本不需要依赖任何dll。
https://pan.baidu.com/s/1hqtLQUK 这个是我写的msvbvm60.tlb,里面就是声明的VB6运行库未公开函数,其中内存操作函数我为了让操作更像指针特意声明成了属性,比如:
abc = PtrLng(内存地址1) '读取内存地址1中的Long数据(属性读取)
PtrLng(内存地址2) = 233 '往内存地址2中写入Long数据(属性赋值)
Set PtrObj(内存地址3) = obj '对象要用Set赋值(对象Let赋值是对其默认属性赋值)

0xAA55 发表于 2020-2-22 16:44:28

系统消息 发表于 2020-2-20 19:26
msvbvm60.dll其实给我们提供了内存操作函数,只不过没有公开而已,我们直接写tlb声明这个未公开函数就行了 ...

哟!好东西啊,那啥时候把这个TLB的源码弄成一个github repo,让我们自己编译呢?

系统消息 发表于 2020-2-22 19:08:26

本帖最后由 系统消息 于 2020-2-22 19:10 编辑

0xAA55 发表于 2020-2-22 16:44
哟!好东西啊,那啥时候把这个TLB的源码弄成一个github repo,让我们自己编译呢? ...

源码不在现在这台电脑上,过段时间吧。还有就是最近有群友发现我tlb有一些地方有BUG,需要改进。

系统消息 发表于 2020-2-24 21:35:03

smitest 发表于 2020-2-23 22:03
还有请问大佬,entry(0x60000000)里0x60000000是啥意思呢

反编译工具的BUG
页: [1]
查看完整版本: 【MASM,VB6】论坛老大VB6指针的拓展