如何编译用于C程序(GNU汇编程序)的程序集例程?

Mr.*_*nce 9 x86 assembly linker compilation

我有一组汇编函数,我希望通过创建头文件在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( 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; }

在这种情况下,编译链接程序的正确方法是什么?我正在尝试这样的事情:


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 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'
...

所有这些,例如PCI_FUNCTION_ID,都在我的头文件中定义,该文件包含在C程序中.当我自己编译汇编代码时,没有错误.

pts*_*pts 15

根据你问题中的文件,我设法编译它.我已经更改了文件名和文件内容.

asm_const.h:

#define ASM_CONST_1    0x80
#define ASM_CONST_2    0xaf
Run Code Online (Sandbox Code Playgroud)

asm_functions.h:

#include "asm_const.h"
unsigned char asm_foo( int, int, int );
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

test_asm.c:

#include "asm_functions.h"
int main() {
  return asm_foo( 1, 2, 3);
}
Run Code Online (Sandbox Code Playgroud)

请注意,您需要使用大写字母S的汇编文件扩展名.S..s,.s文件不会通过预处理器运行,因此#include不起作用,您将无法使用.s文件中的ASM_CONST_1.

使用单个命令编译:

gcc -o test_asm asm_functions.S test_asm.c
Run Code Online (Sandbox Code Playgroud)

或者,作为替代方案,使用多个命令进行编译,创建.o文件:

gcc -c asm_functions.S
gcc -c test_asm.c
gcc -o test_asm asm_functions.o test_asm.o
Run Code Online (Sandbox Code Playgroud)

单命令gcc负责使用gas编译.S文件,使用GCC的C编译器编译.c文件,并使用ld将生成的临时.o文件链接在一起.默认情况下,gcc使用适当的标志运行所有这些命令.

在某些系统上(但不是在安装了默认GCC的Linux上),您必须在.S文件中的导出函数名称前加下划线(但不包括.c或.h文件中).所以所有实例asm_foo_asm_foo只会出现在.S文件中.