上次我们提到了汇编语言的两种格式,Intel 和 AT&T 格式,今天讲的是对应两种编译器的一些使用。
我们知道,编译器就是一个将一种程序语言翻译成另外一种语言的程序。编译的过程其实共有5个流程:词法分析、语法分析、语义分析和中间代码生成、优化、目标代码生成。具体是怎么实现的,有兴趣的话,可以找一本好的《编译原理》书看一看,顺便自己也尝试写一个编译器。
对于汇编语言呢,不同平台不同格式都有各自不同的编译器,也有一些可以跨平台的编译器。那么上次我们提到的Intel 格式和AT&T格式汇编使用的编译器是什么呢?
Linux 中编译Intel 格式使用 Nasm, 编译AT&T格式使用Gas。
下面以Hello World程序做个示范,为了区分格式,我们将Intel格式的汇编代码文件后缀名写为.asm,而AT&T的写为.s.
Intel:
$> nasm -f elf hello.asm
或者
$> nasm -f elf64 hello.asm
上面的两条命令都会生成一个hello.o目标文件,下面的那条命令可以对上兼容。elf64相当于说是说明64位机器,elf是32位。看我们的代码可以知道,如果寄存器中使用的rax之类的,那么一定是64位的。当然,这个问题都不大,不管使用那一条命令,其实都能通过。
生成.o文件之后,我们就需要用链接器(linker)将目标文件链接起来,生成可执行文件
$> ld -m elf_i386 -o hello hello.o $> ld -o hello hello.o $> ld -o -m elf_x86_64 -o hello hello.o
上面的第1条链接命令对应前面的第一条编译命令,第2,3条是等价的,对应前面第二条编译命令。之前也说了,这是一个对应机器位数的问题。如果混用,会出现不匹配问题,看图说话。
情况就是这么个情况,不要问为什么。这就跟找对象一样,合适是很重要了。
AT&T
使用Gas编译AT&T格式汇编。Gas 是GNU中自带的,如果是Linux系统的话,基本上都自带了,不需要再安装。
Gas编译起来没有那么多花样
$> as -o hello.o hello.s
$> ld -o hello helle.o
通也是生成了可执行文件hello
测试一下
关于编译和链接的一些参数,可以通过使用 --help 参数来查看,一般来说掌握几个基本参数即可。
到目前来说呢,基本的概念和几个工具都已经简单讲完了,后面将会开始正式的开始我们的汇编语言学习。为了好看吧,将会以Intel格式来讲解,期待一波吧。