Come posso compilare le routine di assemblaggio per l'uso con un programma C (assemblatore GNU)?
-
03-07-2019 - |
Domanda
Ho una serie di funzioni di assemblaggio che voglio usare nei programmi C creando un file header. Ad esempio, se ho asm_functions.s che definisce le routine di assemblaggio effettive e asm_functions.h che dispone di prototipi per le funzioni e di alcuni # define standard di cui avevo bisogno. Il mio obiettivo è utilizzare un programma C, ad esempio test_asm.c per chiamare le funzioni di assemblaggio.
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 una situazione come questa, quale sarebbe il modo corretto di compilare un collegamento al programma? Stavo provando qualcosa del genere:
gas -o asm_foo.o asm_foo.s
gcc -o test_asm test_asm.c
Ma ricevo ancora un errore del linker da GCC che dice che la mia routine di assemblaggio non è definita. Spero che questo esempio inventato sia abbastanza buono da spiegare la situazione.
Grazie!
EDIT:
Ecco uno snippet di output quando compilo con un singolo comando:
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'
...
Tutti questi, come PCI_FUNCTION_ID, sono definiti nel mio file di intestazione, che è incluso nel programma C. Quando compilo il codice assembly da solo non ci sono errori.
Soluzione
Sulla base dei file nella tua domanda, sono riuscito a compilarlo. Ho modificato sia i nomi dei file che i relativi contenuti.
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 (la S finale deve essere maiuscola! #include ne ha bisogno):
#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);
}
Si noti che è necessaria l'estensione del file assembly .S con maiuscole S. Con .s, il file .s non verrebbe eseguito tramite il preprocessore, quindi #include non funzionerebbe e non si sarebbe in grado di utilizzare ASM_CONST_1 nel file .s.
Compila con un singolo comando:
gcc -o test_asm asm_functions.S test_asm.c
Oppure, in alternativa, compilare con più comandi, creando file .o:
gcc -c asm_functions.S
gcc -c test_asm.c
gcc -o test_asm asm_functions.o test_asm.o
Il comando singolo gcc si occupa di compilare il file .S usando gas, il file .c con il compilatore C di GCC e di collegare insieme i file .o temporanei risultanti usando ld. gcc esegue tutti questi comandi con i flag appropriati per impostazione predefinita.
Su alcuni sistemi (ma non su Linux con l'installazione GCC predefinita) devi anteporre un carattere di sottolineatura ai nomi delle funzioni esportate nel file .S (ma non nei file .c o .h). Quindi tutte le istanze di asm_foo
diventerebbero _asm_foo
solo nel file .S.
Altri suggerimenti
Hai considerato utilizzando l'assemblaggio in linea ? Sarebbe molto più semplice che usare un file assembler.
Modifica: inoltre, il motivo per cui si verificano errori del linker è probabilmente perché il compilatore C aggiunge un carattere di sottolineatura iniziale sugli identificatori per i simboli effettivi. Prova ad aggiungere un carattere di sottolineatura nel file di assieme.