读《Professional Assembly Language》之EAX消失之迷
今年是离开校园的第五年,这五年来我一直在从事应用软件的设计、开发工作,大部分时间是在与高级编程语言、设计模式、业务逻辑打交道。它们大多流于表面,久而久之,与技术底层疏远了,诸如计算机组成原理、汇编语言、编译原理、数据结构以及算法慢慢得生疏,时至今日,我已经弄不懂IA-32里有几类寄存器、间接寻址、词法分析是怎么一回事情了。五年是一个契机,趁着下一个五年开始之际,我计划用三个月至半年时想间,重新学习这些知识,以期达到巩固基础,厚积薄发的目的。
学习过程肯定会有问题,找不出问题的学生不是好学生。因此,我把遇到的问题和解决的方法记录下来,便形成了读书笔记。本篇博文便是我在阅读《Professional Assembly Language》一书时,所作的其中一篇读书笔记。《Professional Assembly Language》,中文译作《汇编语言程序设计》,是我学习汇编语言时选择的工具书,该书对于我这种已经有了高级语言的使用经验,又热衷Linux的人来说非常合适。
CPUID的例子出现第四章,A Sample Assembly Language Program,也是全书第一个完整的代码示例,结构简单,编译和链接均正常,执行结果也符合预期。
但是,在接下来的过程中出现了问题,DEBUG是日常工作的一部分,我把它视作是显微镜。使用GDB调试,每次查看通用寄存器都看不到想要的结果,而会被告知:Value can’t be converted to integer.
。
同时,如果使用 info registers,则根本找不到任何eax等寄存器的踪影,取而代之的是rax等一类新面孔,如图所示。
那么是什么原因引起了这个问题呢?这里要说明的是,《Professional Assembly Languge》出版时间在2006年前后,当时AMD / Intel 64刚刚推出不久,市场主流的PC架构还是IA32,这本书也是假定读者使用的是IA32。
但是,时过境迁,IA32已经淡出了市场。使用以下命令,来看看所使用的Linux是哪个架构的:
$ uname -a
Linux enaic 2.6.32-5-amd64 #1 SMP Tue Jun 14 09:42:28 UTC 2011 x86_64 GNU/Linux
显然,所使用的Linux是64-bit的,这和作者的假定环境是有出入的。那么这会有什么影响呢?如下所示:
$ file cpuid.o cpuid
cpuid.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
cpuid: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
哦,它们全成了64-bit。为了要配合书上的讲解,必须使得它们生成32-bit,为此,要进行如下操作:
$ as -gstabs --32 -o cpuid.o cpuid.s
$ ld -melf_i386 -o cpuid cpuid.o
$ file cpuid.o cpuid
cpuid.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
cpuid: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped
好吧,再次执行GDB,看看期待的结果有没有出现。
从IA32到x86-64,算是计算机发展史上的一次重大进步。但可惜的是,关于x86-64汇编目前资料还不多,比如本书还停留在IA32,比较期待作者能够与时俱进,因为这是本非常不错的书。
[…] 上文里说到了,在x86-64的机器上,通过对as命令加入–32 参数,并在 ld 命令里加入-melf_i386参数,即可编译并链接成32-bit的cpuid。关于这两个参数的说明,可以参看man手册。 […]