从C调用汇编函数的问题

时间:2012-03-21 17:42:35

标签: c assembly

(在64位Windows 7上运行MingW,在Kubuntu上运行GCC)

这可能只是一个MingW问题,但它至少在一个Kubuntu装置上也失败了,所以我很怀疑。

我有一个简短的C程序,它应该调用汇编函数。我使用nasm和使用MingW的gcc实现的c程序编译汇编程序。这两个用makefile链接在一起 - bog-simple。然而,关于声称外部函数是“未定义的引用”的声明,链接失败了

makefile的相关部分:

assign0: ass0.o main.o 
gcc -v -m32 -g -Wall -o assign0 ass0.o main.o 


    main.o: main.c 
         gcc -g -c -Wall -m32 -o main.o main.c 

    ass0.o: ass0.s
     nasm -g -f elf -w+all -o ass0.o ass0.s

汇编文件的开头:

section .data                       ; data section, read-write
    an:    DD 0                 ; this is a temporary var

section .text                       ; our code is always in the .text section
    global do_str               ; makes the function appear in global scope
    extern printf               

do_str:                             ; functions are defined as labels
[Just Code]

和c文件的声明:

extern int do_str(char* a);

这至少在一个Kubuntu安装上有效,在另一个上失败,在MingW上失败了。有没有人有想法?

2 个答案:

答案 0 :(得分:4)

  

......声称外部函数是'未定义的引用'

LOL!林克斯并没有“声称”谎言。你不会说服它通过坚持你是正确的或错误来改变它的想法。接受工具告诉你的事实是毫不拖延的事实。这是快速识别问题的关键。

几乎每个C编译器(包括您正在使用的编译器)都会生成带有下划线前缀的全局符号,以最大限度地减少与汇编语言符号的名称冲突。例如,将代码更改为

extern _printf
...
call  _printf

并且有关printf未定义的错误消息将消失。如果你获得对_printf的未定义引用,那是因为链接器没有访问C运行时库。链接命令可能很难获得正确。通常这样做并不是非常有教育意义,因此从工作项目中获取信息,或者寻找一个例子。这是IDE非常有用的方式。

对于调用汇编函数的C代码,使用C的约定编写汇编函数通常最简单:

    global  _do_str

_do_str:

或者,您可以声明函数使用Pascal调用约定:

extern int pascal do_str ( whatever parameters are needed);
...

retval = do_str ("hello world");

Pascal调用约定与C有很大的不同:它不会在符号前面加上前导下划线,调用者负责在返回后删除参数,参数的顺序也不同,可能还有一些参数数据类型在寄存器中而不是在堆栈中传递。有关所有详细信息,请参阅编译器参考。

答案 1 :(得分:2)

C编译器可以不同地调用实际的“功能”,例如_do_str而不是do_str。名称修改不会发生总是取决于系统(当然还有编译器)。尝试调用asm函数_do_str。使用正确的attributes(在gcc中)也可以解决问题。还read this