[英]Unrecognised emulation mode: elf_i386 on MinGW32
I'm trying to make a kernel, and I cannot link the C output with the assembly. 我正在尝试创建一个内核,我无法将C输出与程序集链接起来。 The
ld
. ld
。 I'm getting the error: 我收到错误:
unrecognized emulation mode: elf_i386
无法识别的仿真模式:elf_i386
I'm using Windows 10 professional with the MinGW32 and MSYS. 我正在使用Windows 10专业版与MinGW32和MSYS。 The code I am using:
我正在使用的代码:
link.ld link.ld
/*
* link.ld
*/
OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
SECTIONS
{
. = 0x100000;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
kernel.c kernel.c
/*
* kernel.c
*/
void kmain(void)
{
const char *str = "my first kernel";
char *vidptr = (char*)0xb8000; //video mem begins here.
unsigned int i = 0;
unsigned int j = 0;
/* this loops clears the screen
* there are 25 lines each of 80 columns; each element takes 2 bytes */
while(j < 80 * 25 * 2) {
/* blank character */
vidptr[j] = ' ';
/* attribute-byte - light grey on black screen */
vidptr[j+1] = 0x07;
j = j + 2;
}
j = 0;
/* this loop writes the string to video memory */
while(str[j] != '\0') {
/* the character's ascii */
vidptr[i] = str[j];
/* attribute-byte: give character black bg and light grey fg */
vidptr[i+1] = 0x07;
++j;
i = i + 2;
}
return;
}
kernel.asm kernel.asm
;;kernel.asm
bits 32 ;nasm directive - 32 bit
section .text
global start
extern kmain ;kmain is defined in the c file
start:
cli ;block interrupts
mov esp, stack_space ;set stack pointer
call kmain
hlt ;halt the CPU
section .bss
resb 8192 ;8KB for stack
stack_space:
To Compile and link I use: 编译和链接我使用:
nasm -f elf32 kernel.asm -o kasm.o
gcc -m32 -c kernel.c -o kc.o
ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o
I'm Using: 我正在使用:
Why am I getting this error, and how can I fix it? 为什么我会收到此错误,我该如何解决?
The standard MinGW/32 LD linker doesn't output ELF binaries. 标准MinGW / 32 LD链接器不输出ELF二进制文件。 Preferably you would be using an i686 cross-compiler, but if you're not you may be able to get away with the tips below.
您最好使用i686交叉编译器,但如果不是,您可以使用下面的提示。
It appears you are using Arjun's Let's Write a Kernel tutorial. 看来你正在使用Arjun的Let's Write a Kernel教程。 If you are following that tutorial you have missed a step to make
kernel.asm
compatible with the GRUB boot loader and QEMU 's -kernel
option. 如果你正在跟踪该教程你已经错过了一步,使
kernel.asm
使用GRUB引导加载程序和QEMU的兼容-kernel
选项。 Before we start you should read the rest of the tutorial. 在开始之前,您应该阅读本教程的其余部分。 The following code adds a Multiboot header to
kernel.asm
to make it GRUB compatible: 以下代码将一个
kernel.asm
标头添加到kernel.asm
以使其与GRUB兼容:
;;kernel.asm
bits 32 ;nasm directive - 32 bit
global entry
extern _kmain ;kmain is defined in the c file
section .text
entry: jmp start
;multiboot spec
align 4
dd 0x1BADB002 ;magic
dd 0x00 ;flags
dd -(0x1BADB002 + 0x00) ;checksum. m+f+c should be zero
start:
cli ;block interrupts
mov esp, stack_space ;set stack pointer
call _kmain
hlt ;halt the CPU
section .bss
resb 8192 ;8KB for stack
stack_space:
Besides adding a header I've also put an entry
label in the file and a jmp start
to jump over the Multiboot header. 除了添加标题之外,我还在文件中放入了一个
entry
标签,并且jmp start
跳过Multiboot标头。 I've done this to make it easy to set a breakpoint at 0x100000 in the future if you start debugging. 我已经这样做了,如果你开始调试,将来很容易设置一个断点在0x100000。
One other change is that on MinGW, GCC adds an underscore to function names by default. 另一个变化是,在MinGW上, GCC默认为函数名添加下划线。 I've changed references to the C function
kmain
to _kmain
. 我已经将对C函数
kmain
引用更改为_kmain
。 This differs from the Linux convention. 这与Linux惯例不同。
Since the entry point of our code is now entry
instead of start
I've modified link.ld
to be: 由于我们的代码的入口点现在是
entry
而不是start
我已经修改了link.ld
:
/*
* link.ld
*/
OUTPUT_FORMAT(pei-i386)
ENTRY(entry)
SECTIONS
{
. = 0x100000;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
Another important change in the file above is the usage of OUTPUT_FORMAT(pei-i386)
. 上面文件中的另一个重要变化是使用
OUTPUT_FORMAT(pei-i386)
。 This will output a Portable Executable Image (32-bit) rather than an ELF (which isn't supported). 这将输出可移植可执行映像(32位)而不是ELF (不支持)。
In order to build the kernel and produce an ELF image from the PEI-I386 we can use these commands: 为了构建内核并从PEI-I386生成ELF图像,我们可以使用以下命令:
nasm -f elf32 kernel.asm -o kasm.o
gcc -m32 -c kernel.c -o kc.o -ffreestanding -nostdlib -nostdinc
ld -T link.ld -o kernel kasm.o kc.o -build-id=none
objcopy -O elf32-i386 kernel kernel.elf
The LD command has been modified to not write out the build-id to the executable to avoid the Multiboot header from being shifted outside the first 8k of the executable. 已修改LD命令,以便不将build-id写入可执行文件,以避免Multiboot标头移出可执行文件的前8k。 The GCC options have been modified to produce freestanding code (without the standard library and includes) using the options
-ffreestanding -nostdlib -nostdinc
. 已修改GCC选项以使用
-ffreestanding -nostdlib -nostdinc
选项生成独立代码(没有标准库和包含)。 We use objcopy
to convert the PEI-I386 file ( kernel
) to an ELF32 image called kernel.elf
. 我们使用
objcopy
将PEI-I386文件( kernel
)转换为名为kernel.elf
的ELF32映像。 You will want to be using kernel.elf
with GRUB and/or QEMU . 您将希望将
kernel.elf
与GRUB和/或QEMU一起使用 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.