Page 1 of 3

undefined reference to _k_main

Posted: Mon Jul 19, 2010 6:31 pm
by drax
Hello developpers,

I am trying to compile the simple C kernel from this tutorial: http://www.osdever.net/tutorials/view/w ... e-c-kernel
I use these commands to compile (the exact same commands than in the tutorial):

drax@debian:~/Desktop/basic_kernel$ nasm -f aout kernel_start.asm -o ks.o
drax@debian:~/Desktop/basic_kernel$ gcc -c kernel.c -o kernel.o
drax@debian:~/Desktop/basic_kernel$ ld -T link.ld -o kernel.bin ks.o kernel.o

and at the ld step, I get these two errors:

ld: i386 architecture of input file `ks.o' is incompatible with i386:x86-64 output
ks.o: In function `start':
kernel_start.asm:(.text+0x1): undefined reference to `_k_main'

Versions:
NASM: 2.08.01
gcc: 4.3.5
ld: 2.20.1

I'm running a 64bit debian, that probably explains the first error. I guess I could solve it by outputting the assembly code to something else than aout.
But my main concern is about the "undefined reference to _k_main".
I used the search functionality and looked on Google, tried removing the first underscore but it changed nothing. I used the exact same code than the tutorial (I downloaded the ZIP file that appears in it) and executed the same compilation commands than the tutorial. What can I do to make it compile/link successfully?
Thank you.

Re: undefined reference to _k_main

Posted: Mon Jul 19, 2010 11:41 pm
by JackScott
GCC_Cross-Compiler

Doing that should fix every one those errors.

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 4:08 am
by Creature
JackScott wrote:GCC_Cross-Compiler

Doing that should fix every one those errors.
Agreed. However (at the risk of being called a newbie, which I am in fact), doesn't debian already supply an ELF compiler? From what I can see, it's trying to use x86-64, but can't you turn that off by activating emulation mode (-m32 for the compiler and something like -m elf_i386 for the linker)?

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 4:09 am
by Almamu
drax wrote:Hello developpers,

I am trying to compile the simple C kernel from this tutorial: http://www.osdever.net/tutorials/view/w ... e-c-kernel
I use these commands to compile (the exact same commands than in the tutorial):

drax@debian:~/Desktop/basic_kernel$ nasm -f aout kernel_start.asm -o ks.o
drax@debian:~/Desktop/basic_kernel$ gcc -c kernel.c -o kernel.o
drax@debian:~/Desktop/basic_kernel$ ld -T link.ld -o kernel.bin ks.o kernel.o

and at the ld step, I get these two errors:

ld: i386 architecture of input file `ks.o' is incompatible with i386:x86-64 output
ks.o: In function `start':
kernel_start.asm:(.text+0x1): undefined reference to `_k_main'

Versions:
NASM: 2.08.01
gcc: 4.3.5
ld: 2.20.1

I'm running a 64bit debian, that probably explains the first error. I guess I could solve it by outputting the assembly code to something else than aout.
But my main concern is about the "undefined reference to _k_main".
I used the search functionality and looked on Google, tried removing the first underscore but it changed nothing. I used the exact same code than the tutorial (I downloaded the ZIP file that appears in it) and executed the same compilation commands than the tutorial. What can I do to make it compile/link successfully?
Thank you.
change _k_main to k_main, it should fix the error, on GCC seems to not be needed the first underscore for calling C functions from ASM...

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 5:13 am
by Solar
Creature wrote:
JackScott wrote:...doesn't debian already supply an ELF compiler?
Yes. But building a cross-compiler anyway will give you a toolchain that doesn't need any specific command-line options to make it work. And it enables others to reproduce your exact environment (e.g. i586-elf cross-compiler vs. Debian this-or-that). And if you ever want to compile your binaries natively, you'll have to port the toolchain over anyway - at which point you'll want to get rid of any host-specific command line switches anyway, so why not start with that right away?

You'll also avoid grabbing the wrong include files by accident, screwing up your system compiler by any aliases or configs you'll do...

Many upsides to having a cross-compiler. Only two downsides to it - the CPU time to build it and the disk space to store it. Both negligible IMHO.

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 5:29 am
by -m32
Solar wrote:...so why not start with that right away?...
Because it's a huge pain in the neck when all you want to do is write code. :mrgreen:

Adding -m32 to your GCC command line and -melf_i386 to your ld command line is not that much overhead :)

A cross compiler's useful, but an unnecessary hurdle when all you're trying to do is to get a "Hello World" kernel to work.

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 5:33 am
by -m32
drax wrote: drax@debian:~/Desktop/basic_kernel$ nasm -f aout kernel_start.asm -o ks.o
drax@debian:~/Desktop/basic_kernel$ gcc -c kernel.c -o kernel.o
drax@debian:~/Desktop/basic_kernel$ ld -T link.ld -o kernel.bin ks.o kernel.o

