Странная ошибка компоновщика gcc при следовании простому учебнику ядра - PullRequest
0 голосов
/ 21 марта 2012

Я следую этому уроку о том, как сделать простое загрузочное ядро: 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 бит

Ответы [ 4 ]

4 голосов
/ 23 марта 2012

Вам необходимо изменить -f aout на -f elf, чтобы связать созданный объектный файл.

Современные компоновщики будут ожидать ELF и / или Windows PECOFF;Ваш явно не распознает устаревший формат объектного файла a.out.

По умолчанию NASM использует режим бинарного бинарного режима, если не указан формат с опцией -f, поэтому полное его удаление не то, что вам нужно.

1 голос
/ 21 марта 2012

Ваши gcc и ld, вероятно, ожидают объектные файлы PECOFF или ELF, а не a.out, который является старым и устаревшим.Попробуйте заменить -f aout из вашего nasm вызова на -f elf для ELF32 .o или -f win32 для PECOFF .obj

(удаление -f полностью дает значение по умолчанию -f bin бинарный файл, как для .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

Предупреждение: в этом примере это не отображается, но Синтаксис инструкции , используемый при написании ассемблера, очень отличается от того, что вы могли ожидать. Этот ТАК вопрос ссылается на руководство.Использование директивы GAS .intel_syntax noprefix даст вам синтаксис, отличный от NASM;это больше похоже на MASM.


Дополнительная складка, о которой следует знать: есть отличные шансы, что у не должно быть подчеркивание в начале символа _k_main в сборке,В начале всех символов, определенных в C, подчеркивается то, как это работает в a.out, но не выполняется в ELF.Я не знаю о PECOFF.

0 голосов
/ 09 апреля 2019

Замените _k_main на k_main в kernel.asm следующим образом:

[BITS 32] ; inform the processor of 32 bits mode program

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

start:
    call k_main ; call the c kernel

    cli  ; stop interrupts
    hlt ; halt the CPU
0 голосов
/ 17 июня 2017

Я не использую windows, поэтому я не знаю, как это отразится на вашей проблеме, но однажды у меня возникла та же проблема при компиляции моего ядра (ld дал мне тот же код ошибки).Проблема заключалась в том, что мой код компилировался с помощью clang вместо того, чтобы компилироваться с помощью GCC моей инструментальной цепочки, поэтому, когда ld моей инструментальной цепочки пытался связать его, он не мог прочитать объектные файлы, потому что они были не в том формате, который ожидался,Если вы не используете цепочку инструментов x86 (кросс-компилятор), используйте ее и убедитесь, что вы используете GCC, включенный в эту цепочку инструментов, для компиляции ваших файлов.

...