follow my heart...
分类:
2006-09-15 13:38:09
[点评:NASM使用方式与TASM/MASM相似,在Linux下面应用非常广泛.在windows下面也有版本,强烈建议使用.]
本文主要为有汇编基础, 而习惯了用 VC 的 inline ASM 写代码的朋友们而作.
为什么要使用 NASM?
使用 inline asm 固然方便, 但是却不利于代码的移植. 加上 VC 对新指令集(3D Now! ,XMM 等)的支持速度不够, 使用起来很不方便, 所以我们往往采用外部汇编. 如果你以前熟悉 MASM 或是 TASM, 也不必更换, 否则云风推荐 NASM. NASM 及其文档在 可以下载的到. 使用前最好通读一遍文档. 本文只会强调一些重点部分, 而补充一点遗漏, 而不会全盘复述. NASM 支持各种最新的指令集, 有相当强大的宏语言支持. 你将得到比 VC 的 inline asm 更为灵活的使用空间.
选一个好的编程环境
将 VC 当作 NASM 的编辑环境是完全可行的, 只需要在 Tools->Customize->Tools 下加入 NASM.exe 作为外部工具. 这里不详细介绍. 云风推荐 这款小巧实用的编辑器. 你可以指定各种关键字的颜色, 云风自己制作的语法文件在, 写的还不完备, 很多 nasm 的宏语句尚未加入, 另外还加了一些自己制作的宏. 所以请各位读者酌情修改. 加入 Editplus 的方法是在 Tools-> Preferences->Files->Syntax 里增加一个语法文件. Editplus 支持 output 窗口信息捕获, 在 Tools->Preferences->Tools->User Tools 里增加 NASM.exe, 并选 capture output 就可以了. 当然如果你想制作单独的 win32/pe 文件, 而不是编译成 obj 供 VC link, 那么还需要一个 link 程序. 最好再配合 makefile 使用.
如何编译成可供 VC 连接的 obj
NASM 支持多种输出格式, 虽然 VC 号称是使用的 COFF 格式, 但实际上是有区别的. NASM 除了输出 COFF 格式外, 另外也支持 VC 的目标文件格式, 叫做 win32. 我在 Editplus 的 user tools 里设置的是
-i I:\nasm\include\ -f win32 -o $(FileNameNoExt).obj $(FileName)注: 这里的 -i 后是头文件的路径 将编译出来的 obj 加入 VC 的 project 里就可以了. 一般来说, 目标文件有三个段, 分别是 text/data/bss 段.
这里, 用 global 声明了一个可被 C 调用的函数 func (C 函数都有一个下划线前缀) _func: 是这个函数的入口. 在对应的 C 代码里想使用 func 这个函数, 还需要用 extern 声明 func 是外部函数. 如果在 C++ 里使用则还需要将函数说明成 C 调用方式, 方法是用 extern "C" { } 说明
[bits 32]
[section .text]
global _func
_func:
; 这里写func 函数的代码
[section .data]
[section .bss]
参数的传入和处理
函数的参数处理和其调用方式有关, C 的缺省调用方式是 _cdel 调用方式, C++ 的非静态成员函数采用的是 _thiscall, 关于各种调用方式的处理堆栈的方法, 在 MSDN 里可以查的到. 写 inline asm 可能很少涉及这些, 但是这里却必须搞清楚.
用纯汇编写 win32 程序等
写 WIN32 下的 win32/pe EXE, 我建议使用 Borland 的 obj 格式, 这是因为导入 DLL 中的 API 比较方便. 但是需要注意一些要点:
[section .text class=code use32]
[section .data class=data use32]
[section .bss class=bss use32]
%define __SECT__
你的代码将从 WinMain 这里开始运行.
[section .text]
..start
WinMain:
push dword 0
call GetModuleHandle ; 获得 hInstance
push dword 0 ; 退出码
call ExitProcess
import GetModuleHandle kernel32.dll GetModuleHandleA
extern GetModuleHandle
另外 ExitProcess 也是这样:
import ExitProcess kernel32.dll
extern ExitProcess
善于使用 NASM 强大的宏指令
这本是一个应该很丰富的 Section, 但是时间有限, 只举一个简单的例子, 定义下面这样一个宏:
然后, 比如你需要调用 MessageBox, 就可以这样写
%imacro callapi 1-*
%define %%api %1
%rotate -1
%rep %0-1
%rotate -1
push dword %2
%endrep
call %%api
%endmacro