从C调用汇编函数的问题

Faq*_*aqa 2 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
Run Code Online (Sandbox Code Playgroud)

汇编文件的开头:

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

和c文件的声明:

extern int do_str(char* a);
Run Code Online (Sandbox Code Playgroud)

这至少在一个Kubuntu安装上起作用,在另一个安装上失败,在MingW上失败。有人有主意吗?

wal*_*lyk 5

...声称外部功能是“未定义的引用”

大声笑!链接器不“宣称”虚假信息。您不会通过坚持自己是对还是错来说服它改变主意。毫不拖延地接受工具告诉您的事实。这是快速识别问题的关键。

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

extern _printf
...
call  _printf
Run Code Online (Sandbox Code Playgroud)

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

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

    global  _do_str

_do_str:
Run Code Online (Sandbox Code Playgroud)

另外,您可以声明该函数以使用Pascal调用约定:

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

retval = do_str ("hello world");
Run Code Online (Sandbox Code Playgroud)

Pascal调用约定与C的约定大不相同:它没有在符号前加下划线,调用者负责在返回后删除参数,并且参数的顺序不同,可能传入了一些参数数据类型寄存器而不是堆栈。有关所有详细信息,请参见编译器参考。