1. 谁能向我解释为什么AT&T语法中的每个常数都在其前面都有“ $”?
  2. 为什么所有寄存器都有“%”?
  3. 这只是让我做很多la脚打字的另一次尝试吗?
  4. 另外,我是唯一找到的人: 16(%esp)[esp+16]?
  5. 我知道它会编译为同一件事,但是为什么有人想键入很多“ $”和“%” s呢? - 为什么GNU选择此语法作为默认值?
  6. 另一件事,为什么在AT&T语法中的每个指令都在:L? - 我确实知道它适用于操作数尺寸,但是为什么不让汇编器弄清楚呢? (我是否想对没有那么大小的操作数进行动态吗?)
  7. 最后一件事:为什么MOV参数反转?

不是 更多的 逻辑:

eax = 5
mov eax, 5

AT&T在哪里:

mov 5, eax
5 = a (? wait what ?)

注意:我不是要拖钓。我只是不了解他们做出的设计选择,我想知道他们为什么做自己的工作。

有帮助吗?

解决方案

1、2、3和5:符号有些多余,但是我发现在组装中发展时这是一件好事。冗余有助于阅读。关于“让汇编器弄清楚”的观点很容易变成“让读取代码弄清楚的程序员”,而当我参加阅读的人时,我不喜欢它。编程不是仅写作任务;甚至程序员本人也必须阅读自己的代码,语法冗余有很大帮助。

另一点是“%”和“ $”意味着可以添加新寄存器而不会破坏向后兼容性:添加时没有问题,例如,寄存器,称为 xmm4, ,将其写出为 %xmm4, ,它不能与称为的变量混淆 xmm4 这将在没有“%”的情况下写。

至于打字量:通常,在组装中编程时,瓶颈是大脑,而不是手。如果“ $”和“%”放慢了您的速度,那么您要么要比通常认为对人类可行的速度更快,或者更可能是,您的任务太机械化了,不应完成部件;它应该留给自动代码生成器,这是俗称“ C编译器”的东西。

添加“ L”后缀来处理汇编器“无法”弄清楚的某些情况。例如,此代码:

mov  [esp], 10

是模棱两可的,因为它不知道您是否要编写一个值10的字节,还是具有相同数值的32位单词。然后,英特尔语法要求:

mov  byte ptr [esp], 10

当您考虑它时,这很丑陋。 AT&T的人们希望使事情变得更加理性,因此他们想到了:

movb   $10, (%esp)

他们更喜欢系统性,并具有“ b”(或'l'或'w')后缀 到处. 。请注意,后缀并不总是 必需的. 。例如,您可以写:

mov   %al, (%ebx)

并让GNU汇编器“弄清楚”,因为您在谈论'%al',此举是针对一个字节。真的行 !但是,我仍然发现指定大小更好(这确实可以帮助读者,而程序员本人是他自己的代码的第一个也是最重要的读者)。

