很长一段时间我都没有使用 C 和汇编程序进行编程(大约 2 年)。现在我决定重新开始,但我想做一些更复杂的事情。我考虑过创建一个简单的内核。现在我在互联网上找到了这个源代码:
启动.asm:
global loader
extern kernel_main
MAGIC equ 0xbad
FLAGS equ 0x3
CHECKSUM equ -(MAGIC+FLAGS)
section .text
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
loader:
call kernel_main
cli
quit:
hlt
jmp quit
内核.c:
void print(char *text) {
char *memory = (char*)0xb8000;
while(*text) {
*memory++ = *text++;
*memory++ = 0x3;
}
}
void kernel_main() {
print("My cat sometimes smells like cafe. I love it.");
}
链接器.ld:
ENTRY(loader)
SECTIONS {
. = 0x100000;
.text : { *(.text) }
}
注意:我用“GCC”编译了 C 文件,用“NASM”编译了汇编文件。
如果我尝试这个命令:
ld -T linker.ld -elf_i386 -o final.bin boot.o kernel.o
它说:“boot.asm:(.text+0xd): undefined reference to `kernel_main'”。 我怎样才能解决这个问题? 我在 Windows 上工作,不想在 Linux 或任何东西上运行 VM。提前致谢!
编辑: 这是我的 GCC 命令:
gcc -m32 -o kernel.o srckernel.c -nostdlib -nostartfiles -nodefaultlibs
这是我的 NASM 命令:
nasm -f elf32 -o boot.o boot.asm
最佳答案
有很多错误。我会假设错误:
boot.asm:(.text+0xd): undefined reference to
kernel_main
您没有使用 ELF 交叉编译器,而是使用生成 native Windows 可执行文件的 GCC 编译器(即 Cygwin 和 MinGW)。我强烈推荐使用 i686(或 x86_64)ELF cross compiler用于操作系统开发,尤其是在 Windows 上。
您的主要问题是:
选项
-elf_i386
可能意味着-melf_i386
但这甚至是不正确的。对于面向 Windows 的 GCC,您将希望使用-mi386pe
输出为 Win32 PE/COFF 格式。 Windows GCC 链接器通常不知道如何生成 ELF 可执行文件。我还建议在使用 LD 输出 i386pe 格式时使用-N
选项。将您的链接器命令更改为:ld -N -T linker.ld -mi386pe -o final.bin boot.o kernel.o
对于 Win32 PE/COFF 对象1:使用 CDECL 调用约定的函数必须具有 underscore (
_
) prepended给他们。kernel_main
需要是_kernel_main
。您需要更改boot.asm
中的这些行:extern kernel_main call kernel_main
到:
extern _kernel_main call _kernel_main
您没有说明如何编译
kernel.c
以及如何组装boot.asm
但它们应该类似于:nasm -f win32 boot.asm -o boot.o gcc -g -c -m32 -ffreestanding kernel.c -o kernel.o
当您设法生成
final.bin
时,它是一个 Windows PE 可执行文件。 Multiboot specification需要 ELF 可执行文件。使用 LD 链接到final.bin
后,您可以将final.bin
转换为 ELF 格式:objcopy -O elf32-i386 final.bin final.elf
final.elf
现在应该可以用作 Multiboot ELF 可执行文件。boot.asm
中的 Multiboot header 存在问题。 Multiboot 魔法值为0x1badb002
而不是0xbad
。由于您未在 Multiboot header 中指定视频配置FLAGS
不应设置位 1,因此FLAGS
应为 0x1 而不是 0x3。从以下位置更改您的 Multiboot header :MAGIC equ 0xbad FLAGS equ 0x3
到:
MAGIC equ 0x1badb002 FLAGS equ 0x1
通过上述更改,我能够生成一个名为 final.elf
的 ELF 可执行文件。使用以下命令与 QEMU 一起运行时:
qemu-system-i386 -kernel final.elf
我得到的输出是:
脚注:
- 1生成 Win64 PE32+ 对象时,函数名称上的额外下划线不适用。
关于gcc - 是什么导致 "x.asm:(.text+0xd): undefined reference to ` y'”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57274231/