zoukankan      html  css  js  c++  java
  • [转]VB中嵌入汇编与真正的DLL

    发信人: flashboy()
    整理人: winsy(2003-03-05 16:37:08), 站内信件

    VB是个高级程序语言,不允许你做那些如嵌入汇编等工作,但天下没有不可能的
    事,让兔子抽烟也是可能的。VB已经是个编译器而非BASICA之类的解释器,对VB
    编译器的编译过程有所了解后,就能基本做到为所欲为。

    VB的compile过程也如所有compile的一样,包含编译(compile)和连接(link)。在
    VB里实际上是调用c2.exe和link.exe来完成的。c2是微软的“两次过(second-pa
    ss)”编译器。在VB的集成环境里,VB通过WIN32API的CreateProcess来调用c2和
    link,注意,这就是个突破点,可以把这个调用hook起来,就可以介入VB的编译
    连接过程。

    VB用C2对你项目中的每个文件进行编译,然后产生目标库(object modules),并
    把这些目标库暂存在你的TEMP目录下,等全编译完了后把它们在link起来,生成
    EXE文件。C2有很多参数可用,其中最关键的是FAs,这个参数让编译器产生汇编
    的源程序。

    明天再续。。


    为什么我们用VC?
    因为VC灵活自由,
    从高处看,可以做继承,可以做重载,可以做多态性。
    从低处看,可以操作指针,可以嵌入汇编。
    从结果看,可以调整不同的编译参数使目标码效率高,执行快,尺寸小。
    VC真是写系统程序的唯一选择。

    为什么我们用VB?
    因为写程序和调试程序的速度是用VC写的几十倍。有了VB才有了RAD(快速程序开
    发)这个词。

    为什么我们不用VB?
    因为VB不能做VC可以做的上述事情。
    等一等,是VB不能做还是大多数人不会做??
    在进行下去之前,为了有效的拦截VB的编译器,我们要安装一个利器。利器安装
    后,我们就可以随心所欲地拦截VB的编译器。如果把Hook Compiler激活,你一旦
    编译。就会看到有个显示编译参数的窗口显示出来。上一篇说过有个很重要的参
    数是“-FAs”,(格式是: -FAs -Fa "C:\myvb\modbas.lst")。这个编译参数可
    以使编译器产生汇编源码。看到这里,怎样嵌入你自己的汇编程序应该也猜出来
    了。对,就是修改VB产生的那个汇编程序,再用MASM编译程OBJ。或者,你想做的
    更干脆的话,从头到尾用汇编也行。用同名文件替换VB的OBJ就行了。同理,你可
    以嵌入你的VC程序,BC程序,FORTRAN程序。比如你对某些VB的运算速度不满意,
    想用VC或ASM重写。你可以只写一个空的VB函数(只有一个名字)。然后编译,中间
    截住,狸猫换太子,换上你自己VC,ASM目标库。在让VB继续生成EXE执行文件。
    多好!有点做黑客的感觉。

    汇编的编译器(ML.EXE)可以在DDK里找到,是MASM 6.11d版,可以从MS下载。看看
    下面的实例:有个VB程序做除2的工作,


    Public function DivideBy2(lngDividend as Long) as Long   DivideBy2 = l
    ngDividend / 2End Function

    编译后汇编码如下:

    ?DividBy2@Module1@@AAGXXZ PROC NEAR ; Module1::DividBy2, COMDAT; 2  
      : Public Function DividBy2(lngDividend As Long) As Long push ebp mov
    ebp, esp sub esp, 8 push OFFSET FLAT:___vbaExceptHandler mov eax, DWO
    RD PTR fs:__except_list push eax mov DWORD PTR fs:__except_list, esp s
    ub esp, 48 ; 00000030H push ebx push esi push edi mov DWORD PTR __
    $SEHRec$[ebp+8], esp mov DWORD PTR __$SEHRec$[ebp+12], OFFSET FLAT:$S2
    6 xor eax, eax; 3    :     Divideby2 = lngDividend / 2 lea edx, DWORD 
    PTR _unnamed_var1$[ebp] mov DWORD PTR _DividBy2$[ebp], eax mov DWORD P
    TR _Divideby2$[ebp], eax mov eax, DWORD PTR _lngDividend$[ebp] lea ecx
    , DWORD PTR _Divideby2$[ebp] mov DWORD PTR _unnamed_var1$[ebp], 5 fild
    DWORD PTR [eax] fstp QWORD PTR -64+[ebp] fld QWORD PTR -64+[ebp] cmp
    DWORD PTR __adjust_fdiv, 0 jne SHORT $L48 fdiv QWORD PTR __real@8@4000
    8000000000000000 jmp SHORT $L49$L48: push DWORD PTR __real@8@400080000
    00000000000+4 push DWORD PTR __real@8@40008000000000000000 call __adj_
    fdiv_m64$L49: fstp QWORD PTR _unnamed_var1$[ebp+8] fnstsw ax test al, 
    13 ; 0000000dH jne SHORT $L41 call DWORD PTR __imp_@__vbaVarMove f
    wait push $L40$L35:; 4    : End Function

    天哪,VB竟产生了这么多乱七八糟的代码。你可以在上面动手优化,结束后,用

    ml /c /Cp /coff /Zm module1.lst
    编译你自给的OBJ。
    你也可以完全在ASM或VC写个模块。在这种工作方式下,要注意的是VB每次编译动
    态产生函数名,这个VC里用的函数名不同。在替换OBJ时要注意使名字一致。比如
    VB产生的名字是:
    ?DividBy2@Module1@@AAGXXZ
    VC里面可能是?DividBy2@@GXF@Z,所以要手工改名字。

    加入不同的编译参数还可以做不少事情。例如:VB只能产生ActiveX DLL? 谁说的
    ,用了/EXPORT或/DEF参数就能输出函数从而产生一个普通的DLL文件。

  • 相关阅读:
    shell脚本之for循环
    shell脚本小集锦
    Java构建指定大小文件
    IntelliJ+Maven+Spring+Tomcat项目搭建(MAC)
    Git下基本命令操作
    Mac下IntelliJ的Git、GitHub配置及使用
    Git下的.DS_Store文件
    Mac下GitHub以及GitHub Desktop使用实战
    idea快捷键
    汉字获取首字符
  • 原文地址:https://www.cnblogs.com/Jonlee/p/313346.html
Copyright © 2011-2022 走看看