为什么这个movq指令工作在linux上而不是osx?

以下汇编代码在OSX 10.9.4上运行时出现错误,但在Linux(Debian 7.6)上成功运行。 特别是,movq指令似乎不喜欢标签参数。

 $ cat test.S .globl _main _main: movq $_main, %rax ret 

这是错误:

 $ as -o test.o test.S test.S:3:32-bit absolute addressing is not supported for x86-64 test.S:3:cannot do signed 4 byte relocation 

将第3行中的$_main更改$_main$10这样的文字可以正常工作。

代码必须以非常小的方式进行修改,才能使其在Linux上运行 – 只需从标签中删除下划线即可。

 $ cat test.S .globl main main: movq $main, %rax ret 

独立validation代码在Linux上工作是非常容易的:

 $ as -o test.o test.S $ gcc -o test.out test.o $ ./test.out 

请忽略这些代码并没有做太多的事情,我已经尽可能有意地将其修剪掉,以certificate错误。

我已经看了很多使用LEA(加载有效的地址),但是在我做这个改变之前,我想了解它们之间的区别 – 为什么它在Linux而不是OSX上工作?

Solutions Collecting From Web of "为什么这个movq指令工作在linux上而不是osx?"

您对movq指令无法引用绝对地址是正确的。 这部分是由于OS X ABI Mach-O格式使用符号的可重定位寻址。

编译为位置无关的可执行程序( PIE )的程序通常不能以与movq $_main, %rax相同的方式引用绝对虚拟地址。 而是调用全局偏移表 ,它允许位置相对码( PC-rel )和位置无关码( PIC )在其当前绝对地址位置处提取全局符号。 如下所示, GOTPCREL(%rip)创建了lea rdi, _msg的解释:

引用它的全局偏移表的PC-rel代码:

 .globl _main _main: movq _main@GOTPCREL(%rip), %rax sub $8, %rsp mov $0, %rax movq _msg@GOTPCREL(%rip), %rdi call _printf add $8, %rsp ret .cstring _msg: .ascii "Hello, world\n" 

Mac OS X Mach-O汇编程序:

 $ as -o test.o test.asm 

苹果的GCC版本:

 $ gcc -o test.out test.o 

输出:

 $ ./test.out Hello, world