0xAA55 发表于 2014-2-16 22:53:26

【混合编程】NASM与VC6合体编程

其实编译的原理无非是各个编译器负责编译自己的文件为中间文件,然后让链接器把各个中间文件链接起来,得到可执行文件等。所以说VC6和NASM编程,无非就是让VC6的编译器编译程序的C语言、C艹部分,然后让NASM编译汇编部分,最后用链接器完成链接。
这个叫“外联汇编”。比起内联汇编,外联汇编更安全。如果你有很多需要重复运行的指令,如果是C语言编写,运行速度可能会受到影响,而如果交给汇编,运行速度就能得到保障。
此外外联汇编还能做到一些C语言做不到的事,比如调用CPUID指令查看CPU的型号、参数等,这样的话要么内联汇编,要么外联汇编。
废话不多说。第一步,用VC6打开一个VC6的工程。

切换到FileView(文件视图)。如下所示:

然后菜单“文件->新建”

选择“文件->C++ Source File”文件名的话,就输入“×××.ASM”。也就是自定文件名。但是最好是英文。
我不能保证就算NASM能正常编译中文名文件的源码LINK也能识别中文中间文件名。所以最好是英文。
然后点确定。正常的节奏应该是如下图所示的:

然后就会多出一个“×××.ASM”在工程的文件视图。因为“×××.ASM”是新建的,因此它是空的。
没有问题的话是如下图所示的。

这个时候,我觉得,为了便于管理,我会在文件视图专门给NASM的源码新建一个文件夹。
所以大家也跟着我建立文件夹吧。


然后把你刚才产生的“×××.ASM”拖进去,应该是下面这个样子的:

关键的地方在这里!!在你建立的文件夹上点右键->设置,如下所示:

在弹出的对话框中找到“自定义组建”,描述那里就填写“正在用NASM编译$(InputPath)”然后在“命令”那里输入编译的命令:
nasm -f win32 $(InputPath) -o $(TargetDir)\$(InputName).obj再在“输出”那里输入编译器编译后的中间文件名,也就是编译器输出的文件名:$(TargetDir)\$(InputName).obj没有问题的话,应该是如下图所示的:

Ps:NASM的命令详见NASM说明文档:(全英文但是非常非常详细)
http://www.nasm.us/pub/nasm/releasebuilds/2.11/doc/nasmdoc.txt
嗯,这里输入好了以后点确定就行。设置好以后应该是这个样子的:

好!现在开始编程了。我在这里讲讲要点。
1、代码放在代码段.text
2、数据放在数据段.data
3、未初始化数据放在未初始化数据段.bss
然后NASM怎么引用C的符号呢?用extern声明外部符号。
NASM怎么导出符号给C用呢?用global导出内部符号。C语言的_cdecl形式的函数的特点从汇编的角度来讲就是:
1、参数逆序压栈。
2、返回的时候用ret
3、调用者自行将栈维持平衡。也就是说,调用者要把压入的参数弹掉。
4、如果返回值是浮点数,那么返回值放在浮点处理器的浮点数栈的栈顶。而如果返回值是正数,那么返回值放在eax寄存器。
C语言的_stdcall形式的函数的特点从汇编的角度来讲就是:
1、参数逆序压栈。
2、返回的时候用“ret 参数占用字节数”指令。也就是被调用者要维护栈,把参数弹掉。
3、返回值的特点和_cdecl是一样的。
寄存器的使用要点:
1、eax、ecx、edx、随便用。这三个寄存器不需要保护。
2、ebx要保护。esp是栈,要维持栈平衡。ebp是访问栈参数、临时变量的寄存器,要保护起来。
3、esi、edi是C、C艹用来当做一些常用变量的寄存器,比如for(int i=0;i<10;i++)这句很可能就是把esi当做变量i,从而省去了分配内存的间隔。
关于符号的使用要点:
1、C++输出的符号和C的不同点是C++输出的符号会有奇怪的修饰。其实是为了实现函数重载。因此对C++的函数要特殊考虑。
2、C语言输出的符号是带有下划线前缀的,也就是“_”,这点修饰比C++的简单多了。
3、_stdcall的函数的修饰是后面加一个“@参数占用字节数”。比如int _stdcall A(short);因为这个函数有一个参数,虽然这个参数是short类型的但是因为函数参数表是4字节对齐的,因此它输出的符号应该是“_A@4”,它最后的返回指令是“ret 4”
4、调用API的时候,我举个例,是这样的:extern __imp__MessageBoxA@16

global _ShowMsgBox    ;void ShowMsgBox(void);

segment .text
_ShowMsgBox:
push 0
push msgTitle
push msgPrompt
push 0
call dword
ret

segment .data
msgPrompt       db "这个是提示文本"
msgTitle      db "这个是标题栏"
这么说感觉文字好无力。那么我这里给出一个VC和NASM的源码,供大家下载研究。

把上面这张图右键另存为ZIP就能解压看到源码啦。
页: [1]
查看完整版本: 【混合编程】NASM与VC6合体编程