繁体   English   中英

遵循简单的内核教程时出现奇怪的链接器错误 gcc

[英]Weird linker error gcc when following simple kernel tutorial

我正在关注如何制作一个简单的可引导内核的教程:http ://www.osdever.net/tutorials/view/writing-a-simple-c-kernel

教程中有以下必需文件:

kernel.c 源代码:

#define WHITE_TXT 0x07 // white on black text

void k_clear_screen();
unsigned int k_printf(char *message, unsigned int line);


k_main() // like main in a normal C program
{
    k_clear_screen();
    k_printf("Hi!\nHow's this for a starter OS?", 0);
};

void k_clear_screen() // clear the entire text screen
{
    char *vidmem = (char *) 0xb8000;
    unsigned int i=0;
    while(i < (80*25*2))
    {
        vidmem[i]=' ';
        i++;
        vidmem[i]=WHITE_TXT;
        i++;
    };
};

unsigned int k_printf(char *message, unsigned int line) // the message and then the line #
{
    char *vidmem = (char *) 0xb8000;
    unsigned int i=0;

    i=(line*80*2);

    while(*message!=0)
    {
        if(*message=='\n') // check for a new line
        {
            line++;
            i=(line*80*2);
            *message++;
        } else {
            vidmem[i]=*message;
            *message++;
            i++;
            vidmem[i]=WHITE_TXT;
            i++;
        };
    };

    return(1);
};

kernel_start.asm 源代码:

[BITS 32]

[global start]
[extern _k_main] ; this is in the c file

start:
  call _k_main

  cli  ; stop interrupts
  hlt ; halt the CPU

link.ld 源代码:

OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS
{
  .text  0x100000 : {
    code = .; _code = .; __code = .;
    *(.text)
    . = ALIGN(4096);
  }
  .data  : {
    data = .; _data = .; __data = .;
    *(.data)
    . = ALIGN(4096);
  }
  .bss  :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
    . = ALIGN(4096);
  }
  end = .; _end = .; __end = .;
}

编译它的指令是:

nasm -f aout kernel_start.asm -o ks.o
gcc -c kernel.c -o kernel.o
ld -T link.ld -o kernel.bin ks.o kernel.o

我能够成功执行前两行:

nasm -f aout kernel_start.asm -o ks.o
gcc -c kernel.c -o kernel.o

然后当我尝试运行此行时:

ld -T link.ld -o kernel.bin ks.o kernel.o

我收到错误:

C:\basic_kernel>ld -T link.ld -o kernel.bin ks.o kernel.o
ks.o: file not recognized: File format not recognized

有谁知道这是为什么以及我如何解决这个问题? 我正在使用 Windows 7 64 位

您需要将-f aout更改为-f elf以链接生成的目标文件。

现代链接器将期待 ELF 和/或 Windows PECOFF; 您的显然无法识别过时的 a.out 目标文件格式。

当没有使用-f选项给出格式时,NASM 默认为平面二进制模式,因此完全删除它不是你想要的。

您的gccld可能需要 PECOFF 或 ELF 对象文件,而不是旧的和过时的 a.out。 尝试更换-f aoutnasm调用与-f elf一个ELF32 .o-f win32一个PECOFF .obj

(完全删除-f为您提供默认的-f bin flat 二进制文件,例如.com可执行文件或 MBR 引导扇区,而不是链接器输入。)


如果这不起作用,请尝试将此文件命名为ks.s ,使用gcc ks.s -c -o ks.o组装它,并使用它代替您拥有的ks.o / kernel_start.asm

    .text
    .code32
    .globl start
start:
    call _k_main
    cli
    hlt

警告:它没有出现在这个例子中,但是当你以这种方式编写汇编时使用的指令语法与你可能期望的非常不同。 这个 SO 问题链接到指南。 使用 GAS 的.intel_syntax noprefix指令将为您提供与 NASM 不同的语法; 它更像是 MASM。


要注意的其他问题:在程序_k_main的符号_k_main的开头应该有下划线的_k_main 在 C 中定义的所有符号开头的下划线是它在 a.out 中的工作方式,但在 ELF 中没有。 我不知道 PECOFF。

我不使用 Windows,所以我不知道这如何适用于您的问题,但是我在编译内核时曾经遇到过同样的问题(ld 给了我相同的错误代码)。 问题是我的代码是由 clang 编译的,而不是由我的工具链的 GCC 编译的,因此当我的工具链的 ld 尝试链接它时,它无法读取目标文件,因为它们不是它所期望的格式. 如果您没有使用 x86 工具链(交叉编译器),请使用一个并确保您使用该工具链中包含的 GCC 来编译您的文件。

将 kernel.asm 中的 _k_main 替换为 k_main,如下所示:

[BITS 32] 

[global start]
[extern k_main] ; include the c kernel

start:
    call k_main ; call the c kernel

    cli  ; stop interrupts
    hlt ; halt the CPU

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM