与AT&T语法相比,Intel汇编语法的限制

98

对我来说,Intel语法更易于阅读。如果我只集中精力阅读Intel语法的汇编代码,我会错过什么吗?除了能够阅读其他人的AT&T汇编之外,是否有任何理由要切换到AT&T?我的第一个线索是gdb默认使用AT&T。

如果这很重要,我的重点只在于汇编和语法与Linux/BSD和C语言的关系。

7个回答

89

两者之间真的没有优劣之分。我同意 Intel 语法更易于阅读。请注意,据我所知,所有 GNU 工具都有使用 Intel 语法的选项。

看起来您可以使用以下命令使 GDB 使用 Intel 语法:

set disassembly-flavor intel

使用-masm = intel 可以让 GCC 使用 Intel 语法。


18
在执行以下命令后,~/.gdbinit文件中将添加"echo set dis intel"一行内容:as well, echo set dis intel >> ~/.gdbinit。 - oevna
9
AT&T语法相对不易读懂的原因是什么?相较于使用"dword",在操作数上加上大小后缀更为简洁。我是否忽略了其他方面的问题? - Hawken
58
lea -0x30(%rcx,%rax,8),%eax 这句话是Intel格式下的复杂汇编语句,翻译成通俗易懂的形式为 lea eax,[rcx+rax*8-0x30]。在Intel格式中使用加号和乘号可以更好地表示计算方式。 - jørgensen
9
我将他们的“卷积”视为相等但不同:如果ATT是不透明的,那么Intel就是含糊不清的。虽然中缀算术对于代数学生来说更为熟悉,但从语法上并不明显操作有确切的4个参数,或者只能乘以其中一个参数,在任何情况下都不清楚乘数必须是2的幂。 - bug
10
我发现AT&T的后缀比Intel的“ptr”更好,因为你总是需要明确指定它,这 真的 减少了错误的数量(至少对我来说是这样)。至于其余部分(例如$和%符号)... 是的,它们并不令人愉悦,但这正是它们的优点:它们是明确的,再一次减少了错误。我会说Intel的语法更适合阅读,而AT&T的语法更适合编写代码。 - MasterMastic
显示剩余14条评论

48
GNU汇编器(GAS)的主要语法是AT&T。Intel语法是相对较新的补充。Linux内核中的x86汇编语言采用AT&T语法,在Linux世界中,这是常见的语法。在MS世界中,Intel语法更为普遍。个人而言,我讨厌AT&T语法。有许多支持Intel语法的免费汇编器(NASM,YASM)以及GAS,因此在Linux中使用Intel语法不会有任何问题。除此之外,这只是一种语法上的差异。无论哪种语法,结果都将是相同的x86机器码。

27
同意并赞同。使用AT&T语法应该是一种犯罪,它不符合直觉且难看,为什么要在每个数字和寄存器前加上$和%,并以反向SIB符号指定相对寻址,我已经使用Intel语法两年了,仍然不明白为什么AT&T语法存在的必要。 - L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
13
如果你要大力宣称英特尔更好,至少提供一些证据。 - Hawken
8
讨厌霍肯的人会继续抱怨。 - Gunther Piez
8
你是在暗示他使用粗体字是因为他想以某种方式陈述自己的观点,如果他没有加粗,就不会像现在这样表达观点吗?问题本身似乎就是在邀请这种基于个人观点的“辩论”,这也可能是它已经关闭的原因! - Elliott
1
ARM 的 Intel 语法怎么样? - ceving
显示剩余2条评论

36

实际上,它们之间没有任何优劣之分。尽管个人非常讨厌Intel语法,但我不同意Intel语法更易读的说法。请记住,据我所知,所有GNU工具都可以选择使用Intel语法。

at&t noprefix                   intel
mov eax, -4(ebp,edx,4)          mov DWORD PTR[-4 +ebp +edx *4], eax
mov eax, -4(ebp)                mov DWORD PTR[-4 +ebp], eax
mov edx, (ecx)                  mov DWORD PTR[ecx], edx
lea (   ,eax,4), eax            lea eax, DWORD PTR[8 + eax*4]
lea (eax,eax,2), eax            lea eax, DWORD PTR[eax*2+eax]

更复杂的指令会让情况变得更加复杂。

话说回来。

附注:这个答案存在的主要原因是为了突出其他答案中(在我看来)的弱点,它们实际上不是答案,而是意见。当然,这个答案实际上只是我的谦虚意见。

附注2:我不讨厌英特尔语法,我只是不关心。


20
我感到非常困惑。您是在暗示at&t语法从不需要显式指定字长吗?为什么您复制了我的示例并添加了字长和无用的PTR内容?还有,为什么您将我的差异更改为负左操作数的总和?这是因为指令实际上是这样编码的吗?用户很少关心那些。在我使用过的每个汇编器中,您可以省略DWORD PTR,因为左操作数为32位,而右操作数周围有方括号。 - L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
12
此外,IDA/ollydbg 甚至不会产生类似于您所写的东西,因此,我相信从机器码到“易懂”的 Intel 语法转换没有任何问题。因此,您的示例似乎相当牵强,除了最简单的汇编器或反汇编器之外,我永远不会看到它。另一方面,我嘲笑的 AT&T 指令直接来自教授 AT&T 语法的教程的第一段落。 - L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
8
我得出结论,你是一台机器,所以你更喜欢直接反映指令比特编码的语法(也就是at&t语法)。我还怀疑人们使用at&t语法时会感到更加1337,因为它更加晦涩,尽管这并不是一个优势... - L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
8
不需要在AT&T语法中明确指定字长,如果从上下文中清楚,则与Intel相同:如果操作数的大小从上下文中清楚,就不需要使用“SOMEWORD PTR []”。 但是,在将立即数移动到内存位置时(包括来自AT&T的'l'和来自Intel的DWORD PTR),您需要它。是的,我的例子相当牵强,但你的例子也是如此。如果您仍然不明白原因,请注意在Intel中省略了不必要的字长,但在AT&T中却有它们。您选择操作数的方式使它们在Intel中对齐,但在AT&T中则没有。 - Gunther Piez
7
那么你是说-4(ebp,edx,4)这个东西比[4*edx+ebp-4]更好吗?我认为后者更易懂。 - Calmarius
显示剩余10条评论

