也不知道怎么了,最近想搞搞这个东西,嘿嘿,,可能觉得某些方面对速度要求不高的用c/c++就可以了且很方便,可对速度要求高的用汇编来实现也是个不错的选择。。而通常情况下,这两条都希望有,所以想到了交叉编译,当然写成DLL形式再接口调用也未尝不可,只是有时希望整合一下,嘿嘿。。。。罗嗦了吧,哈哈,下面开始吧。
说明:
1.调用约定
统一采用_stdcall方式压栈,通常用于Win32 Api中,函数采用从右到左的压栈方式,
自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。
比如:int f(void *p) 编译后为 _f@4(在外部汇编语言里可以用这个名字引用这个函数)
2.名字修饰约定
C或者C++函数在内部(编译和链接)通过修饰名识别。修饰名是编译器在编译函数定义或者原型时生成的字符串。
修饰名由函数名、类名、调用约定、返回类型、参数等共同决定。
a、C编译时函数名修饰约定规则:
__stdcall调用约定决定了在输出函数名前加上一个下划线前缀,后面加上一个“@”符号和其参数的字节数,
格式为_functionname@number。
b、C++编译时函数名修饰约定规则:
通过extern "C"强制采用C编译时的函数名修饰约定规则a。
3. 以下程序均以上面两条约定方式、windows vc6.0包 环境实现,其他方式也未尝不可,只是这种方式用的多一点吧。。
C/C++调用汇编函数
也不想多说什么,给个具体的例子吧
我们要通过C/C++来调用下面的汇编函数GetArgument PROC a:DWORD
.386
.model flat,stdcall
option casemap :none
.code
GetArgument PROC a:DWORD
mov eax, a
ret
GetArgument ENDP
end
将其保存为myasm.asm文件。写个批处理将其编译成目标文件:
@echo off
set include=e:/masm32/include
set lib=e:/masm32/lib
set path=e:/masm32/bin;%path%
echo --------------========By GoldenSpider 2010-7-26========---------------
echo on
ml /c /coff myasm.asm
pause
保存为myasm.bat双击得到myasm.obj文件。
接下来,通过C或C++来调用这个汇编函数。下面是C或C++的统一写法:
#include <stdio.h>
#ifdef __cplusplus
#include <windows.h>
extern "C" {
#endif
int _stdcall GetArgument(int);
#ifdef __cplusplus
}
#endif
int main()
{
printf("Good luck!! C_Call_Asm Succeed return %d/n",GetArgument(10));
system("PAUSE");
return 0;
}
保存为myc.c或myc.cpp即可
再写个批处理交叉编译myc.c和myasm.obj得到可执行文件:
@echo off
set include=D:/vcPack/include;D:/vcPack/MFC/Include
set lib=D:/vcPack/lib;D:/vcPack/MFC/lib
set path=D:/vcPack/bin;%path%
echo --------------========By GoldenSpider 2010-7-26========---------------
echo on
cl /c myc.c
link /subsystem:console myc.obj myasm.obj
pause
myc.exe
pause
保存bat文件双击即可,运行效果如下:
汇编调用C/C++函数
我们要通过汇编来调用C/C++函数int GetArgument(int a) 采用前面的两条约定方式,下面是C/C++的统一写法:
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
int __stdcall GetArgument(int a)
{
printf("Good luck!! Asm_Call_C Succeed return %d/n",a);
return 0;
}
#ifdef __cplusplus
}
#endif
保存为myc.c或myc.cpp即可
下面写个批处理来编译这个myc.cpp文件
@echo off
set include=D:/vcPack/include;D:/vcPack/MFC/Include
set lib=D:/vcPack/lib;D:/vcPack/MFC/lib
set path=D:/vcPack/bin;%path%
echo --------------========By GoldenSpider 2010-7-26========---------------
echo on
cl /c myc.cpp
pause
保存为myc.bat 双击执行得到myc.obj文件。
接着写汇编啦,嘿嘿
.386
.model flat,stdcall
option casemap:none
GetArgument proto :dword ;函数申明
.code
start:
invoke GetArgument,10 ;函数调用
xor eax,eax
ret
end start
保存为myasm.asm文件
再写个批处理来编译上面的myc.obj和myasm.asm,生成可执行文件:
@echo off
set include=e:/masm32/include
set lib=e:/masm32/lib
set path=e:/masm32/bin;%path%
echo --------------========By GoldenSpider 2010-7-26========---------------
echo on
ml /c /coff myasm.asm
link /subsystem:console myasm.obj myc.obj msvcrt.lib
pause
myasm.exe
pause
保存bat文件双击即可,需要说一下的是,由于原c中用到了printf函数,所以在链接时要包含库文件msvcrt.lib,运行效果如下: