MOV 可能是每个人在学习 ASM 时学习的第一条指令。
刚才我遇到了一本书Rajat Moona 在 GNU/Linux for IA32 Architectures 中的汇编语言编程,它说:(已删除断开的链接)
但我了解到它是MOV dest, src
。它就像“加载dest
” src
。甚至维基也这么说。
我不是说作者错了。我知道他是对的。但是我在这里错过了什么?
顺便说一句..他正在使用 GCCas
来组装这些指令。但这不应该改变指令语法吗?
MOV 可能是每个人在学习 ASM 时学习的第一条指令。
刚才我遇到了一本书Rajat Moona 在 GNU/Linux for IA32 Architectures 中的汇编语言编程,它说:(已删除断开的链接)
但我了解到它是MOV dest, src
。它就像“加载dest
” src
。甚至维基也这么说。
我不是说作者错了。我知道他是对的。但是我在这里错过了什么?
顺便说一句..他正在使用 GCCas
来组装这些指令。但这不应该改变指令语法吗?
mov dest, src
称为Intel 语法。(例如mov eax, 123
)
mov src, dest
被称为AT&T 语法。(例如mov $123, %eax
)
包括 GNU 汇编器在内的 UNIX 汇编器使用 AT&T 语法,我所知道的所有其他 x86 汇编器都使用 Intel 语法。您可以阅读wikipedia上的差异。
是的,as/gas 使用使用 src,dest 顺序的 AT&T 语法。MASM、TASM、NASM 等都使用“dest,src”的顺序。碰巧的是,AT&T 语法不太适合英特尔处理器,而且(至少在 IMO)是一个几乎无法阅读的混乱。例如movzx
特别出来坏的。
有两种不同类型的汇编语言语法 - Intel 和 AT&T 语法。您可以在Wikipedia 的汇编语言页面上找到两者的比较。
您的书很可能使用 AT&T 语法,其中源操作数位于目标之前。
正如 Jerry Coffin 在回答中已经提到的那样,英特尔语法更适合 x86 架构的指令编码。作为我的调试器反汇编程序中的注释,“操作数在指令中出现的顺序与它们在反汇编输出中出现的顺序相同”。例如,考虑以下指令:
-a
1772:0100 test word [AA55], 1234
1772:0106
-u 100 l 1
1772:0100 F70655AA3412 test word [AA55], 1234
-
正如您在操作码 hexdump 中看到的那样,指令操作码0F7h
首先是,然后是 ModR/M 字节06h
,然后是小端偏移字0AA55h
,最后是立即字1234h
。Intel 语法与汇编源代码中的顺序相匹配。testw $0x1234, (0xAA55)
在 AT&T 语法中,与编码相比,这看起来像交换顺序。
另一个遵循 Intel 语法顺序的例子是比较条件。例如,考虑这个序列:
cmp ax, 26
jae .label
这将跳转到.label
if ax
is above-or-equal-to 26(在无符号比较中)。此助记符仅适用于cmp dest, src
操作数顺序,它将标志设置为 for dest -= src
。