Come posso compilare le routine di assemblaggio per l'uso con un programma C (assemblatore GNU)?

StackOverflow https://stackoverflow.com/questions/808948

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 toPCI_FUNCTION_ID'
/tmp/ccY0SmMN.o: In function _pci_bios_read_byte':
(.text+0xa): undefined reference toREAD_CONFIG_BYTE'
/tmp/ccY0SmMN.o: In function _pci_bios_read_byte':
(.text+0x18): undefined reference toPCI_BIOS_FUNCTION_INT'
/tmp/ccY0SmMN.o: In function _pci_bios_read_byte':
(.text+0x1b): undefined reference toBAD_REGISTER_NUMBER'
/tmp/ccY0SmMN.o: In function _pci_bios_read_word':
(.text+0x30): undefined reference toPCI_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.

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top