无法识别的仿真模式:MinGW32上的elf_i386 [英] Unrecognised emulation mode: elf_i386 on MinGW32

查看:631
本文介绍了无法识别的仿真模式:MinGW32上的elf_i386的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作内核,并且无法将 C 输出与程序集链接. ld.我遇到了错误:

I'm trying to make a kernel, and I cannot link the C output with the assembly. The ld. I'm getting the error:

无法识别的仿真模式:elf_i386

unrecognized emulation mode: elf_i386

我将Windows 10 Professional与MinGW32和MSYS结合使用.我正在使用的代码:

I'm using Windows 10 professional with the MinGW32 and MSYS. The code I am using:

link.ld

/*
*  link.ld
*/
OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
SECTIONS
 {
   . = 0x100000;
   .text : { *(.text) }
   .data : { *(.data) }
   .bss  : { *(.bss)  }
 }

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
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

我正在使用:

  • Gcc 4.8.1
  • Ld 2.25.1
  • Nasm 2.11.09rc1

为什么会出现此错误,该如何解决?

Why am I getting this error, and how can I fix it?

推荐答案

标准的MinGW/32 LD 链接器不会输出 ELF 二进制文件.最好使用i686交叉编译器,但如果不使用交叉编译器,则可以摆脱下面的提示.

The standard MinGW/32 LD linker doesn't output ELF binaries. 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.

您似乎正在使用Arjun的让我们写一个内核教程.如果您遵循该教程,则可能错过了使kernel.asm GRUB 引导加载程序和 QEMU -kernel选项兼容的步骤.在开始之前,您应该阅读本教程的其余部分.下面的代码向kernel.asm添加一个Multiboot标头,以使其与GRUB兼容:

It appears you are using Arjun's Let's Write a Kernel tutorial. 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. 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
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:

除了添加标题之外,我还在文件中放置了entry标签,并在jmp start中放置了跳过Multiboot标题的位置.我这样做是为了便于将来在开始调试时将断点设置为0x100000.

Besides adding a header I've also put an entry label in the file and a jmp start to jump over the Multiboot header. I've done this to make it easy to set a breakpoint at 0x100000 in the future if you start debugging.

另一个变化是,在MinGW上, GCC 默认情况下在函数名称上添加了下划线.我已将对 C 函数kmain的引用更改为_kmain.这与Linux约定不同.

One other change is that on MinGW, GCC adds an underscore to function names by default. I've changed references to the C function kmain to _kmain. This differs from the Linux convention.

因为我们代码的入口点现在是entry而不是start,所以我将link.ld修改为:

Since the entry point of our code is now entry instead of start I've modified link.ld to be:

/*
*  link.ld
*/
OUTPUT_FORMAT(pei-i386)    
ENTRY(entry)

SECTIONS
 {
   . = 0x100000;
   .text : { *(.text) }
   .data : { *(.data) }
   .bss  : { *(.bss)  }
 }

上面文件中的另一个重要更改是OUTPUT_FORMAT(pei-i386)的用法.这将输出可移植的可执行映像(32位),而不是 ELF (不受支持).

Another important change in the file above is the usage of OUTPUT_FORMAT(pei-i386) . This will output a Portable Executable Image (32-bit) rather than an ELF (which isn't supported).

为了构建内核并从 PEI-I386 中生成 ELF 图像,我们可以使用以下命令:

In order to build the kernel and produce an ELF image from the PEI-I386 we can use these commands:

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

LD 命令已被修改为不将build-id写出到可执行文件中,以避免Multiboot标头移到可执行文件的前8k之外. GCC 选项已经过修改,可以使用选项-ffreestanding -nostdlib -nostdinc生成独立代码(不包含标准库和包含项).我们使用objcopy PEI-I386 文件(kernel)转换为名为kernel.elf ELF32 图像.您将要在 GRUB 和/或 QEMU 中使用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. The GCC options have been modified to produce freestanding code (without the standard library and includes) using the options -ffreestanding -nostdlib -nostdinc. We use objcopy to convert the PEI-I386 file (kernel) to an ELF32 image called kernel.elf. You will want to be using kernel.elf with GRUB and/or QEMU.

这篇关于无法识别的仿真模式:MinGW32上的elf_i386的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