用 NASM 编写代码(转自http://www.codingnow.com/text/nasm.htm)
来源:互联网 发布:adapter数据更新 编辑:程序博客网 时间:2024/04/30 09:27
用 NASM 编写代码
本文主要为有汇编基础, 而习惯了用 VC 的 inline ASM 写代码的朋友们而作.
为什么要使用 NASM?
使用 inline asm 固然方便, 但是却不利于代码的移植. 加上 VC 对新指令集(3D Now! ,XMM 等)的支持速度不够, 使用起来很不方便, 所以我们往往采用外部汇编. 如果你以前熟悉 MASM 或是 TASM, 也不必更换, 否则云风推荐 NASM. NASM 及其文档在 http://www.web-sites.co.uk/nasm 可以下载的到. 使用前最好通读一遍文档. 本文只会强调一些重点部分, 而补充一点遗漏, 而不会全盘复述. NASM 支持各种最新的指令集, 有相当强大的宏语言支持. 你将得到比 VC 的 inline asm 更为灵活的使用空间.
选一个好的编程环境
将 VC 当作 NASM 的编辑环境是完全可行的, 只需要在 Tools->Customize->Tools 下加入 NASM.exe 作为外部工具. 这里不详细介绍. 云风推荐 Editplus 这款小巧实用的编辑器. 你可以指定各种关键字的颜色, 云风自己制作的语法文件在这里, 写的还不完备, 很多 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 段.
- text 段放置代码, 是只读且可运行段
- data 段放置静态数据, 这些数据会被放置入 exe 文件. 这个段是可读写, 但是不能运行的.
- bss 段放置动态数据, 这些数据不被放入 exe 文件, 在exe文件被加载入内存后才分配的空间.
一个简单的程序框架是这样的:
[bits 32][section .text]global _func_func:; 这里写func 函数的代码[section .data][section .bss]
这里, 用 global 声明了一个可被 C 调用的函数 func (C 函数都有一个下划线前缀) _func: 是这个函数的入口. 在对应的 C 代码里想使用 func 这个函数, 还需要用 extern 声明 func 是外部函数. 如果在 C++ 里使用则还需要将函数说明成 C 调用方式, 方法是用 extern "C" { } 说明
参数的传入和处理
函数的参数处理和其调用方式有关, C 的缺省调用方式是 _cdel 调用方式, C++ 的非静态成员函数采用的是 _thiscall, 关于各种调用方式的处理堆栈的方法, 在 MSDN 里可以查的到. 写 inline asm 可能很少涉及这些, 但是这里却必须搞清楚.
用纯汇编写 win32 程序等
写 WIN32 下的 win32/pe EXE, 我建议使用 Borland 的 obj 格式, 这是因为导入 DLL 中的 API 比较方便. 但是需要注意一些要点:
- NASM 缺省使用的segment 是 USE16 的, 而在 win32 下必须使用 USE32, 而且必须指定段的类型. 所以必须在源文件头写上这样几行:
[section .text class=code use32][section .data class=data use32][section .bss class=bss use32]%define __SECT__
- Borland 的 OBJ 文件里可以指定开始的标签(..start), 一般可以写成这样:
[section .text]..startWinMain:
你的代码将从 WinMain 这里开始运行. - 和 C 不一样, 你的主代码没有什么参数传入, 所以你必须自己来得到必要的参数. 比如:
push dword 0call GetModuleHandle; 获得 hInstance
获得 Instance 句柄(到 eax). - 退出程序也不能直接用 ret, 因为你的程序是一个进程, 而不是一个函数, 所以必须调用:
push dword 0; 退出码call ExitProcess
- 上面的 GetModuleHandle 是 kernel32.dll 里的 API: GetModuleHandleA, 所以需要在汇编源代码中声明导出:
import GetModuleHandle kernel32.dll GetModuleHandleAextern GetModuleHandle另外 ExitProcess 也是这样:import ExitProcess kernel32.dllextern ExitProcess
import 的具体用法请参考 NASM 的文档.
善于使用 NASM 强大的宏指令
这本是一个应该很丰富的 Section, 但是时间有限, 只举一个简单的例子, 定义下面这样一个宏:
%imacro callapi 1-*%define %%api %1%rotate -1%rep %0-1 %rotate -1 push dword %2 %endrep call %%api%endmacro
然后, 比如你需要调用 MessageBox, 就可以这样写
callapi MessageBox,[hWnd],lpText,lpCap,0
- hWnd 是一个全局变量保存的窗口句柄, 当然也可以是 0
- lpText 是文字的字符串指针
- lpCap 是MessageBox 的标题字符串
另外我自己还做了许多诸如处理函数参数, 保护堆栈等等方便使用的宏, 这里就不一一列出来了. 希望我引个头, 能让更多的朋友喜欢上 NASM
- 用 NASM 编写代码(转自http://www.codingnow.com/text/nasm.htm)
- 用 NASM 编写代码(转)
- 怎样优化Pentium系列处理器的代码 From:http://www.codingnow.com/2000/download/pentopt.htm#26_14
- 用 NASM 编写代码(转贴)
- 如何用NASM编写COM文件
- 用Nasm编写Windows窗口
- 我写的bootloader代码,用nasm编写
- 连接 Textfile http://www.javawolf.com/dbcon/text.htm
- Nasm
- NASM
- NASM
- nasm
- ViewState 剖析(翻译兼笔记) (转自http://www.zahui.com/html/4/8435.htm)
- 字符,字节和编码(转自http://www.regexlab.com/zh/encoding.htm)
- 搜索引擎基本工作原理(转自:http://www.se-express.com/about/about2.htm)
- 正则表达式参考文档(转自:http://www.regexlab.com/zh/regref.htm)
- 收藏常用正则表达式 转自shuguang http://www.osphp.com.cn/read.php/453.htm
- 嵌入式从业人员调查报告(转自:http://www.farsight.com.cn/survey2/report.htm)
- GetIdeDiskSerialNumber
- XML VS. CSV
- javascript里的类思想
- 2005年在IT领域创业干点啥?
- Spring 编程入门十大问题解答
- 用 NASM 编写代码(转自http://www.codingnow.com/text/nasm.htm)
- Open question (2:)
- 想搞一个程序员的wiki
- asp.net常用函数
- 试了一天,trackback 终于成功了(同时发现,csdn 的帮助系统 和 blog 是最烂的帮助和最烂的 blog 之一)
- Struts入门经验
- qq为什么能收费,为什么不用免费的msn
- Create a menu item into the Delphi menu
- Create a simple Delphi Expert(创建一个简单的Delphi专家)