and at the ld step, I get these two errors:

ld: i386 architecture of input file `ks.o' is incompatible with i386:x86-64 output
ks.o: In function `start':
kernel_start.asm:(.text+0x1): undefined reference to `_k_main'
Change To:
drax@debian:~/Desktop/basic_kernel$ nasm -f elf kernel_start.asm -o ks.o
drax@debian:~/Desktop/basic_kernel$ gcc -c kernel.c -o kernel.o -m32
drax@debian:~/Desktop/basic_kernel$ ld -T link.ld -o kernel.bin ks.o kernel.o -melf_i386

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 5:51 am
by JackScott
-m32 wrote:
Solar wrote:...so why not start with that right away?...
Because it's a huge pain in the neck when all you want to do is write code. :mrgreen:

Adding -m32 to your GCC command line and -melf_i386 to your ld command line is not that much overhead :)

A cross compiler's useful, but an unnecessary hurdle when all you're trying to do is to get a "Hello World" kernel to work.
Building a cross compiler requires exactly one thing: the ability to follow instructions exactly. If you can't do that, you are unlikely to get anywhere in OSDev, or indeed life.

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 6:09 am
by Solar
-m32 wrote:Because it's a huge pain in the neck when all you want to do is write code. :mrgreen:
That's an attitude that won't get you far in OS development, or any serious development work. Good software engineering is driven by a strong desire to "get it right" (as opposed to "just make it work"). It's the litmus test of the good vs. the mediocre developer.

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 4:29 pm
by gravaera
-m32 wrote:
Solar wrote:...so why not start with that right away?...
Because it's a huge pain in the neck when all you want to do is write code. :mrgreen:
I was just about to come say something sarcastic about this, but then I realized it irritated about two or three other people before I got here, so I've been beat.

--Congratulations,
gravaera

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 5:15 pm
by drax
Thank you everyone, I didn't expect to get as many answers!
Almamu wrote: change _k_main to k_main, it should fix the error, on GCC seems to not be needed the first underscore for calling C functions from ASM...
combined with:
-m32 wrote: Change To:
drax@debian:~/Desktop/basic_kernel$ nasm -f elf kernel_start.asm -o ks.o
drax@debian:~/Desktop/basic_kernel$ gcc -c kernel.c -o kernel.o -m32
drax@debian:~/Desktop/basic_kernel$ ld -T link.ld -o kernel.bin ks.o kernel.o -melf_i386
...Compiles without any error at all, but the code in kernel.c never runs. To test it here's what I've done in the code:
Print a character on the screen with INT 10, then call k_main, then print an other character with INT 10.
Result: the first character gets printed and then the system hangs.

Anyway I'll go with the cross-compiler idea since it seems to be the right thing to do!
Thanks for your help.

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 5:48 pm
by gerryg400

Code: Select all

Print a character on the screen with INT 10, then call k_main, then print an other character with INT 10.
Does INT 10 work in protected mode ?

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 6:50 pm
by drax
gerryg400 wrote:

Code: Select all

Print a character on the screen with INT 10, then call k_main, then print an other character with INT 10.
Does INT 10 work in protected mode ?
Am I wrong with that?

Code: Select all

[BITS 32]
[global start]
[extern k_main]

start:
  MOV AL, 65
  MOV AH, 0x0E
  MOV BH, 0x00
  INT 0x10
  
  call k_main

  MOV AL, 66
  MOV AH, 0x0E
  MOV BH, 0x00
  INT 0x10

  cli
  hlt

TIMES 510 - ($ - $$) db 0
DW 0xAA55
I assume that normally you would do: call k_main + cli + hlt, and everything would be done from k_main.
The k_main from the tutorial contains a k_clear_screen and a k_printf, and these don't get executed (I just see the "booting from floppy..." in QEMU and the screen isn't cleared (With the code above, I also see the letter "A")).

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 6:55 pm
by gerryg400

Code: Select all

  cli
  hlt
This code doesn't work in qemu. You need to leave interrupts enabled or the screen will not refresh. You also need to loop around the hlt just in case the cpu wakes. So ...

Code: Select all

  sti
HALT:
  hlt
  jmp HALT

Re: undefined reference to _k_main

Posted: Tue Jul 20, 2010 7:03 pm
by gerryg400
Am I wrong with that?
Yes, you cannot execute 16 bit bios code in protected mode.

How are you loading your code ? Grub ? Or another loader ?