Evian Zhang's
naive blog

macOS上的汇编入门(五)——第一个汇编程序

通过前几篇文章,我们逐步建立了学习汇编语言之前需要的基础知识。接下来,在这篇文章中,我们开始编写我们的第一个汇编程序了。

编辑器,汇编器与链接器

工欲善其事,必先利其器。我们编写汇编语言,至少需要编辑器、汇编器和链接器。编辑器,就是提供语法高亮、智能缩进、自动补全等功能的文本编辑软件,汇编器与链接器则是汇编语言需要的核心装备,其功能我会在接下来的几篇文章中提到。我使用的编辑器是Visual Studio Code, 汇编器是自带的 as , 链接器也是自带的 ld .

第一个程序

我们在编辑器中输入如下语句,并在自己的目录下保存为 exit.s .

# exit.s    
    .section    __TEXT,__text
    .globl  _main
_main:
    movq    $0, %rax
    retq

然后在终端下进入该目录,键入如下命令:

as exit.s -o exit.o

然后再键入

ld exit.o -o exit -lSystem

此时该目录下应该会有一个叫 exit 的可执行文件,我们在终端下运行它:

./exit

然后,什么都没有发生,程序自动退出了。大功告成!

关于这个程序的解释,我决定下篇文章再讲。这篇文章接下来的篇幅,我打算谈一谈汇编器与汇编语法。

汇编语法

汇编语言是机器码的human-readable版本。虽说如此,汇编语法现在的主流也有两大阵营:Intel语法与GAS语法。其最显著的区别就在于,Intel语法的组成是「指令+目的+源」,而GAS语法的组成是「指令+源+目的」。就比如说,同样的意思,Intel语法是“给小明一个粉笔”,而GAS语法则是“把一个粉笔给小明”。这两种语法并没有优劣,在这一系列文章中,我主要介绍的是GAS语法。

Intel语法是在Windows上进行汇编语言编程时主要使用的,而GAS语法,又称为AT&T语法,则主要是在Linux和类Unix上进行汇编语言时会用到。这里并不是说在不同操作系统上必须用不同的语法,在类Unix的macOS上也能用Intel语法,只不过是大家都偏好这么用罢了。

GCC与LLVM

我们知道,对于一门编程语言来说,它有对应的编译器和调试器。对于编译器来说,在类Unix系统上主要有两大阵营:GCC和LLVM. GCC包括C编译器 gcc 、调试器 gdb 等,LLVM项目包括C编译器 clang 、调试器 lldb 等。对于编译器,GCC的思路是对于每一个CPU架构、每一种操作系统,都开发一个对应的编译器,将代码直接编译成对应的可执行文件;而LLVM项目的思路则是将编译过程分为前端和后端,无论是在什么平台、什么CPU架构下,编译器前端都是相同的,将源代码编译成llvm中间码(IR). 而后端则是将IR再翻译成对应操作系统中对应CPU架构下的可执行文件。因此,如果有a种语言,b个操作系统和c个CPU架构,那么GCC一共需要abc种编译器,而LLVM项目则一共需要a种前端和bc种后端,最终效果是只需要a+bc种编译器代码。

对于高级编程语言,GCC与LLVM的竞争主要在于编译的优化、效率等,但是对于汇编语言,由于其可以直译机器码,所以并不存在汇编器优化,因此,在机器码层面,GCC和LLVM是等效的。在这一系列文章中我使用的汇编器 as 是"Mac OS X Mach-O GNU-based assemblers", 调试器是LLVM的 lldb .

GCC套件是GNU操作系统的一个部分,GNU是开源的、社区驱动的。而LLVM项目也是开源的,现在主要是Apple在投资运行。因此,既然在macOS上,我就主要用的是LLVM系的工具。

可以在哪看到这系列文章

我在我的 GitHub 上, 知乎专栏 上和 CSDN 上同步更新。

上一篇文章: macOS上的汇编入门(四)——操作系统基础

下一篇文章: macOS上的汇编入门(六)——汇编语言初识