27

它是"同一种语言",编译后会生成相同的机器码和操作码等。但另一方面,如果你在使用GCC,你可能需要学习AT&T语法,因为它是默认设置——不需要更改编译器选项等。

我也是用Intel语法x86汇编开始学习(还是在DOS上),当转到C/UNIX时发现它更直观。但是一旦你学会了AT&T,它看起来同样容易。

我不会过多考虑这个——一旦你掌握了Intel语法或AT&T语法,就很容易学习另一个。实际的难点在于掌握语言而非语法。所以请专注于其中一个,等到需要使用另一个时再去学习。


16
什么?因为GCC默认使用AT&T语法并不是学习AT&T语法的理由,特别是当你可以将它切换到更直观的英特尔语法时。 - L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
7
仅仅因为大家都说英特尔汇编语法“更直观”,就去学习它并不是一个很好的理由。实际上这根本不算理由。 - Hawken
1
你们两个都是正确的,原因和Verilog和VHDL一样。 - bug
@Hawken:没错。学习Intel语法的真正原因是因为它是Intel和AMD手册使用的语法。没有ISA参考手册使用AT&T语法像供应商手册那样详细,例如https://www.felixcloutier.com/x86/cmppd(从Intel的PDF中提取)。还有性能信息,如https://uops.info/和https://agner.org/optimize/。我想我读过一些Unix供应商在某个时候制作了一个AT&T ISA参考,但现在肯定已经过时了,而且不会涵盖AVX指令。100%同意这个答案:相同的机器代码,不同的表达语法,没什么大不了的。 - Peter Cordes

21

成为专业人士的标志之一就是你愿意适应任何正在使用的东西。没有真正的优势可以选择其中之一。Intel语法在微软世界中很常见,AT&T是Linux / Unix的标准。既然两者都没有优势,人们倾向于按照他们最先接触到的那种方式去学习。尽管如此,专业程序员不会被这些琐事所影响。使用你所在工作领域或公司所使用的语法即可。


5
作为“专业”工具使用者,掌握如何调整工具以提高生产力如何?+1 支持 Intel 语法。 - Jonathon Reinhart
5
好的,尽管我也更喜欢Intel汇编语法,但他说得有道理——例如考虑现有AT&T代码的维护。了解两种语法肯定没有坏处。 - Elliott
7
虽然我也赞成学习两种语言,但我会扮演“恶魔的辩护人”,建议你可以将vim脚本自动转换*.s文件为你选择的语法。 - bug
2
由于Intel语法更易读,因此Intel语法具有优势。 "lea eax,[eax * 4 +8]"比"leal 8(,%eax,4),%eax"具有更好的客观可读性。 - Lucio M. Tato
3
@bug 嘿,你拼错了emacs ;D - GDP2

13
Intel语法涵盖了所有内容(假设汇编器/反汇编器更新到了Intel添加到其指令集的最新垃圾)。我确定at&t也是如此。
at&t                             intel
movl -4(%ebp, %edx, 4), %eax     mov eax, [ebp-4+edx*4]
movl -4(%ebp), %eax              mov eax, [ebp-4]
movl (%ecx), %edx                mov edx, [ecx]
leal 8(,%eax,4), %eax            lea eax, [eax*4+8]
leal (%eax,%eax,2), %eax         lea eax, [eax*2+eax]
更复杂的指令将变得更加复杂。
就这样。

20
不,说得还不够。 - Gunther Piez
2
海报已经表示他们喜欢英特尔语法了,这很好;所以你想要说服谁呢? - Hawken
4
@Hawken,不仅是发布者会阅读答案。 - wingerse
我喜欢他提到了dword长度的例子。请在单字节或短字节上编写内存操作数。 - Ajay Brahmakshatriya

4

我的第一门汇编语言是MIPS,我注意到它与ATT语法非常相似。因此,我更喜欢ATT语法,但只要你能读懂,它并不重要。


3
MIPS汇编语言仅在加载/存储指令的地址格式方面类似于AT&T语法。但是MIPS只有一种简单的加载/存储寻址模式,而Intel有更多寻址模式,这使得它更加复杂。请考虑jørgensen上面发布的lea -0x30(%rcx,%rax,8),%eaxlea eax,[rcx + rax * 8-0x30]。与AT&T不同,MIPS仍然使用目标寄存器在前的格式,像其他所有汇编语言一样。此外,MIPS数字不需要以$为前缀,而MIPS中的寄存器名称很短,因此在整个过程中一直使用%并不会非常不舒适,就像AT&T一样。 - phuclv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接