0

Situation


  1. Enviroment

    Arch Linux x86-64 (4.2.3-1-ARCH)

  2. GCC

    gcc (GCC) 5.2.0

  3. Command

    gcc -Wall -g -o asm_printf asm_printf.s 
    
  4. Error

    /usr/bin/ld: /tmp/cct4fa.o: Relocation R_X86_64_32S against '.data' can not be used when making a shared object; recompile with -fPIC
    /tmp/cct4fa.o:err adding symbols: Bad value
    collect2: error: ld returned 1 exit status
    
  5. Code

    .section .data
    msg:
        .asciz "Printf In Assembly!!\n"
    
    .section .text
    .globl main
    main:
        pushq $msg
        call printf
        addq $8 %esp
    
        pushq $0
        call exit
    

Question


I tried to use gcc to compile the program in the above Code section using the command in the above Command section and ended up with a error in the Error Section.

Note that I am not compiling a shared library.

  1. What is this error?
  2. How do i fix this?

GhitaB
  • 3,275
  • 3
  • 33
  • 62
Mr Pudin
  • 50
  • 1
  • 7

1 Answers1

2

The specific error is due to the push instruction only supporting 32 bit immediates and you tried to use that for a 64 bit address.

However, the whole code is wrong. It's unclear whether you want 32 or 64 bit code. Most of the code seems to be 32 bit, except for the pushq so I assume you really wanted 32 bit code. For that, change all those to push (which is a good idea anyway) and compile using gcc -m32. Also, you only need to remove 4 bytes from the stack, so use addl $4, %esp. (Thanks to @Employed Russian for pointing this out.)

The 64 bit calling convention is different from 32 bit, so to create a 64 bit version you must make more changes. Since I assume you really wanted 32 bit, here it is for illustration only:

.section .data
msg:
    .asciz "Printf In Assembly!!\n"

.section .text
.globl main
main:
    subq $8, %rsp
    leaq msg(%rip), %rdi
    xor %al, %al
    call printf

    xor %edi, %edi
    call exit
Jester
  • 56,577
  • 4
  • 81
  • 125
  • For 32-bit code, stack cleanup after `CALL` also needs to change from 8 to 4. – Employed Russian Nov 02 '15 at 14:14
  • Oops, indeed. Even if it makes no difference here :) – Jester Nov 02 '15 at 14:27
  • @Jester, I cannot find any book about GAS asm for x64. There are only for 32bit. And as I see from example, the 'hello world' in x64 and 32 is COMPLETELY different. (e.g. no push immediate for fd, syscall and others). So where can I find good book or resource for x64 asm? Also, I want to learn x64 for kernel syscall and the for drive development, but does actually kernel use x64 asm or 32bit in his *.S files? How will differ 32bit asm from x64 in real use? – Herdsman Jan 16 '20 at 19:30
  • 1
    64 bit kernel uses 64 bit asm. Drivers don't use asm. The calling convention and other low level stuff is defined in the [x86-64 abi pdf](https://stackoverflow.com/q/18133812/547981). system calls and arguments are described in the kernel source or [online tables](http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64). – Jester Jan 16 '20 at 19:46