NASM与GAS(实际差异)

时间:2012-12-10 00:59:00

标签: assembly x86 nasm gas

我并没有试图提示英特尔与AT& T战争(无论如何,现在他们都支持英特尔语法)或者问哪一个本身“更好”,我只是想知道实际的差异。选择其中一个。

基本上,当我几年前拿起一些基本的x86组件时,除了我正在阅读的那本书之外,我毫无理由地使用NASM - 这让我坚定但不由自主地进入了NASM阵营。从那时起,我使用汇编的原因很少,所以我没有机会尝试GAS。

请记住,它们都支持Intel语法(我个人更喜欢),理论上至少应该生成相同的二进制文件(我知道它们可能不会,但意思不应该改变),是什么赞成其中一个的理由?

是命令行选项吗?宏?非助记符关键字?或其他什么?

谢谢:)

3 个答案:

答案 0 :(得分:21)

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

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

英特尔语法非常自我解释。在上面的例子中,移动的数据量是从寄存器的大小推断的(在eax的情况下是32位)。使用的寻址模式是从操作数本身推断出来的。

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

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

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

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

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

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

  理论上,

至少应该产生相同的二进制

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

  

赞成其中一个的原因是什么?

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

  

是命令行选项吗?宏?非助记符关键字?

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

答案 1 :(得分:20)

NASM实际上使用了自己的英特尔语法变体,与英特尔官方文档中使用的MASM语法不同。操作码名称和操作数顺序与英特尔相同,因此乍一看说明看起来相同,但任何重要程序都会有差异。例如,对于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,您可以创建创建部分并自行填写数据。

答案 2 :(得分:0)

为什么不检查此post

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

涵盖范围:

  • NASM和GAS之间的基本语法差异
  • 通用的程序集级结构,例如变量,循环,标签和宏
  • 有关调用外部C例程和使用函数的一些知识
  • 汇编助记符的区别和用法
  • 内存寻址方法

一种好的做法是在两种方言中都写hello_world,并具有具体的感觉。