Как скомпилировать ассемблерные программы для использования с программой C (ассемблер GNU)?
-
03-07-2019 - |
Вопрос
У меня есть набор функций сборки, которые я хочу использовать в программах на C, создав файл заголовка.Например, если у меня есть asm_functions.s, который определяет фактические процедуры сборки, и asm_functions.h, который содержит прототипы функций, а также некоторые стандартные #define, которые мне нужны.Моя цель — использовать программу C, например test_asm.c, для вызова функций сборки.
asm__functions.h:
#define ASM_CONST_1 0x80
#define ASM_CONST_2 0xaf
uint8_t asm_foo(интервал, интервал, интервал);
asm__functions.s:
/* dont need this: #include "asm_functions.h" */
.section .text .type asm_foo, @function asm__foo:/ * Код ASM с надлежащим манипулированием стеком для C -вызова конвенций */ ret
test__asm.c:
#include "asm_foo.h"
int main () {uint8_t res = asm_foo (1, 2, 3);вернуть 0;}
В такой ситуации, как правильно скомпилировать ссылку на программу?Я пробовал что-то вроде этого:
gas -o asm_foo.o asm_foo.s
gcc -o test_asm test_asm.c
Но я все еще получаю ошибку компоновщика от GCC, в которой говорится, что моя процедура сборки не определена.Я надеюсь, что этот надуманный пример достаточно хорош, чтобы объяснить ситуацию.
Спасибо!
РЕДАКТИРОВАТЬ:
Вот фрагмент вывода при компиляции с помощью одной команды:
tja@tja-desktop:~/RIT/SP2/latest$ gcc -o test_pci pci_config.s test_pci.c
/tmp/ccY0SmMN.o: In function _pci_bios_read_byte':
(.text+0x8): undefined reference to
PCI_FUNCTION_ID'
/tmp/ccY0SmMN.o: In function _pci_bios_read_byte':
(.text+0xa): undefined reference to
READ_CONFIG_BYTE'
/tmp/ccY0SmMN.o: In function _pci_bios_read_byte':
(.text+0x18): undefined reference to
PCI_BIOS_FUNCTION_INT'
/tmp/ccY0SmMN.o: In function _pci_bios_read_byte':
(.text+0x1b): undefined reference to
BAD_REGISTER_NUMBER'
/tmp/ccY0SmMN.o: In function _pci_bios_read_word':
(.text+0x30): undefined reference to
PCI_FUNCTION_ID'
...
Все они, например PCI_FUNCTION_ID, определены в моем заголовочном файле, который включен в программу C.Когда я компилирую ассемблерный код самостоятельно, ошибок нет.
Решение
На основе файлов в вашем вопросе мне удалось его скомпилировать.Я изменил как имена файлов, так и их содержимое.
asm_const.h:
#define ASM_CONST_1 0x80
#define ASM_CONST_2 0xaf
asm_functions.h:
#include "asm_const.h"
unsigned char asm_foo( int, int, int );
asm_functions.S (конечная S должна быть заглавной!#include это необходимо):
#include "asm_const.h"
.section .text
.globl asm_foo
.type asm_foo, @function
asm_foo:
mov $ASM_CONST_1, %eax
/* asm code with proper stack manipulation for C calling conventions */
ret
test_asm.c:
#include "asm_functions.h"
int main() {
return asm_foo( 1, 2, 3);
}
Обратите внимание, что вам нужно расширение файла сборки .S с заглавной буквы S.При использовании .s файл .s не будет проходить через препроцессор, поэтому #include не будет работать, и вы не сможете использовать ASM_CONST_1 в файле .s.
Компилируем одной командой:
gcc -o test_asm asm_functions.S test_asm.c
Или, как альтернатива, скомпилируйте несколько команд, создав файлы .o:
gcc -c asm_functions.S
gcc -c test_asm.c
gcc -o test_asm asm_functions.o test_asm.o
Команда gcc, состоящая из одной команды, обеспечивает компиляцию файла .S с помощью gas, файла .c с помощью компилятора C GCC и связывает полученные временные файлы .o вместе с помощью ld.gcc по умолчанию запускает все эти команды с соответствующими флагами.
В некоторых системах (но не в Linux с установкой GCC по умолчанию) вам необходимо добавлять подчеркивание к именам экспортируемых функций в файле .S (но не в файлах .c или .h).Таким образом, все случаи asm_foo
станет _asm_foo
только в файле .S.
Другие советы
Вы рассмотрели использование встроенной сборки?Это было бы намного проще, чем использовать файл ассемблера.
Редактировать:Кроме того, причина, по которой вы получаете ошибки компоновщика, вероятно, заключается в том, что компилятор C добавляет начальное подчеркивание к идентификаторам реальных символов.Попробуйте добавить подчеркивание в файл сборки.