Получение неопределенной ссылки на ошибку "_printf" для кода сборки несмотря на использование компоновщика gcc - PullRequest
0 голосов
/ 10 ноября 2018

Я пытаюсь следовать упражнению в книге «Сборка ПК» Пола Картера. http://pacman128.github.io/pcasm/

Я пытаюсь запустить программу с 1.4 стр. 23 в Ubuntu 18. Все файлы доступны на сайте github выше.

Поскольку исходный код для 32-битного кода, я компилирую, используя

nasm -f elf32

для first.asm и asm_io.asm для получения объектных файлов. Я также компилирую driver.c

Я использую компоновщик из gcc и запускаю

gcc -m32 -o first first.o asm_io.o driver.o 

но он продолжает выдавать мне кучу ошибок вроде

неопределенная ссылка на _scanf неопределенная ссылка на '_printf'

(обратите внимание, что вместо printf появляется _printf, потому что в файле asm_io.asm выполняется некоторое преобразование для обеспечения совместимости между Windows и ОС Linux)

Я не знаю, почему появляются эти ошибки. Я также пытаюсь запустить с использованием компоновщика напрямую

ld -m elf_i386 -e main -o first -first.o driver.o asm_io.o -I /lib/i386-linux-gnu/ld-linux.so.2 

и много вариаций, поскольку кажется, что он не связан с библиотеками Си.

Любая помощь? Застрял на некоторое время и не смог найти решение по схожим вопросам

1 Ответ

0 голосов
/ 10 ноября 2018

Linux не добавляет _ к именам при отображении из C в имена символов asm в объектных файлах ELF 1 .

То есть call printf, а не _printf, потому что в libc нет _printf.

Какой бы код "совместимости" ни делал, он делает это неправильно. Только Windows и OS X используют _printf, Linux использует printf.

Так что либо вы что-то неправильно настроили, либо определили неверную настройку, либо требуется обновление / портирование на Linux.


Сноска 1. В древней истории (как и более 20 лет назад) в Linux с форматом файла a.out использовались начальные подчеркивания в именах символов.


Обновление: библиотека использует препроцессор NASM для %define _scanf scanf и т. Д., , но требует ручного определения ELF_TYPE путем сборки с nasm -d ELF_TYPE.

Они могли самостоятельно определять выходные форматы ELF32 или ELF64, , потому что NASM предварительно определяет __OUTPUT_FORMAT__. Кто-то должен отправить pull-запрос, чтобы сделать это обнаружение автоматическим с кодом, похожим на этот:

%ifidn __OUTPUT_FORMAT__, elf32
  %define  ELF_TYPE 32
%elifidn __OUTPUT_FORMAT__, elf64
  %define  ELF_TYPE 64
%endif


%ifdef ELF_TYPE
...
%endif
...