关于BCB和MASM的混合编程

为什么?

关于混合编程
masm的优势在于macro的强大,对细节的精确控制;
C/C++的优势在于模块化,GUI容易控制
为什么不用TASm:支持库不全,它的macro不太会用,现在不升级
为什么不是BCB而不是VC:首先不会VC;好像VC也不存在与masm的兼容问题。BCB需要你用OMF方式来编译asm模块,在api的使用上有很大麻烦,本文主要是解决这个问题


¥怎样做?

一、在高级语言中用 asm{ }或宏定义方式,可应用在小范围内,缺点是只能用最初级的asm,C的编译器很难支持masm的高级应用
二、C中使用masm编译的obj或lib,优势明显,缺点是很难保证兼容性,即编译器难以通过
三、使用dll,很方便,但是要多出文件了


具体方法:
1、__cdecl 方式:
masm中类似于:
.386
.model flat
option casemap:none
...
PUBLIC  _Add3

.code
...
_Add3:
...
ret
end

注意开始的.model 中无stdcall开关,所以标号的声明前面需要加个_
然后编译(不可以应用任何系统lib、任何api)
在C中,声明
    #ifdef __cplusplus
    extern "C" {
    #endif

    int __cdecl Add3(int, int);

    #ifdef __cplusplus
    } /* extern "C" */
    #endif
注意声明中无_,因__cdecl的应用会加上_
此方式的缺点就是masm中不能应用api,因masm的lib都是stdcall方式(BCB的lib可不可以用??)




2、__stdcall 方式:
masm中类似于:
.386
.model flat, stdcall
option casemap:none
...
PUBLIC  Add3

.code
...
Add3:
...
ret
end

注意开始的.model 中有stdcall开关,所以标号的声明前面不需要加_,可以应用api
然后编译
在C中,声明
    #ifdef __cplusplus
    extern "C" {
    #endif

    int __stdcall _Add3(int, int);

    #ifdef __cplusplus
    } /* extern "C" */
    #endif
注意声明中需要加_,因__stdcall的应用不会加_
在无api引用时,此方式可以正常使用,但如果masm中使用了api,BCB编译时提示masm的lib不是OMF格式
解决:可以用BCB的lib..下一个问题是masm生成的obj中引入的api前面有_(因stdcall方式),现在是在obj中删除

如果api被声明成syscall方式,则不产生_,但调用者会错误的修复stack(in masm)
如果api被声明成c方式,产生_,而且调用者会错误的修复stack(in masm)
如果api被声明成stdcall方式(应该是默认方式),则产生_,调用者不会修复stack(in masm),但生成的api索引还会加上一个@8之类的尾巴,BCB的lib是非常干净的,_和尾巴导致BCB编译器不认。解决方法是手工在obj清除api名称中的垃圾,这差不多是目前最佳解决方案。



¥例:

in masm:

.386
.model flat, stdcall        ;使用flat, stdcall模式
option casemap:none        ;大小写敏感
includelib kernel32.lib        ;要使用BCB的lib, 它是omf格式,不要用masm带的lib
GetModuleHandleA  proto :dword    ;声明要使用的api,考虑包含masm的inc文件
PUBLIC  c Add3  ; :dword, :dword    ;声明对外的过程,注意我们使用C模式,编译后前面会加上_

.code
Add3  proc  near c aa:dword, bb:dword  ;proc定义部分,编译后会加上push ebp...因在下面我们用到了变量
;Add3:
  ;jmp  @f
  invoke  GetModuleHandleA, 0    ;测试使用api,正常
@@:
  mov  eax, aa        ;测试使用变量
  add  eax, bb        ;
  ret          ;返回,由调用者自行清理stack
Add3  endp          ;过程结束
end            ;汇编结束

注意BCB需要OMF格式的obj,要用bldomf.bat编译asm模块

这样生成的obj中api name前后都有多余的内容,为使之与BCB的lib兼容,必须手动清除。清除办法就是用objfixer清理一下,之后就可以在BCB里面连接了。

in BCB
in *.h file:
#ifdef __cplusplus
extern "C" {          ;声明外部C过程
#endif

int __cdecl Add3(int, int);      ;用C declare 方式,与masm中保持一致

#ifdef __cplusplus
} /* extern "C" */
#endif

in *.cpp file:
...
    ShowMessage(Add3(33,42));
...

这样就可以通过编译




¥现存难点:
变量及过程的相互引用还是很麻烦的,需要很小心的处理。另外不同call模式及编译器的工作方式可能会导致堆栈平衡问题,需要仔细的debug 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值