我正在尝试制作一个简单的操作系统,但似乎无法让链接器工作。 我尝试使用命令:
ld -m elf_i386 -o kernel.bin -Ttext 0x1000 kernel-entry.o kernel.o --oformat binary
但它只是响应:
unrecognised emulation mode: elf_i386
我目前正在尝试使用 MinGW 在 Windows 上运行它 我不想使用 wsl(Linux 的 Windows 子系统),因为它也不起作用。
为了尝试运行这个,我跑了:
gcc -m32 -ffreestanding -c kernel.c -o kernel.o
nasm assembly/kernel-entry.asm -f elf -o kernel-entry.o
ld -m elf_i386 -o kernel.bin -Ttext 0x1000 kernel-entry.o kernel.o --oformat binary
nasm assembly/mbr.asm -f bin -o mbr.bin
cat mbr.bin kernel.bin > os-image.bin
qemu-system-i386 -fda os-image.bin
运行
ld --help
并查找以 supported emulations:
开头的行。
它将列出您正在使用的
ld
支持的仿真。
由于 MinGW/MinGW-w64 的目标是使用 COFF/PE 格式而不是 ELF 的 Windows,因此您的 gcc+binutils 很可能不支持您尝试定位的平台。
解决方案是获得支持您的仿真/目标平台的 gcc+binutils,可以通过自己构建它或以某种方式找到可以工作的预构建版本。
或者你可以尝试从 Linux 进行交叉编译。在我的 Debian Linux 上,我看到
ld --help
返回:
supported emulations: elf_x86_64 elf32_x86_64 elf_i386 elf_iamcu elf_l1om elf_k1om i386pep i386p
尝试运行此命令:
gcc -m32 [...] [...] ld [...]
几乎在所有情况下,您永远都不想手动调用
ld
。 请改用 gcc
。
这是因为
gcc
不是编译器。 gcc
是一个驱动程序,它调用子进程,如编译器本身(cc1
用于C,cc1plus
用于C++,lto1
用于LTO字节码),汇编器(as
)和链接器(collect2
)和 ld
)取决于命令行选项。
例如,如果该过程包括像 with 这样的链接
gcc main.c -o main.exe
gcc
最终将使用您不想手动添加的many选项和库来调用链接器。要查看 triver 正在调用的命令,请将 -v -Wl,-v
添加到 gcc
选项。更具体地说,在您的情况下,您想通过类似的方式进行链接
gcc -m32 -o kernel.elf -Ttext 0x1000 kernel-entry.o kernel.o
然后根据需要使用
objcopy
从ELF转换为其他格式。 (当时从 gcc
请求非默认输出格式存在问题,因此最好采取单独的步骤。
此外,您可能想要添加更多选项,例如
-nostdlib
、-nostartfiles
、nodefaultlibs
、设置入口点或任何您可能需要的内容。
我不熟悉您正在使用的确切工具链。您是否正在尝试进行某种交叉编译? IE。托管
gcc
的机器/操作系统与运行可执行文件的机器/操作系统不同。如果是这种情况,您需要一个合适的交叉编译器,而-m32
还不够。
问题解决了吗?我也有同样的问题...