I'm trying to make a program with NASM and GCC:
global main
extern puts
section .data
hi db 'hello', 0
section .text
main:
push hi
call puts
ret
I am building with:
nasm -f elf64 main.asm
gcc main.o -o main
rm main.o
I get:
/usr/bin/ld: main.o: relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
I have a feeling I'm doing a few things wrong, judging by the presence of weird stack operations in examples like this and this. I can't find any documentation that actually explains this, for some reason, though (In fact, I can hardly find any useful documentation for 64-bit development with NASM in general, which has made everything I've made so far a real pain in the ass to make), and adding in things like that don't have any effect on my error output.
Update:
I've been looking at this and this.
If I change my main to:
push rbp
mov rax,0
mov rdi, hi
call [puts wrt ..got]
pop rbp
mov rax,0
ret
It compiles fine, but then gives me a segfault when running instead of actually printing. I also don't understand why I'm pushing and pulling the value of rbp from the stack, and why rax's value matters in this case.
rbp is a callee-saved register hence you need to preserve it. You are not changing it so you don't have to push/pop it here. However you need to preserve 16 byte stack alignment, and a push is a simple way to do that. You could have used any other register, or even sub rsp, 8.
mov rdi, hi should be lea rdi, [rel hi].
Functions are called through the PLT not the GOT, and not through a pointer. Just do call puts ..wrt plt.
As such, the following should work:
global main
extern puts
section .data
hi db 'hello', 0
section .text
main:
push rbp
lea rdi, [rel hi]
call puts wrt ..plt
pop rbp
ret
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