Como faço para compilar montagem rotinas para uso com um programa C (GNU assembler)?
-
03-07-2019 - |
Pergunta
Eu tenho um conjunto de função de montagem que eu quero usar em programas C, criando um arquivo de cabeçalho. Por exemplo, se eu tiver asm_functions.s que define as rotinas de montagem reais e asm_functions.h que tem protótipos para as funções, bem como alguns padrão # define do que eu precisava. Meu objetivo é usar um programa C, dizem test_asm.c para chamar as funções de montagem.
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;
}
Em uma situação como esta que seria a maneira correta para compilar um link do programa? Eu estava tentando algo como isto:
gas -o asm_foo.o asm_foo.s
gcc -o test_asm test_asm.c
Mas eu ainda obter um erro de vinculador do GCC dizendo que minha rotina de montagem é indefinido. Espero que este exemplo artificial é bom o suficiente para explicar a situação.
Obrigado!
EDIT:
Aqui está um trecho de saída quando eu compilar com um único 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'
...
Todos aqueles, como PCI_FUNCTION_ID, são definidas no meu arquivo de cabeçalho, que é incluído pelo programa C. Quando eu compilar o código de montagem por si só não há erros.
Solução
Com base nos arquivos em sua pergunta, eu consegui compilá-lo. Eu mudei tanto os nomes de arquivo e o conteúdo do arquivo.
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 (o S arrastando deve ser a capital necessidades #include isso!):
#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);
}
Por favor note que você precisa dos .S extensão do arquivo de montagem com capital S. Com .s, o arquivo .s não seria executado através do pré-processador, assim #include não iria funcionar, e você não seria capaz de usar ASM_CONST_1 no arquivo .s.
Compilar com um único comando:
gcc -o test_asm asm_functions.S test_asm.c
Ou, como alternativa, de compilação com vários comandos, criando .o arquivos:
gcc -c asm_functions.S
gcc -c test_asm.c
gcc -o test_asm asm_functions.o test_asm.o
O gcc-único comando cuida da compilação do arquivo .S usando gás, o C arquivo com o compilador C do GCC, e ligando os arquivos .o temporárias resultantes em conjunto, utilizando ld. gcc executa todos os comandos com as bandeiras apropriados por padrão.
Em alguns sistemas (mas não no Linux com a instalação GCC padrão) você tem que preceder um sublinhado para os nomes das funções exportadas no arquivo .S (mas não no .c ou .h). Assim, todas as instâncias do asm_foo
se tornaria _asm_foo
somente no arquivo .S.
Outras dicas
Você considerou usando linha de montagem ? Seria muito mais fácil do que usar um arquivo assembler.
Edit: Além disso, a razão que você está recebendo erros de vinculador é provavelmente porque o compilador C adiciona um sublinhado levando em identificadores para os símbolos reais. Tente adicionar um sublinhado no seu arquivo de montagem.