VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)

VB爱好者乐园(VBGood)

 找回密码
 立即注册
搜索
查看: 4303|回复: 12

[转帖] 如何和C或Assembly的程序链接

[复制链接]
 楼主| 发表于 2009-8-7 07:29:31 | 显示全部楼层 |阅读模式
如何和C或Assembly的程序链接
说明
基于最佳化的考虑,通常程序一些常用的部分会透过汇编语言来做最佳化的动作,但这对于VB的使用者而言却是一项难题,VB并不支持这样的功能,我们得绕一段远路,透过如何取得lst档相同的方法,我们在多做一个链节器,Link.EXE做法如下
1.先安装C2.zip中的C2.EXE 安装方法请参考如何取得VB编译后的lst文件
2.将E:\ProgramFiles\Microsoft Visual Studio\VB98\Link.EXE改名为E:\ProgramFiles\Microsoft Visual Studio\VB98\iLink.EXE
3.下载Link.zip
4.解压缩后将Link.exe放到E:\Program Files\Microsoft Visual Studio\VB98目录下
准备完成后 透过以下范例 将一步步教你如何链接
请先下载以下范例LinkWith_C_asm.zip内部含有一个VB,C以及ASM的程序
VB的程序如下
'以下程序在Form中
Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Sub Command1_Click()
Dim i As Long, l As Long
Dim bgt As Long, ent As Long
bgt = GetTickCount()

For i = 1 To 1000000
    l = GetSum()
Next

ent = GetTickCount()

MsgBox "
费时:" & ent - bgt

End Sub

Private Sub Command2_Click()
Dim l As Long
l = GetSum()
MsgBox l
End Sub

'以下程序在模块中
Option Explicit

Public Function GetSum() As Long
Dim i As Long, l As Long

For i = 1 To 100
    l = l + i
Next

GetSum = l
End Function
我们动手写个GetSum这个函数 要做的是1累加到100 汇编代码如下
.386P
.model FLAT
PUBLIC GetSum
.code

GetSum PROC NEAR
xor eax, eax
mov ecx, 1

loop1:
  add eax, ecx
  inc ecx
  cmp ecx, 100
jle loop1
ret 0
GetSum ENDP

END
另外我们也用C写一个来比较
extern "C" long __stdcall GetSum();

long __stdcall GetSum()
{
long i,l=0;
for(i=1;i<=100;i++)
  l=l+i;
return l;
}
和ASM链接的方法如下
1.先取得VB编译后的lst文件 如果不会请参考如何取得VB编译后的lst文件
当出现Link画面时 请先不要Link
由于GetSum是在Module1.bas中,他的输出会在Module1.lst
用记事本打开Module1.lst 内容如下
TITLE C:\gs\Module1.bas
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
text$1 SEGMENT PARA USE32 PUBLIC ''
text$1 ENDS
; COMDAT ?GetSum@Module1@@AAGXXZ
text$1 SEGMENT PARA USE32 PUBLIC ''
text$1 ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC ?GetSum@Module1@@AAGXXZ    ;Module1::GetSum
EXTRN __imp____vbaErrorOverflow:NEAR
; COMDAT ?GetSum@Module1@@AAGXXZ
text$1 SEGMENT
?GetSum@Module1@@AAGXXZ PROC NEAR   ; Module1::GetSum, COMDAT

; 4    : Public Function GetSum() As Long

xor eax, eax

; 5    : Dim i As Long, l As Long
; 6    :
; 7    : For i = 1 To 100

mov ecx, 1
$L27:

; 8    :     l = l + i

add eax, ecx
jo SHORT $L19
add ecx, 1
jo SHORT $L19
cmp ecx, 100    ; 00000064H
jle SHORT $L27

; 9    : Next
; 10   :
; 11   : GetSum = l
; 12   : End Function

ret 0
$L19:
call DWORD PTR __imp____vbaErrorOverflow
?GetSum@Module1@@AAGXXZ ENDP    ; Module1::GetSum
text$1 ENDS
END
2.注意用红色标明的部分GetSum备编译后 函数名称已经改为?GetSum@Module1@@AAGXXZ 我们需要修改一下原来组语中的函数名称修改如下
.386P
.model FLAT
PUBLIC ?GetSum@Module1@@AAGXXZ
.code
?GetSum@Module1@@AAGXXZ PROC NEAR
xor eax, eax
mov ecx, 1
loop1:
add eax, ecx
inc ecx
cmp ecx, 100   
jle loop1
ret 0
?GetSum@Module1@@AAGXXZ ENDP
END
这个程序我放在Module1.asc
编译Module1.asc
建议使用MASM编译 比较不会有格式问题 请输入
ml /c /Cp /coff /Zm Module1.asc
然后将编译出的Module1.OBJ覆盖原先由VB编译出的Module1.OBJ
然后按下Link窗口的开始Link按钮即可完成编译
和C链接的方法如下
先将C转为ASM 由于C编译器和VB函数命名方式不同 不能直接编成OBJ在链接 只要把C输出成LST即可以下以BCC为例子
输入
BCC32 -5 -S -Ox Module1.cpp
他会将lst输出到Module1.asm 之后链接方法就和之前的Asm链接法一样
至于使用这个方法 效能能提升多少呢 以下是在Pentium 4-M 1.8GHz,512MB的机器下的测试结果
VB      
301 ms
C        160 ms
ASM   
130 ms
效能确实是有提升
程式
Option Explicit

