Assembly 从64位地址加载到rax以外的寄存器

Assembly 从64位地址加载到rax以外的寄存器,assembly,x86-64,Assembly,X86 64,在x64上,可以通过以下方式从64位绝对地址(即取消对64位立即数的引用)加载 movabs addr64, %rax 但是,当目标寄存器不是rax时,汇编程序会给出一条错误消息,说明MOVAB的操作数大小不匹配。我遗漏了什么?从中可以看出,您可以将64位立即数移动到任何寄存器,但涉及64位立即数绝对地址的加载/存储只能使用Areg 操作码 指示 描述 A0 MOV AL,moffs8* 将(seg:offset)处的字节移到AL。 雷克斯W+A0 MOV AL,moffs8* 将(偏移量)处

在x64上,可以通过以下方式从64位绝对地址(即取消对64位立即数的引用)加载

movabs addr64, %rax
但是,当目标寄存器不是
rax
时,汇编程序会给出一条错误消息,说明MOVAB的
操作数大小不匹配。我遗漏了什么?

从中可以看出,您可以将64位立即数移动到任何寄存器,但涉及64位立即数绝对地址的加载/存储只能使用Areg

操作码 指示 描述 A0 MOV AL,moffs8* 将(seg:offset)处的字节移到AL。 雷克斯W+A0 MOV AL,moffs8* 将(偏移量)处的字节移动到AL。 A1 MOV AX,moffs16* 将(分段:偏移)处的字移动到AX。 A1 MOV EAX,moffs32* 将(seg:offset)处的双字移到EAX。 雷克斯W+A1 MOV RAX,moffs64* 将(偏移量)处的四字移动到RAX。 A2 MOV moffs8,AL 将AL移动到(分段:偏移)。 雷克斯W+A2 MOV moffs8***,AL 将AL移动到(偏移)。 A3 MOV moffs16*,AX 将AX移动到(分段:偏移)。 A3 MOV moffs32*,EAX 将EAX移动到(分段:偏移)。 雷克斯W+A3 MOV moffs64*,RAX 将RAX移动到(偏移)。
对于除
%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
(后者)。

Nit:上面的汇编程序指令既不是英特尔语法,也不是AT&T语法;在英特尔语法中,它是
MOV-RAX,[addr64]
,而在AT&T中,它是
movabs-addr64,%RAX
。与RE相关:我不会在Ubuntu 14.04英特尔Core i5-3210M binutils 2.25上使用。英特尔手册上说,MOV r64、imm64应该可以工作。也许从那以后发生了什么变化?@CiroSantilli六四事件法轮功 我认为
mov r64,imm64
对所有寄存器都有效,但
mov Areg,addr64
仅对一个寄存器有效。“
movabs%al,0xe4000000004049
应该在地址0xe4000000004049中存储al的值”,因此它不会将立即值移动到寄存器中或从寄存器中移动
movabs$0x10000000000000,%rax
类似于
mov-rax,0x10000000000000
但是
movabs 0x100000000000000,%rax
类似于
mov-rax[qword 0x10000000000000]
Ah,好的,取消对立即数的引用。请注意,在AT&T语法中,具有8字节内容且无ModRM(imm64和64位绝对MOFF)的两种形式都被称为
movabs
。(GAS/objdump也在英特尔语法模式下使用它)。包括
movabs 0x123456789abcdef0,%al
,这是一个独立于
a1
的操作码(
a0
),它根据操作数大小为我们提供moffs16/32/64(AX/EAX/RAX)。因此,有趣的是,
movabs 0x12345678abcdef0,%si
%dil
在“替换”//code>实现中没有精确的下降。您需要一个完整的64位寄存器来保存地址(如果RIP相对或32位绝对无法达到),但是8位或16位寄存器的
mov
只会修改寄存器状态的8位或16位,合并到完整寄存器中。可以想象这样的情况,实际上这是可取的,并且您不想
mov$imm64,%reg
/
movzbl
movsbl
将加载扩展到完整寄存器。@PeterCordes:我建议使用xchg/mov64/xchg。(第一个xchg可能是一个mov,但是带有rax的xchg有一个短编码)。@Joshua:有趣的是,这可以做到,而不需要将任何架构状态从寄存器溢出到其他任何地方。当AL/AX是特殊的时,请参考8086技术:P(但不,mov没有意义。如果RAX的旧内容不珍贵,您将
mov$imm64,%RAX
并使用
(%RAX)
.或
movabs mem,%al
/
mov%al,%dil
,即使只有低8位或16位的RAX可以被删除,它也可以工作。如果是字加载,那么可以使用66 90+reg
xchg%ax,reg
来保存一个字节,而不是3字节
mov%ax,reg
,代价是更多UOP。)