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