The following assembly code gives an error when running as
on OSX 10.9.4, but works successfully on Linux (Debian 7.6). In particular, the movq instruction doesn't seem to like the label argument.
$ cat test.S
.globl _main
_main:
movq $_main, %rax
ret
Here is the error:
$ 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
Changing $_main
in line 3 to a literal like $10
works fine.
The code had to be modified in a very minor way to get it to run on Linux - by simply removing the underscores from the labels.
$ cat test.S
.globl main
main:
movq $main, %rax
ret
It's pretty easy to independently verify that the code does work on Linux:
$ as -o test.o test.S
$ gcc -o test.out test.o
$ ./test.out
Please ignore that the code doesn't really do much of anything, I've intentionally trimmed it down as much as possible to demonstrate the error.
I've looked quite a bit into using LEA (load effective address), but before I make that change I'd like to understand the difference - why does it work on Linux and not OSX?
You are correct about the movq
instruction not being able to reference the absolute address. This is in part due to the OS X ABI Mach-O format which uses relocatable addressing for symbols.
A Program that is compiled as a position-independent executable (PIE
) generally cannot reference an absolute virtual address in the same manner as movq $_main, %rax
does. Instead, Global Offset Tables are called upon, which allow position relative code (PC-rel
) and position-independent code (PIC
) to extract global symbols at their current absolute address location. Demonstrated below, GOTPCREL(%rip)
creates an interpretation of lea rdi, _msg
:
PC-rel code referencing it's Global Offset Table:
.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 Assembler:
$ as -o test.o test.asm
Apple's version of GCC:
$ gcc -o test.out test.o
Output:
$ ./test.out
Hello, world
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With