为什么我要使用NASM而不是GNUAssembler(GAS)?

当 GAS 支持多种架构而 NASM 只支持 x86 架构时,为什么我要在 GNU 汇编器 (GAS) 上使用 NASM?我知道存在句法差异,但这并没有让我太困扰。

回答

ASM 本质上是不可移植的。对于其他 ISA,只有 GAS 指令是相同的(不是指令甚至注释字符),并且任何给定的 asm 源文件都将用于单个 ISA。GAS 本身支持多个目标并不是真正相关的,你仍然需要学习其他机器。(一旦您了解了基础知识,至少不难掌握,但指令语法差异通常更容易)。一些其他的汇编为其他的ISA使用NASM风格dbdd数据伪指令,其他人使用Unix风格.byte.long类似气体(或气体)。但这很容易适应。

GAS 最初设计用于汇编编译器输出;因此,它的错误消息并不总是适合人类使用。(就明确它不喜欢一条线的内容而言)。NASM 趋向于更好(但绝不是完美的),现代 GAS 通常也不错;一些主要项目(如 glibc 和 Linux)有手写的 GAS 源文件,所以肯定有人使用它。

NASM 有一种宏语言 ( https://www.nasm.us/doc/nasmdoc4.html ),它在某些方面比GAS 的.macro宏更容易用于复杂的东西。(尽管在 GAS 中使用 CPP 宏是很常见的)。

对于微基准测试(如今手动玩 asm 的少数原因之一),NASM 具有我不知道如何在 GAS 中轻松实现的功能:times重复一行。 %rep重复一个块也很有用。GAS.rept可以做到这一点,但如果您想改变块(例如展开和执行[rdi+0]/ [rdi+4]/ ...),NASM 更好。在 GAS 中,您可以使用递归宏,该宏使用较小的 arg 调用自身,但 NASM 允许%assign%rep.

    times 10  imul eax,eax        ; repeat this line 10 times

 %rep 10                       ; repeat this block 10 times
    add  eax, ecx
    add  ecx, eax
 %endrep

NASM 对作为数字的多字符常量具有非常好的语法,例如mov rax, 'abcdefgh'/push rax导致堆栈上按源顺序排列的 8 个 ASCII 字符。GAS 不能做任何等效的事情;你需要使用原始数字或类似的东西'h'<<56 | 'g'<<48 | ...

NASM 可以组装平面二进制文件,而无需链接器 + 链接器脚本的复杂性。大多数只与 16 位引导加载程序相关,但可能与 shellcode 相关。

直到最近,GAS 还有一些不好的东西,比如add [rdi], 1234默默地默认为 dword 操作数大小,而不是警告你它对于mov. 最近的 GAS 已经解决了这个问题;现在这是一个错误,就像在 NASM 中一样。


NASM 的语法是 100% 一致的[]- 括号存在总是意味着内存操作数,不存在意味着永远不会是内存操作数。(只是为了清楚我的意思,LEA 接受一个内存操作数,但不从中加载。)AT&T 语法也很容易区分($或不是立即数或内存之间的区别),但GAS.intel_syntax noprefix取决于符号如何被宣布add eax, foobar可能是add eax, imm32add eax, [disp32]。更糟的是,这取决于是否foobar有被宣布equ=之前或指令,除非你使用用途后OFFSET,即使你以后做foobar = 42! 将 GNU 中的内存与常量区分为 .intel_syntax.

Intel 语法是 NASM 的主要且唯一的模式,因此您可以轻松地在 Intel 或 AMD 的手册中查找说明。 .intel_syntax noprefix是 GAS 的次要功能,不像其 AT&T 那样有详细的文档记录。除了上述歧义外,它确实可以正常工作。

有时 GNU 工具即使在 Intel 语法模式下(如objdump -d -Mintel)仍然遵循 AT&T 语法错误交换的某些形式的 x87 指令,如 fdiv 与 fdivr。如果您想使用 x87,请尽可能避免使用 GAS。请参阅GAS 手册中的9.16.17 AT&T 语法错误。我认为现代 objdump 现在可能“正确”,但如果我只使用 GAS + binutils,我将不会有一些我相信不会被 GAS 必须与错误兼容的愚蠢 AT&T 实现错误破坏的东西。在 x87 指令之外完全不相关,所以幸运的是现在大部分时间都不相关。

  • That about covers it all from an overview standpoint. I'm glad you touched on NASM's macro feature. That is often overlooked but extremely handy for small tasks. Always educational answers.

以上是为什么我要使用NASM而不是GNUAssembler(GAS)?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>