Gcc MinGW-Win32+;nasm:“;“未定义引用”;

Gcc MinGW-Win32+;nasm:“;“未定义引用”;,gcc,assembly,mingw,nasm,undefined-reference,Gcc,Assembly,Mingw,Nasm,Undefined Reference,我目前正在开发一个用于学习的操作系统,到目前为止,它一直运行良好。然后,我试图从C代码调用一个汇编函数,该函数是用nasm,-fwin32编译的,但我得到的只是一个“未定义的引用”错误。我在pure assembler中创建了一个小示例,它也有同样的问题,但很容易理解,而且小得多: 它包括两个文件: 测试。asm: [bits 32] global _testfunc _testfunc: ret test2.asm: [bits 32] extern _testfunc globa

我目前正在开发一个用于学习的操作系统,到目前为止,它一直运行良好。然后,我试图从C代码调用一个汇编函数,该函数是用
nasm,-fwin32
编译的,但我得到的只是一个“未定义的引用”错误。我在pure assembler中创建了一个小示例,它也有同样的问题,但很容易理解,而且小得多: 它包括两个文件:

测试。asm:

[bits 32]
global _testfunc
_testfunc:
    ret

test2.asm:

[bits 32]
extern _testfunc
global _testfunc2
_testfunc2:
    call _testfunc
    ret
extern void testfunc(void);
void start()
{
    testfunc();
}
这是我的编译器/链接器脚本(使用windows批处理文件):

这将导致以下错误:

test2.o:test2.asm:(.text+0x1): undefined reference to `testfunc'
为了扩展问题,从C调用函数时也会发生同样的情况:

test.c:

[bits 32]
global _testfunc
_testfunc:
    ret

test2.asm:

[bits 32]
extern _testfunc
global _testfunc2
_testfunc2:
    call _testfunc
    ret
extern void testfunc(void);
void start()
{
    testfunc();
}
使用此链接器脚本:

gcc -ffreestanding -c test.c -o testc.o
nasm.exe -f win32 test.asm -o test.o
ld test.o testc.o -o output.tmp

在test.o、test2.o和testc.o中,它总是说
\u testfunc
,因此错误与前导下划线无关

您遗漏了一些重要内容,您的代码不在代码部分

您的asm文件应如下所示:

test.asm

global _testfunc

section .text       ; <<<< This is important!!!        
; all code goes below this!                                                  
_testfunc:

    ret
extern _testfunc
global _testfunc2

section .text       ; <<<< Again, this is important!!!                                                          
_testfunc2:
    call    _testfunc
    ret

在my MinGW设置中,在代码之前需要一个
部分
指令

; foo.asm
[bits 32]
global _testfunc
section .text
_testfunc:
    ret
然后汇编为win32格式:

nasm -fwin32 foo.asm -o foo.o
现在您可以检查
testfunc
是否存在:

$ nm foo.o
00000000 a .absolut
00000000 t .text
00000001 a @feat.00
00000000 T _testfunc
T
表示文本部分是全局的,所以我们可以开始了

注意,我避免命名任何
test
,因为这是一个shell命令。这会导致无尽的悲伤

C函数如您所示,但将文件命名为其他名称:

// main.c
extern void testfunc(void);
int main(void)
{
    testfunc();
    return 0;
}
然后,为了构建一个可执行文件,让
gcc
来完成这项繁重的工作,因为
ld
有时需要神秘的参数

gcc -ffreestanding main.c foo.o -o main

你在C语言中的问题很明显:
externvoidtestfunc(void)
不过是对编译器的一个承诺,即
testfunc
是在其他地方定义的。如果在编译过程中,无法找到您承诺的定义的
testfunc
,则会出现问题错误。
testfunc
在哪里定义?至于nasm,我怀疑同样的情况也在发生,但是我没有写足够的asm来知道。谢谢你的回答,但是testfunc不是在test.o中定义的吗?这就是全局函数所做的,不是吗?不。我看到的只是
test.c
——这里只有一个外部声明—没有存储分配给
testfunc
,也没有
定义。你有另一个C文件吗?test2.c在什么地方?我不知道你在test.asm中的定义是否足够。看,你不需要asm文件中的
[global\u testfunc]
[global\u testfunc2]
吗?如果你再次阅读asm文件,你会看到它们确实包含全局声明。