Проблемы с вызовом функции сборки из C - PullRequest
1 голос
/ 21 марта 2012

(Запуск MingW на 64-битной Windows 7 и GCC на Kubuntu)

Возможно, это проблема MingW, но она не удалась как минимум на одной установке Kubuntu, поэтому я сомневаюсь.

У меня короткая простая программа на C, которая должна вызывать функцию сборки. Я компилирую ассемблер, используя nasm и программу c, используя реализацию gcc в MingW. Эти два связаны вместе с Makefile - болото-просто. И тем не менее, связывание не выполняется для утверждения, что внешняя функция является «неопределенной ссылкой»

Соответствующая часть make-файла:

assign0: ass0.o main.o 
gcc -v -m32 -g -Wall -o assign0 ass0.o main.o 


    main.o: main.c 
         gcc -g -c -Wall -m32 -o main.o main.c 

    ass0.o: ass0.s
     nasm -g -f elf -w+all -o ass0.o ass0.s

Начало файла сборки:

section .data                       ; data section, read-write
    an:    DD 0                 ; this is a temporary var

section .text                       ; our code is always in the .text section
    global do_str               ; makes the function appear in global scope
    extern printf               

do_str:                             ; functions are defined as labels
[Just Code]

И объявление файла c:

extern int do_str(char* a);

Это сработало, по крайней мере, на одной установке Kubuntu, сбой на другой и сбой на MingW. У кого-нибудь есть идея?

Ответы [ 2 ]

4 голосов
/ 21 марта 2012

... утверждение, что внешняя функция является «неопределенной ссылкой»

LOL!Линкеры не "утверждают" ложь.Вы не будете убеждать , что он передумает, настаивая на том, что вы правы или нет.Примите то, что инструменты говорят вам, чтобы быть правдой без промедления.Это ключ к быстрой идентификации проблемы.

Почти каждый компилятор C, включая те, которые вы используете, генерирует глобальные символы с префиксом подчеркивания, чтобы минимизировать конфликты имен с символами на ассемблере.Например, измените свой код на

extern _printf
...
call  _printf

, и сообщения об ошибках о том, что printf не определен, исчезнут.Если вы do получаете неопределенную ссылку на _printf, это потому, что компоновщик не обращается к библиотеке времени выполнения C.Команда link может быть сложной, чтобы получить правильную.Обычно это не очень познавательно, так что читайте с рабочего проекта или ищите пример.Именно поэтому IDE очень полезны.

Что касается кода C, вызывающего функцию сборки, обычно проще всего написать функцию сборки с использованием соглашений C:

    global  _do_str

_do_str:

В качестве альтернативы, вы можетеможет объявить функцию для использования соглашения о вызовах Pascal:

extern int pascal do_str ( whatever parameters are needed);
...

retval = do_str ("hello world");

Соглашение о вызовах Pascal существенно отличается от C: оно не добавляет перед символом начальное подчеркивание, вызывающий отвечает за удаление параметров послеreturn, и параметры находятся в другом порядке, возможно, с некоторыми типами данных параметров, передаваемыми в регистрах, а не в стеке.См. Ссылки компилятора для всех деталей.

2 голосов
/ 21 марта 2012

C-компиляторы могут вызывать фактическую «функцию» по-разному, например, _do_str вместо do_str. Изменение имени не всегда может зависеть от системы (и, конечно, от компилятора). Попробуйте вызвать функцию asm _do_str. Использование правильных атрибутов (в gcc) также может решить проблему. Также прочитайте это .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...