Assembly 从64位地址加载到rax以外的寄存器
在x64上,可以通过以下方式从64位绝对地址(即取消对64位立即数的引用)加载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* 将(偏移量)处
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+regxchg%ax,reg
来保存一个字节,而不是3字节mov%ax,reg
,代价是更多UOP。)