简体   繁体   中英

Weird linker error gcc when following simple kernel tutorial

Im following this tutorial on how to make a simple bootable kernel:http://www.osdever.net/tutorials/view/writing-a-simple-c-kernel

there are the following required files in the tutorial:

kernel.c source code:

#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 source code:

[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 source code:

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 = .;
}

The instructions to compile it are:

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

i am able to successfully execute the first two lines:

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

then when i try and run this line :

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

I get the error:

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

Does anyone know why this is and how I could fix this? I'm using windows 7 64 bit

You need to change -f aout to -f elf in order to link the produced object file.

Modern linkers will be expecting ELF and/or Windows PECOFF; yours clearly doesn't recognize the obsolete a.out object-file format.

NASM defaults to flat binary mode when not given a format with the -f option, so removing it entirely isn't what you want.

Your gcc and ld are probably expecting PECOFF or ELF object files, rather than a.out, which is old and obsolete. Try replacing the -f aout from your nasm invocation with -f elf for an ELF32 .o or -f win32 for a PECOFF .obj

(Removing -f entirely gives you the default -f bin flat binary, like for a .com executable or MBR bootsector, not a linker input.)


If that doesn't work, try naming this file ks.s , assembling it with gcc ks.s -c -o ks.o , and using it instead of the ks.o / kernel_start.asm you have:

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

Warning: It doesn't show up in this example, but the instruction syntax used when you write assembly this way is very different from what you might be expecting. This SO question links to a guide. Using GAS's .intel_syntax noprefix directive will give you different syntax than NASM; it's more like MASM.


Additional wrinkle to be aware of: there are excellent odds that you should not have an underscore at the beginning of the symbol _k_main in the assembly. Underscores at the beginning of all symbols defined in C is how it worked in a.out, but is not done in ELF. I don't know about PECOFF.

I don't use windows so I do not know how this would apply to your problem, but I once had the same issue while compiling my kernel (ld gave me the same error code). The problem was that my code was being compiled by clang instead of being compiled by my toolchain's GCC, so therefore when my toolchain's ld tried to link it, it couldn't read the object files because they weren't in the format it was expecting. If you are not using an x86 toolchain (cross-compiler) use one and make sure you are using the GCC included in that toolchain to compile your files.

Replace _k_main by k_main in kernel.asm like this:

[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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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