对于“倒置”:这是相反的。英特尔语法模拟C中发生的情况,其中右侧计算值,然后写入左侧的值。因此,考虑到阅读从左到右,写作向左向左向左走。 AT&T语法恢复为“正常”方向。至少他们认为;由于他们还是决定使用自己的语法,因此他们认为他们可以将操作数用于他们认为的“正确订购”。这主要是一种惯例,但不是不合逻辑的。 C惯例模仿数学符号,除了数学是关于数学符号的 定义 值(“让x为值5”),而不是关于 分配 值(“我们编写值5 进入 一个称为“ X'”的插槽。AT&T选择是有道理的。只有在将C代码转换为汇编时,它才会感到困惑,该任务通常应保留给C编译器。

从历史的角度来看,问题5的最后一部分很有趣。 X86的GNU工具遵循AT&T语法,因为当时,他们试图在Unix World中占据(“ GNU”的意思是“ GNU不是Unix”)并与Unix工具竞争; Unix由AT&T控制。这是在Linux甚至Windows 3.0的日子之前; PC是16位系统。 UNIX使用了AT&T语法,因此GNU使用了AT&T语法。

那么一个好问题是:为什么AT&T发现发明自己的语法很明智?如上所述,他们有一些原因,这些原因并非没有根据。当然,使用自己的语法的成本是它限制了互操作性。在那些日子里,C编译器或汇编器作为单独的工具没有真正的意义:在UNIX系统中,它们的目的是由OS供应商提供。另外,英特尔不是Unix World的大球员。大系统主要使用VAX或Motorola 680x0衍生物。没有人发现MS-DOS PC会在二十年后变成桌面和服务器世界中的主要体系结构。

其他提示

1-2,5:他们可能选择前缀寄存器,以使其更容易解析;您直接知道第一个字符是什么样的令牌。

4:不

6:同样,可能使解析器更容易弄清楚输出的指令。

7:实际上,这在语法含义中更有意义,移动 什么在哪里. 。也许是 移动 指示应该是 ld 操作说明。

不要误会我的意思,我认为AT&T语法是可怕的。

GNU汇编器的AT&T语法将其起源跟踪到Unix汇编器 1, ,它本身主要从PDP-11 PAL-11组装程序中获取其输入语法(约1970年)。

谁能向我解释为什么AT&T语法中的每个常数都在其前面都有“ $”?

它允许将直接常数与内存地址区分开。英特尔语法以相反的方式做到这一点,内存引用为 [foo].

顺便说一句,MASM(Microsoft Assembler)不需要在语法级别上有区别,因为它可以判断操作数是符号常数还是标签。其他用于X86的组装者会积极避免这种猜测,因为它们可能会使读者混淆,例如:理想模式下的tasm(它警告了内存引用,而不是在括号中),nasm,fasm。

PAL-11使用 # 为了 即时 地址模式,操作数遵循说明。没有常数 # 意思是 相对的 地址模式,相对地址遵循指令。

Unix使用的语法与DEC组装程序相同的语法,并使用 * 代替 @, , 和 $ 代替 #, , 自从 @# 显然不方便的类型 2.

为什么所有寄存器都有“%”?

在PAL-11中,寄存器定义为R0 =%0,R1 =%1,... R6也称为SP,R7也称为PC。 DEC Macro-11宏组件允许将寄存器称为 %x, , 在哪里 x 可能是任意表达,例如 %3+1 提到 %4.

这只是让我做很多la脚打字的另一次尝试吗?

没有。

另外,我是唯一发现的人:与[ESP+16]相比,16(%ESP)真正违反直觉?

这来自PDP-11 指数 地址模式,其中通过按照指令求和一个寄存器的内容和索引单词来形成内存地址。

我知道它会编译为同一件事,但是为什么有人想键入很多“ $”和“%” s呢? - 为什么GNU选择此语法作为默认值?

它来自PDP-11。

另一件事,为什么在AT&T语法中的每个指令都在:L? - 我确实知道它适用于操作数尺寸,但是为什么不让汇编器弄清楚呢? (我是否想对没有那么大小的操作数进行动态吗?)

气体通常可以弄清楚。在特定情况下,其他汇编者也需要帮助。

PDP-11将使用 b 对于字节说明,例如: CLR vs CLRB. 。其他后缀出现在VAX-11中: l 长时间 w 言语, f 对于浮动, d 双重 q 对于四边形,...

Last thing: why are the mov arguments inverted?

可以说,由于PDP-11早于Intel微处理器,因此相反。


  1. 根据气体信息页面,通过BSD 4.2汇编器。
  2. UNIX汇编器参考手册§8.1 -Dennis M. Ritchie

AT&T语法与英特尔相比的AT&T语法倒置顺序很可能是因为UNIX最初开发的PDP-11使用相同的操作数顺序。

英特尔和DEC只是选择了相反的命令。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top