宽度后缀
Intel将指令助记符描述为CMP(在Intel 64 and IA-32 Architectures software Developer's Manual中),但是指令的形式有很多种,比如比较8-、16、 32 位或 64 位数字,将立即数与内存中的值进行比较,等等。
一些汇编器使用后缀来区分操作数的宽度,使用:
-
b 为字节,
-
w for word(英特尔在这些架构中使用两个字节),
-
l 用于长字(四个字节),以及
-
q 用于四字(四个字,八个字节)。
如果其中一个操作数是寄存器,则汇编器可以从中计算出(至少在理论上;某些汇编器可能不具备此功能)它的宽度。
例如,cmp $0x7, %rsp 将是 64 位比较,因为 %rsp 命名为 64 位寄存器。 (%esp 是 32 位寄存器,%sp 是 16 位寄存器。)
操作数形式
cmpl $0x7, (%rsp) 表示立即值0x7 与内存中%rsp 寄存器中包含的地址的数据进行32 位比较。
没有l 后缀,这条指令的宽度是未知的。 0x7 是一个立即数。与 C 不同,它没有默认类型。
同样,(%rsp) 是内存中没有关联类型的位置。所以需要l。 (注意这里的区别:cmp $0x7, %rbp 会将 7 与 %rbp 中的值进行比较,而 cmp $0x7, (%rbp) 会将 7 与内存中地址%rbp 中的值进行比较。)
8(%rsp)是(%rsp)加8得到的地址。
更完整的形式是offset(base, index, scale),表示中的地址em>base(这是一个寄存器)加上 index(另一个寄存器)乘以 scale(常数 1、2、4 或 8)加上 偏移量。
这种形式用于索引数组:假设一个数组从地址%rax 开始并且有4 个字节宽的元素,并且您想要索引在%rbx 中的元素。然后你用(%rax, %rbx, 4) 寻址这个元素。可以添加额外的偏移量来引用数组内结构中的成员或调整数组相对于%rax的基地址。