前言
前面已经提到了为什么从MASM转到NASM,并且也简单的介绍了一下MASM和NASM在伪指令和程序结构上的差异,现在就来搭建一下NASM的编译、开发、调试环境吧。
参考资料:
http://blog.csdn.net/duweix/article/details/19911967
http://blog.csdn.net/cashey1991/article/details/6773927
http://www.mouseos.com/assembly/nasm02.html
http://www.linuxidc.com/Linux/2013-01/78271.htm
WINDOWS
nasm的安装配置
nasm的安装包可以在nasm的官方网站下载到最新的版本,注意安装的时候最好是右键管理员安装。
这之后你可以在CMD中输入 nasm -v 查看nasm的版本,我安装完之后nasm命令是未识别的,所以我手动添加了一下环境变量(如何添加环境变量请自行百度)
环境变量配置正确之后在cmd中输入 nasm -v 就可以看到nasm 显示了它的版本信息。
这个时候已经可以使用nasm直接编译汇编代码的,如果只是想编译二进制的代码那么其实这个时候环境搭建就完成了,但是纯二进制的代码在windows 10 上运行调试都很麻烦的。我能想到的一个办法就是以前提到过的,装个虚拟机用磁盘工具写到引导扇区,开机直接运行但是这样调试困难。
所以还是编译成exe在windows上直接运行吧,这样就可以借助各种调试工具了。但是编译成exe其实也有一个麻烦的地方就是好多中断不能使用, 以后CPU的内存管理啊,cpu的模式切换等等都没法使用,并且屏幕输出很麻烦。但是没关系,先编译成exe把程序逻辑调好,其他的只是接口的调用而已很方便集成的。
nasm可以通过 -f 指令指定要汇编的目标平台,可以使用 nasm -hf 查看支持的平台模式,默认是纯二进制的
所以你要编译纯二进制的文件的话,只需使用如下命令
nasm xx.asm
windows 32 为进程
nasm -f win32 helloworld.asm
windows 64 为进程
nasm -f win64 helloworld.asm
visual stdio的安装
没办法啊要编译windows的应用vs是躲不过去的, 我安装的是最新的vs2017.怎么装请自行百度咯。
编译调试
如何编译成exe参考 http://blog.csdn.net/duweix/article/details/19911967
主要是两条命令
1. 先将asm变成.obj文件
nasm -f win32 helloworld.asm
2. 将obj文件和c库链接成exe
cl.exe helloworld.obj /link libcmt.lib
链接博文z中的asm其实是调用了c的print函数在控制台输出了内容。博文中的示例汇编代码 我在公司的vs2008 环境下编译没问题,但是回家用vs2017就出现了找不到链接地址的情况。不知道是不是库不对。反正我没细究。不用print就是。
编译成的exe怎么调试呢?当然使用vs2017啦,当然也可以用windbg,厉害一点的用IDA也是可以的,反正就是各种反汇编调试工具。应为我们本来就是写的汇编,反汇编出来的结果和我们写的代码是一模一样的,所以调试很方便。
这里说一下vs2017具体的调试步骤
文件 =》打开 =》 项目
直接打开exe
如下图
然后右键 =》调试=》 单步调试
他可能会提示你没找到PDB文件或者没有源代码什么什么的,没关系按确定,然后把反汇编窗口显示出来
你也可以把寄存器窗口显示出现,这样就能看到寄存器的变化。
注意一点: 调试一开始可能不是停在了你汇编开始的位置,而是停在了C库的某个位置,这个时候你 F10 运行几步就会到你代码的开始位置了。
nasm with vs2017
前面的步骤已经可是开发编译调试了,但是你写汇编可能用一个文本编辑器 ,编译链接手动敲命令,vs只有在调试的时候才用到太可惜了。
接下来就是我自己摸索出来的在vs2017集成环境中开发编译调试汇编程序。
1. 新建一个 C++ 空项目
2. 右键属性 =》常规 =》配置项目改成 生成文件
3. 然后选择NMake标签 生成命令写上nmake,没错就是利用了windows的nmake工具,windows的nmake和linux下的make是一样的东西,所以同样也需要一个makefile
4. 新建一个makefile文件,内容如下
# 目标程序的名称,就是定义各一个宏定义,用来指定程序的名字,所以这个 hello.exe 是可以任意替换的,所编写啥 EXE = hello.exe # 需要用到的模块 这也是定义个一个宏变量OBJS, hello.obj 实际指的是 hello.asm 汇编文件# 所以如果你的汇编文件叫 helloword.asm 你就写 helloword.obj# 如果你的程序需要多个汇编文件也是支持的名字用空格隔开即可,也可以用 \ 表示换行,比如#OBJ = hello.obj\# print.obj\# input.objOBJS = hello.obj #编译的平台32?64FORMAT = win32 # 链接命令, 就是链接上面所指定的所有的obj,这个不用改 $(EXE) :$(OBJS) cd Debug cl.exe $(OBJS) /link libcmt.lib # 编译.asm成.obj,这是指定obj由asm编译而来,并是哟个下边的编译指令,所以可以看出我这里编译的都是32位的 .asm.obj: nasm -f $(FORMAT) $< -o Debug\$*.obj #清除临时文件 clean : del*.obj
具体makefile的语法规则可参考前言中给出的链接,上面这个是我研究了好久好不容易写出来的makefile,当然也只是研究了个皮毛出来而已。大家将就着试试。
5. 接下来就可以按F5运行调试,记得打开 反汇编窗口和寄存器窗口。
这是我写的一个例子: https://files.cnblogs.com/files/alwaysking/asm.zip
LINUX
linux下没啥继承环境,所以基本就只有敲命令咯
参考: http://www.linuxidc.com/Linux/2013-01/78271.htm
1. 先将汇编文件编译成.o文件对应的就是windows下的.obj,注意linux32要要选择编译成 elf32格式 64位要选择编译成 elf64
nasm -f elf32 hello.asm
2. 使用GCC将.o文件编译成可执行文件
gcc -o hello hello.o
make是linux下的项目编译工具,我也简单的写了一个makefile文件
# 目标名称EXE=hello
# 需要用到的模块 这也是定义个一个宏变量OBJS, hello.obj 实际指的是 hello.asm 汇编文件# 所以如果你的汇编文件叫 helloword.asm 你就写 helloword.obj# 如果你的程序需要多个汇编文件也是支持的名字用空格隔开即可,也可以用 \ 表示换行,比如
OBJS = hello.o
#编译的平台32?64FORMAT = elf32
# 连接命令这个不用改All:$(OBJS) gcc -o $(EXE)
# 编译对应的asm成.o文件,这个也不用改$(OBJS) $(OBJS): %.o: %.asm nasm -f $(FORMAT) $< -o [email protected]
# 清理操作.PHONY:clean clean: rm -rf *.o Test @echo "Clean done!"