Private Declare Function OpenProcess Lib "kernel32" _
   (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
    ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" _
   (ByVal hObject As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" _
   (ByVal hProcess As Long, lpExitCode As Long) As Long

Const PROCESS_QUERY_INFORMATION = &H400
Const SYNCHRONIZE = &H100000
Const STILL_ALIVE = &H103

Dim ExitCode As Long
Dim hProcess As Long


Private Sub Command1_Click()
Dim pid As Long

Command1.Enabled = False
Me.Hide
DoEvents

pid = Shell("iLink " & Command, vbHide)

hProcess = OpenProcess(PROCESS_QUERY_INFORMATION + SYNCHRONIZE, 0, pid)

Do
  Call GetExitCodeProcess(hProcess, ExitCode)
  DoEvents
Loop While ExitCode = STILL_ALIVE

Call CloseHandle(hProcess)

Unload Me

End Sub

Private Sub Form_Load()
List1.Clear
List1.AddItem "
这个程序可以暂缓Link.exe执行"
List1.AddItem "再按下""开始Link""前 你可以先编译"
List1.AddItem "你的程序(用C或是Assembly)所做出的lst文件"
List1.AddItem "(记得函数名称命名必须和和替换掉程序的命名相同)"
List1.AddItem "编译只要用任何32bit的Assembly编译器应该都可以"
List1.AddItem "    TASM编译方式是这样tasm32 /ml xxx.lst "
List1.AddItem "    MASM编译方式是这样 ml /c / Cp / coff /Zm xxx.lst"
List1.AddItem "编译完成后 按下""开始Link""即可"

End Sub
范例下载
  C2.zip
文件出处
Honey
整理时间
2003'2,30.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

评分

参与人数 1威望 +1 人气 +1 收起 理由
KusoSoft + 1 + 1 精品文章

查看全部评分

发表于 2009-8-7 10:03:45 | 显示全部楼层
居然坐了新林的沙发了。
回复 支持 反对

使用道具 举报

发表于 2009-8-7 10:46:45 | 显示全部楼层
慢慢看,板凳先坐。
回复 支持 反对

使用道具 举报

发表于 2009-8-7 10:51:36 | 显示全部楼层
标记下,学习
回复 支持 反对

使用道具 举报

发表于 2009-8-7 10:58:37 | 显示全部楼层
这个早有插件实现自动化了,
不需要手工改这么累.

thundervb ->迅雷VB?
回复 支持 反对

使用道具 举报

发表于 2009-8-7 11:43:33 | 显示全部楼层
本帖最后由 coyove 于 2009-8-7 11:45 编辑

我也写过,与此类似
http://www.vbgood.com/viewthread.php?tid=82528

评分

参与人数 1人气 +1 收起 理由
msflexgrid + 1 类似的好像在别的地方看过,原来你是作者啊,

查看全部评分

回复 支持 反对

使用道具 举报

发表于 2009-8-7 14:30:38 | 显示全部楼层
另外新林不要老是转贴.
如果一个网站真的好.你到资源区发个网站的入口就行了.

假设我开个论坛,然后把VBGOOD的一贴一贴的原创转载过去,大家会如何想?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-8-7 15:46:16 | 显示全部楼层
另外新林不要老是转贴.
如果一个网站真的好.你到资源区发个网站的入口就行了.

假设我开个论坛,然后把VBGOOD的一贴一贴的原创转载过去,大家会如何想?
msflexgrid 发表于 2009-8-7 14:30


msflexgrid,没有那么夸张,只是把我觉得好的这两三篇转来而已,没有其它的想法,更不会整站转的想法,我也没那么大的精力,只是好像在论坛里没见过类似的资料,再说原贴地址也有,愿意的自己去看就好了啊~~
回复 支持 反对

使用道具 举报

发表于 2009-8-8 07:52:43 | 显示全部楼层
一场误会,以为你当了版主就要负责到处转载呢.
回复 支持 反对

使用道具 举报

发表于 2009-8-8 16:40:09 | 显示全部楼层
7# msflexgrid

***.tw 随时可能被墙掉的……

评分

参与人数 1人气 +1 收起 理由
msflexgrid + 1 .tw的比较稳定,几年都还在,而中文的VB站反

查看全部评分

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

文字版|手机版|小黑屋|VBGood  

GMT+8, 2022-7-3 00:28

VB爱好者乐园(VBGood)
快速回复 返回顶部 返回列表