无法将.data中的变量移动到Mac x86汇编寄存器中

4

我使用AT&T语法编写了一小段汇编代码,并在 部分声明了三个变量。但是,当我尝试将这些变量中的任何一个移动到寄存器中(例如%eax)时,会引发来自gcc的错误。以下是代码和错误信息:

.data
  x:.int 14
  y:.int 4
  str: .string "some string\n"

.globl _main

_main:
  pushq %rbp
  movq %rsp, %rbp
  subq $16, %rsp
  movl x, %eax; #attempting to move the value of x to %eax;
  leave
  ret

出现的错误如下:

call_function.s:14:3: error: 64位模式不支持32位绝对地址寻址

movl x, %eax;

^

我还尝试在x前面添加$字符来移动值,但是会出现clang错误:

clang: 错误: 链接器命令执行失败,退出码为1 (使用 -v 查看调用)

有没有人知道如何将存储在x中的值成功地移动到%eax中?我正在Mac OSX上使用x86汇编,并使用gcc进行编译。


6
使用movl x(%rip), %eax。 (注:该指令将从程序计数器加上偏移量x处读取一个32位的值,然后将其存储到寄存器eax中)。 - Jester
@Jester 谢谢,x(%rip) 可以工作!如果您能写一篇带有解释的答案,我会接受它。 - Ajax1234
1
错误信息有点不诚实。是的,movl x, %eax被架构支持,但你不应该使用它。 - fuz
1
Intel语法重复。 - Jester
1
在AT&T语法中,movmoffs形式(使用64位绝对地址)使用movabs助记符,因此普通的mov意味着您想要带有ModR / M字节的mov r32,r / m32操作码。 MachO64输出格式根本不支持32位绝对重定位,并且图像基地址在OS X上超过2 ^ 32,因此[disp32]寻址模式无法工作。 因此,对于mov,RIP相对是唯一的选择。 - Peter Cordes
显示剩余2条评论
1个回答

7
在MacOS上,RIP相对地址模式是唯一一个用于寻址静态数据的好选项;图像基地址超过了2^32,因此即使在位置相关代码中也无法使用32位绝对地址(不像x86-64 Linux)。RIP相对地址定位静态数据是位置无关的,因此即使在位置无关可执行文件(ASLR)和库中也可以工作。

movl x(%rip),%eax是RIP相对地址的AT&T语法。

GAS .intel_syntax noprefix 中的mov eax,dword ptr [rip + x]

或者,为了将符号的地址放入寄存器中,可以使用lea x(%rip),%rdi


NASM语法:mov eax,[rel x],或使用default rel以便[x]是RIP相对的。

请参见Mach-O 64位格式不支持32位绝对地址。 NASM访问数组,以获取有关您可以在OS X上完成的操作的更多背景信息,例如movabs x,%eax是可能的,因为目标寄存器是AL/AX/EAX/RAX。(64位绝对地址,但不要这样做,因为它比RIP相对加载更大而且速度也没有更快。)

还请参见http://felixcloutier.com/x86/MOV.html


这是否意味着在GNU汇编器中,对于类似于movq x,%rdx这样的语句,即使是构建64位代码,标签x也被视为m32 - c-x-berger
@c-x-berger:不,Intel手册中的“m32”表示32位操作数大小。它并不意味着用于访问那4个字节内存的寻址模式。movq x,%rdx是一个m64内存操作数,以匹配q操作数大小和64位目标寄存器,但您告诉它不要使用RIP相对寻址,并且您没有使用movabs进行64位绝对地址(仅适用于RAX目标),因此汇编器必须在Mod / RM字节中编码地址。唯一不包括任何其他寄存器的非RIP相对模式是[sign-extended-disp32] - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接