在VC中使用汇编语言,可以使用内联汇编,也可以编写独立的汇编语言文件放进工程中编译。由于VC在编译x64目标平台的程序时,不支持内联汇编,因此下面介绍编写独立的汇编语言文件,并加入VC的工程中进行编译的方法。
我们将编写一个小程序,来说明如何进行C语言与汇编语言的混合编译。
程序的功能很简单:生成a和b两个随机数,并显示a与b的和。其中,a与b求和的操作编写成一个函数,并用汇编语言实现这个函数。
使用VC2010创建一个Win32 Application的工程,并在工程中加入3个文件:main.c、add.asm、add.h,其中,main.c中包含程序的主函数,add.asm包含加法函数的实现,add.h包含加法函数的定义。
main.c的内容如下:#include <windows.h> #include "add.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int a = 0; int b = 0; TCHAR szBuffer[32]; srand(GetTickCount()); a = rand()%100; b = rand()%100; wsprintf( szBuffer, TEXT("%d + %d = %d"), a, b, Add_asm(a,b) ); if ( sizeof(void *) == 8 ) { MessageBox( NULL, szBuffer, TEXT("计算结果 - 64位"), MB_OK ); } else if ( sizeof(void *) == 4 ) { MessageBox( NULL, szBuffer, TEXT("计算结果 - 32位"), MB_OK ); } else { MessageBox( NULL, szBuffer, TEXT("计算结果"), MB_OK ); } return 0; }
add.h的内容如下:
#ifndef _ADD_HEADER_ #define _ADD_HEADER_ #include <windows.h> #if defined(__cplusplus) extern "C" { #endif DWORD __stdcall Add_asm( DWORD a, DWORD b ); #if defined(__cplusplus) } #endif #endif /* _ADD_HEADER_ */
add.asm的内容如下:
ifdef X86 .386 .model stdcall,flat endif option casemap:none public Add_asm .const .code ifdef X86 Add_asm proc a:dword,b:dword mov eax, a add eax, b ret endif ifdef X64 Add_asm proc mov rax, rcx add rax, rdx ret endif Add_asm endp end
建立好3个文件之后,我们还需要做如下2个工作:
1. 在Build->Configuration Manager中,添加一个x64平台
2. 右键点击add.asm,在弹出菜单中选择Properties,选择X86+Debug的配置,我们需要修改Custom Build Step->General中的两项:
在Command Line中填写ml.exe /c /D"X86" /D"DEBUG" /Fo"$(IntDir)/$(InputName).obj" $(InputFileName)
在Outputs中填写$(IntDir)/$(InputName).obj
ml.exe是VC提供的x86汇编器,x64汇编器为ml64.exe
/D用来定义宏,对于X64+Release的配置,可以修改为/D"X64" /D"RELEASE"
这样,一个可以编译的工程就配置好了。运行一下试试?
补充:
幸运的是,我们不需要对每个asm文件都进行上面2的步骤,因为第一次配置后,VC会生成一个编译规则文件,以后添加asm文件的时候,选择使用这个规则即可
再补充:
刚刚发现VC2008里面,asm文件是自动使用MASM编译的,不过有点问题,于是还是改成使用Custom Build,由于代码和工程是分别存放的,于是Command Line变成了这个样子:
cd $(InputDir)
ml64.exe /c /D"ARCH_X64" /D"CV_DEBUG" /Fo"$(ProjectDir)$(IntDir)/$(InputName).obj" $(InputFileName)
cd $(ProjectDir)
真难看……
另外记得把asm的头文件设置为Exclude from build=YES