如何将内存中某个地址的值复制到 gcc AT&T 样式的寄存器中

Posted

技术标签:

【中文标题】如何将内存中某个地址的值复制到 gcc AT&T 样式的寄存器中【英文标题】:How to copy the value at a certain address in memory to a register in gcc AT&T style 【发布时间】:2013-10-21 00:45:53 【问题描述】:

我想将内存中某个地址的值复制到使用 AT&T 样式程序集的寄存器中。我知道这应该不难,而且我认为在英特尔风格中它是这样的:

mov rdi, [0xdeadbeef]

但我对 AT&T 风格(或一般的装配)了解不多。我搜索了它,但我得到的所有关于mov 的例子都不包括这个。

那么谁能告诉我这个指令是什么样子的?

另外,我在哪里可以找到 AT&T 风格的 x86_64 汇编指令的完整列表?

【问题讨论】:

十六进制以零开头0,而不是o,参数之间应该有逗号 @LưuVĩnhPhúc 谢谢,我纠正了错误。 在这里索要清单是题外话,但这里是:Is there a complete x86 assembly language reference that uses AT&T syntax? AT&T 只是意味着将操作数倒序排列。汇编语言不仅仅是汇编器,读取它的工具决定了语言语法。 x86 汇编器有很多不兼容的语法,x86 vs AT&T 只是其中的一小部分。 【参考方案1】:

将内存中某个地址的值复制到寄存器在 32 位模式下我们使用

mov edi, [0xdeadbeef] ; Intel
movl 0xdeadbeef, %edi ; AT&T

在 AT&T any literal that is not prefixed by $ is an address

但是在 x86_64 64-bit absolute addressing is not allowed,所以你不能像上面那样使用movq 0xdeadbeef, %rdi。唯一具有 64 位立即数的指令是 mov(气体中的 movabs),它可以将 64 位常量分配给任何寄存器,或 move value at a 64-bit absolute address to Areg

mov rax, [0xdeadbeef]   ; Intel
movabs 0xdeadbeef, %rax ; AT&T

如果您确实需要将值从 64 位绝对地址移动到不同于 Areg 的寄存器中,您必须 use indirect addressing instead

mov rdi, 0xdeadbeef     ; Intel
mov rdi, [rdi]

movq $0xdeadbeef, %rdi  ; AT&T
movq (%rdi), %rdi

或者如果您希望将值同时复制到 rax 和 rdi 则

mov rax, [0xdeadbeef]   ; Intel
mov rdi, rax

movabs 0xdeadbeef, %rax ; AT&T
movq %rax, %rdi

这里的q 后缀表示四字(64 位)寄存器

在 AT&T 语法中,内存操作数的大小由指令助记符的最后一个字符确定。 bwlq 的助记符后缀指定字节(8 位)、字(16 位)、长(32 位)和四字(64 位)内存引用。英特尔语法通过在内存操作数(不是指令助记符)前加上 byte ptrword ptrdword ptrqword ptr 来实现这一点。因此,Intel mov al, byte ptr foo 在 AT&T 语法中是 movb foo, %al

在 64 位代码中,movabs 可用于使用 64 位位移或立即操作数对 mov 指令进行编码。

https://sourceware.org/binutils/docs/as/i386_002dVariations.html

更多关于 64 位 mov 指令的信息在这里:Difference between movq and movabsq in x86-64。如您所见,没有从 32 位绝对地址移动到 64 位寄存器的版本,因此即使在极少数情况下,当地址适合 0xdeadbeef 等 32 位时,您仍然必须使用movabs Areg, moffs64

【讨论】:

应该是mov 0xdeadbeef, %rdi吗?因为在 AT&T 中,目的地应该是第二个。那么 $0xdeadbeef 复制值而 0xdeadbeef 复制地址? 不,英特尔风格的mov [0xdeadbeef], rdi 会在 AT&T 语法中颠倒过来,就像我上面写的那样 好的,我的英特尔风格指令是错误的...根据我的要求,即“将值从内存移动到寄存器”,这应该是我评论的方式。 啊,您的英特尔风格示例是错误的。要将值从地址复制到寄存器,指令应为 mov rdi, [0xdeadbeef],在 AT&T 中为 movq 0xdeadbeef, %rdi 现在我很困惑......你能解释一下以下三个指令吗? 1.mov $5, %rdi 2.mov $0xdeadbeef, %rdi 3.mov 0xdeadbeef, %rdi.第一个是将值5移动到rdi,第二个和第三个是移动地址处的值,其中一个是移动地址0xdeadbeef ???我认为第二个移动值是因为 $ 符号...

以上是关于如何将内存中某个地址的值复制到 gcc AT&T 样式的寄存器中的主要内容,如果未能解决你的问题,请参考以下文章

内存字节对齐

内存字节对齐

js深复制

将本地向量复制到映射中某个键的值时遇到段错误

浅拷贝深拷贝

gcc 链接器 - 将存档中的所有目标文件映射到某个部分