为什么?
关于混合编程
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
关于混合编程
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