【发布时间】:2018-09-27 23:56:00
【问题描述】:
当我正在开发我的“OsDev”项目时,我正在学习新东西(对于由于 Web 开发而长期没有使用 C/C++ 编写代码的人来说,这有点“新”)。我在另一个线程中发现,从 ASM 调用 C++ 函数需要有一个 extern "C" 前缀,但现在我对标准库的衬里有问题,例如 cstdio 等。我坚持这条消息。
kc.o: In function `kmain':
kernel.cpp:(.text+0x3e4): undefined reference to `strlen`
C++
#include <string.h>
#include <cstdio>
#include "inc/screen.h"
extern "C" void kmain()
{
clearScreen();
kernel_print((char*)"Hello Github! :-)", 0x04);
}
如果我尝试使用strlen(),它将无法链接。 (顺便说一句。包括screen.h 出于某种原因正在工作)。
编译脚本
nasm -f elf32 kernel.asm -o kasm.o
g++ -c kernel.cpp -o kc.o -lgcc -m32 -Wall -Wextra -O2
ld -m elf_i386 -T link.ld -o kernel.bin kasm.o kc.o
link.ld
OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
SECTIONS
{
. = 0x100000;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
感谢您的任何建议。 :)
【问题讨论】:
-
"从 ASM 调用 C++ 函数需要有一个 extern "C" 前缀" - 不,它没有。通过确保 C 调用约定和没有 C++ 名称修饰,它确实使事情变得更容易,但是这里没有 requirement。你可以(原则上)从 asm 调用 any 函数——不管是什么语言——这可能并不容易——而且你需要知道你在做什么(根据我的经验;最大的障碍)。
-
哦,好的。我刚刚在某处读到(关于名称修饰),并将其命名为“更简单”。总之,我猜它并没有解决我的链接问题。所以.. :/
-
确保静态链接 libc。即使那样,也绝对不能保证哪些部件可以在您的玩具操作系统中运行。
strlen如果你能走到那一步,可能会。-lgcc看起来也很可疑,您的链接器脚本也是如此(例如,它似乎没有复制.rodata) -
我认为
-lgcc在您的gcc -c命令行中被忽略,因为您只是在创建.o,而不是链接。它不会创建部分链接的目标文件(因为这不是一个东西),它也不会静态地合并到静态库中的某些代码中。 将您需要的库放在您的ld命令行中。 -
@Jester:嗯,glibc
strlen可能会使用 SSE2 而无需检查。在这种情况下How do I enable SSE for my freestanding bootable code? 但也许你从静态链接 32 位 glibc 获得的版本不会。
标签: c++ assembly linker-errors osdev