在 AT&T 语法指令中,通常必须以适当的操作数大小为后缀,以及q
对 64 位操作数的操作。然而,在 MMX 和 SSE 中也有movq
指令,q
在原始 Intel 助记符中,而不是附加后缀。
那么这将如何在 AT&T 中体现出来呢?是否需要另一个q
后缀,例如
movqq %mm1, %mm0
movqq %xmm1, %xmm0
或不?
如果有任何其他指令以 AT&T 后缀(如paddd
, slld
)结尾,它们的工作方式是否相同?
AT&T 语法基本上不会对助记符+后缀与其他助记符之间的冲突做任何事情。 寄存器操作数总是在mov
带有q
操作数大小后缀的助记符与movq
助记符之间消除歧义
movq %xmm0, %xmm0
、movq %rax, %xmm0
和movq %xmm0, %rax
是 3 个不同的操作码,它们都使用相同的助记符(movq
在 Intel 和 AT&T 语法中)。
movq
助记符上不允许有后缀: Error: invalid instruction suffix for 'movq'
. 这是正常的,因为对于操作数大小没有可能的歧义。 movq
总是移动 64 位,所以q
后缀是多余的。
这会使解析 AT&T 比解析 Intel 语法更难吗?在 MMX 甚至存在之前(因此也在 x86-64 之前), movl
仍然是6 种不同操作码的助记符(英特尔的 insn set ref 手动条目mov
列出了所有这些操作码,以及它们的数字操作码):
MOV r/m32,r32
MOV r32,r/m32
(如果两个操作数都是 reg,汇编器可以选择其中一个操作码)MOV r32, imm32
(简写)MOV r/m32, imm32
(带有 modr/m,可用于内存操作数)。MOV moffs32,EAX
和MOV EAX,moffs32
,作为使用 32 位绝对地址存储/加载的优化(无 ModR/M)。这还不包括 mov 到/从段、控制和调试寄存器。就像 with 一样movq %xmm0, %rax
,AT&T 的语法总是不得不处理mov %ds, %ax
.
添加更多具有不同寄存器的表单来消除歧义可能并不难解析。
除此之外,当寄存器确定操作数大小时,操作数大小后缀是可选的。 mov %rax, %rcx
是合法的,并且仅在将立即数移至内存时才需要后缀。 mov $1, (%rsi)
是非法的,因为这两个操作数都没有暗示操作数大小,并且没有后缀可以使其明确。
movq
与 MMX 一起引入以促进 MMX 寄存器和非 MMX 寄存器之间的四字移动。这是一个通用操作码;您可以在 mmx 寄存器和任何其他寄存器(mmx 或非 mmx)之间移动四字,甚至在非 mmx 寄存器之间移动。
换句话说,没有两个不同的操作码。因此,语法总是movq
.