【问题标题】:MinGW Win32 + nasm: "undefined reference"MinGW Win32 + nasm:“未定义的引用”
【发布时间】:2014-10-23 23:02:44
【问题描述】:

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

test.asm:

[bits 32]
global _testfunc
_testfunc:
    ret

test2.asm:

[bits 32]
extern _testfunc
global _testfunc2
_testfunc2:
    call _testfunc
    ret

这是我的编译器/链接器脚本(使用 Windows 批处理文件):

nasm.exe -f win32 test.asm -o test.o
nasm.exe -f win32 test2.asm -o test2.o
ld test.o test2.o -o output.tmp

这会导致错误:

test2.o:test2.asm:(.text+0x1): undefined reference to `testfunc'

为了扩展这个问题,从 C 调用函数时也会发生同样的情况:

test.c:

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中,总是说_testfunc,所以错误与前导下划线无关!

【问题讨论】:

  • 您在 C 中的问题很明显:extern void testfunc(void); 只不过是向编译器承诺testfunc 在其他地方定义。如果在编译期间,testfunc 无法按照您的承诺定义,您将收到相关错误。 testfunc 在哪里定义?至于 nasm,我怀疑同样的情况正在发生,但我没有写足够的 asm 来知道。
  • 感谢您的回答,但 testfunc 不是在 test.o 中定义的吗?这就是全局所做的,不是吗?
  • 没有。我所看到的只是test.c——而你所拥有的只是一个外部声明——没有为testfunc分配存储空间,也没有definition。你有另一个C文件吗? test2.c 某处?不知道你在 test.asm 中定义是否够用。
  • 看,你在 asm 文件中不需要 [global _testfunc][global _testfunc2] 吗?
  • 如果您再次阅读 asm 文件,您会发现它们确实包含全局声明。

标签: gcc assembly mingw nasm undefined-reference


【解决方案1】:

在我的 MinGW 设置中,您需要在代码前添加 section 指令。

; 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

【讨论】:

    【解决方案2】:

    你遗漏了一些重要的东西,你的代码不在代码部分!

    您的 asm 文件应如下所示:

    test.asm

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

    test2.asm

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

    【讨论】:

      猜你喜欢
      • 2014-02-28
      • 2020-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多