想出一种VB也能生成汇编的方法,有心者看能不能再发扬光大了
VB做SubClass一般都不得不带上个标准模块,但有时在自己的类中也要做SubClass处理,带模块的就不方便了,我想试过的都有点感触,我就不多说了。
不带模块,在网上也见过不少代码,方法就是写一段像天书一样的16进制码到全局内存中,显得非常神秘,虽然有些不用劳神拿来就能用,但毕竟不知源码处理方法,有时很难与自己的需求配合好!VB能不能做出那些古怪的东东呢?我今天突然想出了个办法,拿出来与大家分享,也希望能抛砖引玉,完善这种方法。
那种汇编码说起来也不神秘,无非就是写一个公用过程,将过程编译后的机器码转成字符串,放到程序中,它的作用相当于一个标准模块,可只为类的一个实例独享,绝不会引起冲突。但这个过程要调用对象的方法,又要绕过VB的对象引用计数。突破VB的重重封锁,真是让我犯了难。
据我测试,VB的引用计数,是与Set语句相关联的,不用Set,直接将对象指针Copy给对象变量,就不会计数。基于这点认识我写了个简单的汇编码生成程序,虽然功能有限,但却可自己控制程序流向,应该是有利用价值的。
1、先加个类Class2,它没功能,目的就了为了绕过编译时的类型检查,代码如下:
Public Function WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wp As Long, ByVal lp As Long) As Long
End Function
2、加个标准模块,代码如下:
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private obj As Class2
Public Function WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wp As Long, ByVal lp As Long) As Long
'这是要生成汇编的过程,以后就要靠它为我们的类服务了
'这个过程内容暂时不支持其它函数调用,不然又要动态取函数地址,很麻烦
'想做什么处理,全部放到类里的WndProc函数中去
WndProc = obj.WndProc(hwnd, Msg, wp, lp)
End Function
Public Sub Main()
Dim i As Long, a() As Byte, s As String, b(3) As Byte, s1 As String
Const CodeLen As Long = 200 '复制汇编码的长度,可大致估算一下汇编码的容量,只能多不能少!
ReDim a(CodeLen - 1)
i = GetAddress(AddressOf WndProc) '取WndProc函数地址
CopyMemory a(0), ByVal i, CodeLen '将函数的汇编码复制到字节数组中
For i = 0 To CodeLen - 1
If i < CodeLen - 1 Then
If a(i) = &H90 And a(i + 1) = &H90 Then Exit For '判断过程码是否结束的标志之一
End If
If a(i) > 15 Then
s = s & Hex$(a(i))
Else
s = s & "0" & Hex$(a(i))
End If
If i > 10 Then
If a(i - 1) = &HC2 And a(i) = &H10 Then Exit For '判断过程码是否结束的标志之二
End If
Next
CopyMemory b(0), VarPtr(obj), 4 '取对象变量的地址,因为它是动态的,我没法在VB中用对象指针直接调用对象的方法,只好这样变通了
For i = 0 To 3
If b(i) > 15 Then
s1 = s1 & Hex$(b(i))
Else
s1 = s1 & "0" & Hex$(b(i))
End If
Next
s = Replace$(s, s1, "xxxxxxxx") '把汇编码中保存对象变量的地址的4个字节,用“x”标出,便于加载时替换。
Debug.Print s
If Dir(App.Path & "\1.txt") <> "" Then Kill App.Path & "\1.txt"
Open App.Path & "\1.txt" For Binary As #1 '写入程序目录下“1.txt”文件
Put #1, , s
Close #1
End Sub
Public Function GetAddress(ByVal a As Long) As Long
GetAddress = a
End Function
把工程用本机码(记住不能用p代码)编译成EXE,编译速度优化选项包括高级选项,最好全部选上。
动行Exe,呵呵,VB生成的汇编码就写入“1.txt”中了。
至于怎么调用,我要睡觉了,明天再写。。。