被 x86 MOV 指令迷惑

Posted

技术标签:

【中文标题】被 x86 MOV 指令迷惑【英文标题】:Puzzled by x86 MOV instruction 【发布时间】:2014-07-22 12:58:33 【问题描述】:

从 Intel64 & IA-32 manual vol 2a,指令mov 有许多可能的用法。如:

mov r64, m64      # move m64 to r64

mov rax, moffs64  # move quadword at (offset) to RAX

我写了代码来测试(gas,intel 语法):

movabs rax, label

movabs rax, offset label

...
label:
    .quad 0x112233445566

经过组装,链接和objdump,我得到了相关的组装:

mov rax, qword ptr ds:0xffff80000000008e
mov rax, 0xffff80000000008e

显然,我写的第二条指令不是预期的手册指令。手册中的格式说明是什么?

【问题讨论】:

汇编器会自动在这两个版本之间进行选择,汇编是一样的。您的movabs rax, offset label 不是两者之一,而是mov r64, imm64。如果您想查看第一个版本,即mov r64, m64,请使用rax 以外的其他寄存器,例如mov rdx, label 【参考方案1】:

moffs 表示内存操作数。以下是英特尔手册中的描述:

moffs8, moffs16, moffs32, moffs64 — 字节、字或 MOV 指令的某些变体使用的双字。实际地址由一个简单的偏移量给出 相对于段基数。指令中没有使用ModR/M 字节。以moffs 显示的数字 表示它的大小,由指令的address-size属性决定。

MASM 和 TASM 等汇编程序使用的 offset 运算符为您提供“[操作数] 相关段的偏移量” (source)。所以你用offset label 得到的是label 的偏移量,它是一个立即值。所以你在看两个不同的东西:获取存储在特定地址的值,而不是获取地址本身。

我不知道获得moffs64 变体的GAS 语法是什么,但是使用NASM 你可以写mov rax,[qword label](请注意,这种编码会比你简单写mov rax,[label] 更长 - 即mov r64, r/m64)。

【讨论】:

GAS 语法就是movabs label, %rax。这汇编为操作码48 a1,这是唯一支持moffs64mov 指令。

以上是关于被 x86 MOV 指令迷惑的主要内容,如果未能解决你的问题,请参考以下文章

x86 简单 mov 指令

Android 逆向x86 汇编 ( call 子函数调用指令 | jmp 跳转指令 | lea 加载指令 | mov 数据传送指令 )

Android 逆向x86 汇编 ( call 子函数调用指令 | jmp 跳转指令 | lea 加载指令 | mov 数据传送指令 )

GNU 汇编器 x86 指令后缀(如“mov.s”中的“.s”)如何工作?

arm指令中mov和ldr有啥区别?

X86中mov和movl指令的区别?我在阅读汇编时遇到了一些麻烦[重复]