繁体   English   中英

为什么这个movq指令适用于linux而不是osx?

[英]Why does this movq instruction work on linux and not osx?

运行时,下面的汇编代码提供了一个错误as对OSX 10.9.4,但成功在Linux(Debian的7.6)。 特别是,movq指令似乎不喜欢label参数。

$ 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

很容易独立验证代码在Linux上是否可行:

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

请忽略代码并没有真正做很多事情,我故意尽可能地将其修剪下来以证明错误。

我已经看了很多使用LEA(加载有效地址),但在我做出改变之前,我想了解其中的区别 - 为什么它适用于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

Apple的GCC版本:

$ gcc -o test.out test.o

输出:

$ ./test.out
Hello, world

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM