在 x64 上,从 64 位绝对地址加载(即,取消引用 64 位立即数)可以通过
movabs addr64, %rax
但是,当目标寄存器不是rax
汇编器时,会给出一条错误消息,说operand size mismatch for movabs
. 我错过了什么?
从MOV 指令文档中,您可以看到您可以将 64 位立即数移动到任何寄存器,但涉及 64 位立即数绝对地址的加载/存储只能使用 Areg
操作码 | 操作说明 | 描述 |
---|---|---|
A0 | MOV AL, moffs8 * | 将 ( seg:offset )处的字节移动到 AL。 |
雷克斯.W + A0 | MOV AL, moffs8 * | 将(偏移)处的字节移动到 AL。 |
A1 | MOV AX,moffs16 * | 将 ( seg:offset )处的单词移动到 AX。 |
A1 | MOV EAX,moffs32 * | 将 ( seg:offset ) 处的双字移动到 EAX。 |
雷克斯.W + A1 | MOV RAX,moffs64 * | 将 ( offset )处的四字移动到 RAX。 |
A2 | MOV moffs8 ,AL | 将 AL 移动到 ( seg:offset )。 |
雷克斯.W + A2 | MOV moffs8 ***,AL | 将 AL 移动到(偏移)。 |
A3 | MOV moffs16 *,AX | 将 AX 移动到 ( seg:offset )。 |
A3 | MOV moffs32 *,EAX | 将 EAX 移动到 ( seg:offset )。 |
雷克斯.W + A3 | MOV moffs64 *,RAX | 将 RAX 移动到(偏移)。 |
如您所见,没有 ModR/M 字节来编码寄存器编号。由于这比将 64 位立即数移动到寄存器更不常用,因此不会有问题。如果真的需要,可以在 2 条指令中完成
MOVABS
是操作MOV
码形式的 GAS 操作码名称,MOV Areg, [Offs64]
并且MOV [Offs64], Areg
. 在 Yasm 的 NASM 语法模式下,你可以通过MOV AX, [qword xxx]
. Yasm 的 GAS 语法模式接受MOVABS
(为了 GAS 兼容性)。请注意,此表格仅对 Areg (AL/AX/EAX/RAX) 作为源/目标寄存器有效。http://cvs.tortall.net/pipermail/yasm-devel/2006-March/000579.html
对于除一个以外的任何寄存器%rax
都可以用两条指令替换它:
48 bb f0 de bc 9a 78 56 34 12 mov $0x123456789abcdef0,%rbx
48 8b 1b mov (%rbx),%rbx
这个比一个长,
48 a1 f0 de bc 9a 78 56 34 12 mov 0x123456789abcdef0,%rax
因此,如果您可以使用它,您很可能更喜欢movabs
(后者)。