我目前正在开发一个用于学习目的的操作系统,直到现在它一直运行良好。然后我尝试从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
,因此该错误与前导下划线无关!
答案 0 :(得分:3)
在我的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
答案 1 :(得分: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