49

我并不是要引发英特尔与 AT&T 的战争(无论如何,现在它们都支持英特尔语法,这是有争议的)或者问哪个本身“更好”,我只是想知道选择一个或另一个的实际差异.

基本上,几年前当我学习一些基本的 x86 程序集时,我无缘无故地使用了 NASM,除了我正在阅读的那本书——这让我坚定但不由自主地加入了 NASM 阵营。从那以后,我很少有使用汇编的理由,所以我没有机会尝试 GAS。

请记住,它们都支持英特尔语法(我个人更喜欢)并且至少在理论上应该产生相同的二进制文件(我知道它们可能不会,但不应该改变含义),有什么理由支持非此即彼?

是命令行选项吗?宏?非助记词?或者是其他东西?

谢谢 :)

4

3 回答 3

33

NASM 实际上使用了自己的 Intel 语法变体,与 Intel 官方文档中使用的 MASM 语法不同。操作码名称和操作数顺序与 Intel 中的相同,因此乍一看指令看起来相同,但任何重要的程序都会有所不同。例如,对于 MASM,使用的指令MOV ax, foo取决于 的类型foo,而 NASM 没有类型,它总是汇编为立即移动指令。当无法隐式确定操作数的大小时,MASM 需要DWORD PTR在 NASM 用来DWORD表示相同事物的地方使用类似的东西。除了指令助记符和基本操作数格式和顺序之外的大多数语法都是不同的。

就功能而言,NASM 和 GAS 几乎相同。两者都有汇编宏工具,尽管 NASM 更广泛和更成熟。许多 GAS 源代码文件使用 C 预处理器而不是 GAS 自己的宏支持。

两个汇编器之间最大的区别是它们对 16 位代码的支持。GAS 不支持定义 x86 段。使用 GAS,您只能创建简单的单段 16 位二进制映像,基本上只是引导扇区和 .COM 文件。NASM 完全支持分段并支持 OMF 格式的目标文件,您可以使用合适的链接器来创建分段的 16 位可执行文件。

除了 OMF 对象文件格式之外,NASM 还支持 GAS 不支持的许多格式。GAS 通常只支持运行它的机器的本机格式,基本上是 ELF、PE-COFF 或 MACH-O。如果您想支持不同的格式,您需要为该格式构建 GAS 的“交叉编译”版本。

另一个显着的区别是 GAS 支持创建 DWARF 和 Windows 64 位展开信息(Windows x64 ABI 需要后者),而使用 NASM 您必须自己创建部分并填写数据。

于 2015-06-20T17:42:24.617 回答
29

英特尔语法:mov eax, 1(指令目标,源)

AT&T 语法:movl $1, %eax(指令源,目标)

Intel 的语法很容易解释。在上面的示例中,移动的数据量是根据寄存器的大小(在 eax 的情况下为 32 位)推断出来的。使用的寻址模式是从操作数本身推断出来的。

AT&T 语法有一些怪癖。首先,注意指令l末尾的后缀mov,它代表long并表示 32 位数据。其他指令后缀包括 w一个字(16 位 -不要与 CPU 的字长混淆!)、q一个四字(64 位)和b一个单字节。虽然并不总是需要,但通常您会看到使用 AT&T 语法的汇编代码明确说明指令正在操作的数据量。

当涉及到源操作数和目标操作数上使用的寻址模式时,需要更加明确。$表示immediate寻址,就像使用指令本身中的值一样。在上面的例子中,如果没有 this 写入$direct将使用寻址,即 CPU 将尝试获取内存地址 1 处的值(这很可能会导致分段错误)。%表示register寻址,如果您没有在上面的示例中包含它,将eax被视为一个symbol即标记的内存地址,这很可能会导致undefined reference链接时间。因此,您必须明确说明两者使用的寻址模式源操作数和目标操作数。

指定内存操作数的方式也不同:

英特尔:[基址寄存器 + 索引 * 索引大小 + 偏移量]

AT&T:偏移量(基址寄存器、索引、索引大小)

英特尔语法使查找内存地址的计算更加清晰。使用 AT&T 语法,结果是相同的,但您应该知道正在发生的计算。

至少理论上应该产生相同的二进制文件

这完全取决于您的工具链。

偏爱其中一个的原因是什么?

当然,个人偏好,在我看来,这归结为在寻址内存时您感觉更舒服的语法。你更喜欢 AT&T 语法的强制明确性吗?或者你更喜欢你的汇编程序为你找出这个低级细节?

是命令行选项吗?宏?非助记词?

这与汇编程序(GAS、NASM)本身有关。再次,个人喜好。

于 2015-06-20T13:16:12.287 回答
0

为什么不检查这篇文章

NASM 和 GAS 之间最大的区别之一是语法。GAS 使用 AT&T 语法,这是一种相对古老的语法,专用于 GAS 和一些较旧的汇编程序,而 NASM 使用 Intel 语法,得到大多数汇编程序(如 TASM 和 MASM)的支持。(现代版本的 GAS 确实支持名为 .intel_syntax 的指令,它允许在 GAS 中使用 Intel 语法。)

它涵盖:

  • NASM 和 GAS 之间的基本语法差异
  • 常见的汇编级结构,例如变量、循环、标签和宏
  • 关于调用外部 C 例程和使用函数的一些信息
  • 汇编助记符区别及用法
  • 内存寻址方法

一个好的做法是用两种方言写hello_world,有具体的感觉。

于 2020-05-25T22:00:35.740 回答