Ошибка GCC-Assemby: перемещение R_X86_64_32S относительно '.data'

Ситуация


  1. #P6# <блочная цитата> #P1#
  2. #P7# <блочная цитата> #P2#
  3. #P8# <блочная цитата>
    gcc -Wall -g -o asm_printf asm_printf.s 
    
  4. #P9# <блочная цитата>
    /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. #P10# <цитата>
    .section .data
    msg:
        .asciz "Printf In Assembly!!\n"
    
    .section .text
    .globl main
    main:
        pushq $msg
        call printf
        addq $8 %esp
    
        pushq $0
        call exit
    

Вопрос


Я попытался использовать gcc для компиляции программы из приведенного выше раздела Код с помощью команды из приведенного выше раздела Команда и получил ошибку в разделе Ошибка Раздел.

Обратите внимание, что я не компилирую общую библиотеку.

  1. Что это за ошибка?
  2. Как это исправить?


person Mr Pudin    schedule 02.11.2015    source источник


Ответы (1)


Конкретная ошибка связана с тем, что инструкция push поддерживает только 32-битные непосредственные значения, и вы пытались использовать ее для 64-битного адреса.

Однако весь код неверен. Неясно, хотите ли вы 32-битный или 64-битный код. Большая часть кода кажется 32-битной, за исключением pushq, поэтому я предполагаю, что вы действительно хотели 32-битный код. Для этого измените все на push (что в любом случае неплохо) и скомпилируйте с использованием gcc -m32. Кроме того, вам нужно удалить только 4 байта из стека, поэтому используйте addl $4, %esp. (Спасибо @Employed Russian за указание на это.)

64-битное соглашение о вызовах отличается от 32-битного, поэтому для создания 64-битной версии необходимо внести дополнительные изменения. Поскольку я предполагаю, что вы действительно хотели 32-битную версию, здесь это только для иллюстрации:

.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
person Jester    schedule 02.11.2015
comment
Для 32-битного кода очистка стека после CALL также должна измениться с 8 на 4. - person Employed Russian; 02.11.2015
comment
Упс, действительно. Даже если здесь нет никакой разницы :) - person Jester; 02.11.2015
comment
@Jester, я не могу найти ни одной книги об ассемблере GAS для x64. Есть только для 32bit. И как я вижу из примера, 'hello world' в x64 и 32 СОВЕРШЕННО отличается. (например, нет немедленной отправки для fd, системного вызова и других). Итак, где я могу найти хорошую книгу или ресурс для x64 asm? Кроме того, я хочу изучить x64 для системного вызова ядра и для разработки дисков, но действительно ли ядро ​​​​использует x64 asm или 32-битную версию в своих файлах *.S? Чем будет отличаться 32-битный asm от x64 в реальном использовании? - person Herdsman; 16.01.2020
comment
64-битное ядро ​​использует 64-битный asm. Драйверы не используют asm. Соглашение о вызовах и другие элементы низкого уровня определены в x86-64 abi pdf. системные вызовы и аргументы описаны в исходном коде ядра или в онлайн-таблицах. - person Jester; 16.01.2020