Wie kompiliere ich Montag Routinen für die Verwendung mit einem C-Programm (GNU Assembler)?
-
03-07-2019 - |
Frage
Ich habe eine Reihe von Montagefunktion, die ich durch die Schaffung einer Header-Datei in C-Programme verwenden möchten. Zum Beispiel, wenn ich asm_functions.s haben, die definiert die eigentliche Montage Routinen und asm_functions.h die Prototypen für die Funktionen sowie einige Standard # hat definieren die ich brauchte. Mein Ziel ist es, ein C-Programm zu verwenden, sagen test_asm.c die Montage Funktionen aufzurufen.
asm__functions.h:
#define ASM_CONST_1 0x80
#define ASM_CONST_2 0xaf
uint8_t asm_foo( int, int, int );
asm__functions.s:
/* dont need this: #include "asm_functions.h" */
.section .text
.type asm_foo, @function
asm__foo:
/* asm code with proper stack manipulation for C calling conventions */
ret
test__asm.c:
#include "asm_foo.h"
int main() {
uint8_t res = asm_foo( 1, 2, 3);
return 0;
}
In einer Situation wie dieser, was der richtige Weg wäre, einen Link, um das Programm zu kompilieren? Ich war so etwas wie dies versuchen:
gas -o asm_foo.o asm_foo.s
gcc -o test_asm test_asm.c
Aber ich habe noch einen Linker-Fehler von GCC erhalten, dass meine Assembly-Routine nicht definiert ist. Ich hoffe, das erfundene Beispiel gut genug ist, um die Situation zu erklären.
Danke!
EDIT:
Hier ist ein Ausschnitt des Ausgangs, wenn ich mit einem einzigen Befehl kompilieren:
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'
...
Alle diese, wie PCI_FUNCTION_ID, sind in meiner Header-Datei definiert, die von dem C-Programm enthalten ist. Wenn ich den Assembler-Code von selbst kompilieren keine Fehler vorhanden sind.
Lösung
Basierend auf den Dateien in Ihrer Frage, schaffte ich es zu kompilieren. Ich habe sowohl die Dateinamen und die Dateiinhalte verändert.
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 (die hintere S Kapital sein muss # include braucht es!):
#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);
}
Bitte beachten Sie, dass Sie benötigen, die die Montagedateierweiterung mit einem Kapital S. Mit .s .S würde die .s-Datei nicht durch den Präprozessor ausgeführt werden, so würde # include nicht funktioniert, und Sie würden nicht sein Lage ASM_CONST_1 in der .s-Datei zu verwenden.
Übersetzen mit einem einzigen Befehl:
gcc -o test_asm asm_functions.S test_asm.c
Oder als Alternative kompilieren mit mehreren Befehlen, die Schaffung .o Dateien:
gcc -c asm_functions.S
gcc -c test_asm.c
gcc -o test_asm asm_functions.o test_asm.o
Der Single-Befehl gcc nimmt die .S-Datei Kompilieren unter Verwendung von Gas, die C-Datei mit GCC C Compiler und der Verknüpfung des resultierenden temporären .o-Dateien zusammen ld verwenden. gcc läuft all diese Befehle mit dem entsprechenden Flags in der Standardeinstellung.
Auf manchen Systemen (aber nicht auf Linux mit der Standard-GCC-Installation) Sie haben einen Unterstrich auf die Namen der exportierten Funktionen in der .S-Datei vorangestellt wird (aber nicht in der .c oder .h-Dateien). So werden alle Instanzen von asm_foo
würde _asm_foo
nur in der .S-Datei.
Andere Tipps
Haben Sie darüber nachgedacht Inline-Assembler mit? Es wäre viel einfacher, als eine Assembler-Datei.
Edit: Auch der Grund, warum Sie Linker Fehler bekommen ist wahrscheinlich, weil die C-Compiler ein führende auf Identifikatoren für die tatsächlichen Symbole Strich ergänzt. Versuchen Sie, einen Unterstrich in der Baugruppendatei.