第4章 汇编语言和汇编软件
该章主要介绍了汇编语言和汇编语言编译器的安装和使用。
汇编语言程序
该小节主要介绍了为什么要有汇编语言和汇编语言程序的一些基础写法。
书中有提到CPU有不同的架构,汇编语言有不同的风格,那么不同的CPU架构和不同的汇编风格到底是什么关系呢?有些东西如果不了解全貌,感觉身在此山中呢!
为了厘清这些个东西,继续搜资料(资料链接参见文章尾部),最后整理出汇编风格、编译器和指令集这3类。
备注:编译器和CPU(指令集)架构没有列全,这里主要是列一些主要的。
这三大类之间的关系是什么呢?因为编译器是将汇编代码编译成机器代码的程序,理论上来说编译器可以决定风格和支持的CPU架构,故列一个表格进行说明就清晰了。
该书汇编主要采用NASM编译器,Intel的风格,支持x86和x86-64架构,这下就清晰多了,知道自己学习的是其中哪个汇编了,位于整体中的哪个位置了。
书中列举了一些例子,这里摘录如下:
mov ax,3FH ;将立即数3EH传送到寄存器ax中
add bx,ax ;将寄存器bx的内容和寄存器ax的内容相加,结果在bx中
add cx,ax ;将寄存器cx的内容和寄存器ax的内容相加,结果在cx中
3FH最后个H字母表明这是一个十六进制数,但是很多高级语言中,都是添加0x前缀:
mov ax,0x3F
作者提到为什么是用0x?没有找到原因。我尝试去找了一下,找到一篇 stackexchange 上一篇文章,链接见文末,大概得意思就是说:
- BCPL语言 使用了#b表示二进制、#o表示八进制、 #x 表示十六进制;
- B语言 放弃了 # 这种方式,采用 0 作为前缀表示八进制。又因为当时八进制和机器架构更加适合,所以就没有设计十六进制的表示方式。
- C语言 时代十六进制和机器架构更合适,所以结合B语言和BCPL语言就用了0x表示了。
作者如果有看到这篇文章,能否请我喝杯咖啡哈?
如果不习惯十六进制,0x3F也可以用二进制和十进制代替:
mov ax,63 ;十进制,末尾可以加D如63D,也可以不加。
mov ax,00111111B ;二进制末尾要加1个B
几个进制之间列个表格就更加清楚了:
其实B、O、D、H就是对应英文单词的首字母,英文好的话对变成帮助真的很大。
另外在网上搜索相关资料时,发现了汇编语言的层级介绍,遂摘录在此。
从图中可以看出Assembly Language处于机器语言和高级语言之间,但是据我了解,现在也有高级语言直接翻译成机器语言了,不用经过汇编了。如C、Ruby、Go、Java、C#等。
NASM编译器
该小节介绍了NASM的安装和使用,以及用什么IDE编写汇编和如何查看编译后二进制编码。
NASM的下载和安装
NASM的全称是Netwide Assembler,它是可免费使用的开源软件,并且可以支持Linux、Windows、MacOS等多平台。
NASM官网:https://www.nasm.us
然后跟着书本讲解,进行操作交作业。我的电脑是Win10,所以下载了Windows 64位的,并安装在了:D\Env\NASM 目录。
然后配置Path环境变量:
代码的书写和编译过程
书中作者自己编写了一个Nasmide软件编写汇编,只是我没有用,我自己习惯是用Visual Studio Code,然后在增强版的CMD工具 PowerShell 里进行编译。
Visual Studio Code我是安装这个插件:x86 and x86_64 Assembly,显示效果也不错:
PowerShell 一开始敲命令还挺麻烦的,但是敲了第一次后,可以通过 ctrl+r 进行历史命令查找还是挺方便的。
常用命令格式:
nasm -f bin exam.asm -o exam.bin -l exam.lst
- f bin:表示生成的文件只包含纯二进制的,只有处理器能够识别的代码。
- -o:输出的二进制文件,运行就是用这个文件。
- -l:输出的汇编列表文件,方便debug用。
用HexView观察编译后的机器代码
生成二进制文件后,调试的时候经常会需要查看二进制文件,所以如果能转成16进制查看就比较友好。
书中作者介绍了 HexView 软件可以进行查看,我还是习惯用 Visual Studio Code ,想着是否有插件支持,于是在插件库搜索 Hex,发现了 Hex Editor 这个插件,安装后:
右击文件 -> Open With -> 多了一个Hex Editor选项 选择 Hex Editor 打开,效果感觉也不错,如下图:
不得不说,Visual Studio Code 确实很强大。
配书文件包的下载和使用
作者提供了书籍配套的源码和工具包,除了源码编码是gb2312的,我都一一转成了utf-8,其他没有发现什么问题,真的是非常给力。
本章习题
开始写作业了。作业要用到图4-8,摘录在此。
对应的源码是:
mov ax,0x3f ;将0x3f传送到AX寄存器
add bx,ax
add cx,ax
如图4-8所示,请问:
- 源程序共有3行,每行第一个字符在文件内的偏移量分别是多少?
- 第一行第一个字符m在文件内的偏移量是 0;
- 第二行第一个字符a在文件内的偏移量是 0x35;
- 第三行第一个字符a在文件内的偏移量是 0x40;
- 该源程序文件的大小是多少字节?
最后一个字符的偏移地址是 0x49,所以源程序文件大小就是 0x49+1=0x50 字节了。(偏移地址从0开始计算)
参考资料
- 处理器架构、指令集和汇编语言,三者有何关系? - young cc的回答 - 知乎
- 编程语言-2-处理器架构、指令集和汇编语言_指令集和芯片 汇编的区别-CSDN博客
- 不同汇编语言的对比_汇编语言版本区分-CSDN博客
- 常见CPU架构、产品、指令集、特点 - 程序员老吴的文章 - 知乎
- Introduction to Assembly Language with Examples - Just Code
- history - Where and when did the 0x convention for hexadecimal literals originate? - Retrocomputing Stack Exchange