[Newbie] Switching from assembly to C after boot

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
gerenjo
Posts: 10
Joined: Tue Feb 03, 2009 12:16 pm

[Newbie] Switching from assembly to C after boot

Post by gerenjo »

Hi everyone,

I began my own OS a couple of weeks ago. I spent 1 full week learning assembly language and writing my bootloader.
That wasn't that hard for me though, since I know C quite well.
However, i encounter difficulties when I try to use C code. How exactly can I jump from an assembly routine (my stage2) to a C function, which would be my kmain() ?
I've been following plenty of tutorials lately, but I am stuck at the same step each time.

For instance, I followed the "barebones tutorial" that everyone here knows, on the wiki. I easily can print a character at the top of screen, which is great.
However, as soon as i try to do something like that :

Code: Select all

char *str = "Hello world!";
videomem[0] = str[0];
It does not work anymore. Nothing outputs, but the kernel does not crash, since I still can print characters llike that after :

Code: Select all

videomem[0] = 'H';
(I fill the videoram with 0x07 before, I dont )

I noticed the same thing with the tutorial available here : http://www.osdever.net/bkerndev/Docs/basickernel.htm
I imagine that some of you know this one too. The result was exactly the same : everything works fine until I try to use strings :(

Can anyone tell me what I should fix to have real strings to work in my C kernel ?
Then how can I jump from an assembly routine to an actual C function ? I guess the output format of my compiled kernel will be ELF.

Thanks,

A random noob :)
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: [Newbie] Switching from assembly to C after boot

Post by Solar »

Make sure your linker script actually includes .rodata* in your kernel binary - that's the section strings end up in. Individual characters don't - it's a very common beginner mistake.
Every good solution is obvious once you've found it.
CodeCat
Member
Member
Posts: 158
Joined: Tue Sep 23, 2008 1:45 pm
Location: Eindhoven, Netherlands

Re: [Newbie] Switching from assembly to C after boot

Post by CodeCat »

Don't forget that video memory consists of 16-bit words, not bytes. The first byte of each word is the character, the second is the colour attributes. If the attribute bit is 0 you'll get black on black, so you won't see anything.

EDIT: Calling a C function is done by following the cdecl calling convention. The basic rules for a function call are:

- push the parameters on the stack in reverse order, starting from the rightmost one (the leftmost parameter is pushed last)
- call the function (using the CALL instruction)
- remove the parameters from the stack

For your kmain function this would be nothing more than:

Code: Select all

call kmain
Note that there is nothing mandating that kmain actually has to return, but to make sure things don't get messed up if it does return, you should add a HLT instruction and an infinite loop at the end after the call to kmain:

Code: Select all

cli
loop:
hlt
jmp loop
gerenjo
Posts: 10
Joined: Tue Feb 03, 2009 12:16 pm

Re: [Newbie] Switching from assembly to C after boot

Post by gerenjo »

Yeah I know all this.
I just copy/pasted the linker scripts given in those two tutorials, and it does not work with strings.
As I said, i fill the video ram bytes with 0x7, so I get white text on black background.

The linker script copy/pasted from the bare bones tutorial includes the .rodata AFTER .text, so it doesn't mess the code up.
see: http://wiki.osdev.org/Bare_bones
Again, I don't see any reasons for this not to work:

Code: Select all

char *str = "toto";
videoram[0] = str[0];
whereas THAT works

Code: Select all

videoram[0] = 't';
Is there anything I don't understand or forget to do ? :/
(Assume my code is exactly the same as in the bare bones tutorial)
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: [Newbie] Switching from assembly to C after boot

Post by Combuster »

Are you using the GCC Cross-Compiler? If not the section may have a different name (try .rdata, or better, use objdump)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
neonek
Member
Member
Posts: 38
Joined: Thu Aug 28, 2008 1:53 pm
Location: Białystok - Podlasie, Poland

Re: [Newbie] Switching from assembly to C after boot

Post by neonek »

Hello gerenjo

Maybe JamesM tutorial will help you. For printing functions read The Screen section and read this.

Regards,
Mark
Please correct my English. If you'll find mistake please tell me about it so I can improve my English.
gerenjo
Posts: 10
Joined: Tue Feb 03, 2009 12:16 pm

Re: [Newbie] Switching from assembly to C after boot

Post by gerenjo »

Thank you, I will study this a bit. (more read!)
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: [Newbie] Switching from assembly to C after boot

Post by Troy Martin »

Am I the only one that found a painfully obvious one? Instead of this:

Code: Select all

videoram[0] = str[0];
Use this:

Code: Select all

videoram[0] = *str++; /* put the byte pointed to by str and increase the pointer! */
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: [Newbie] Switching from assembly to C after boot

Post by AJ »

Hi,

I think the OP was only trying to put the first character on the screen to prove it works. What's the point of incrementing the pointer if you only want to display the first character?

Cheers,
Adam
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: [Newbie] Switching from assembly to C after boot

Post by Solar »

Compile your C file to object code (-c).

Use objdump to make sure the string is in the object code, and note the name of the section it is stored in.

Double-check your linker script does include that section.

Compile your kernel binary.

Use objdump to make sure the string is in the binary.

Find out which step fails by logic deduction.

Return here with the additional info.
Every good solution is obvious once you've found it.
User avatar
abachler
Member
Member
Posts: 33
Joined: Thu Jan 15, 2009 2:21 pm

Re: [Newbie] Switching from assembly to C after boot

Post by abachler »

Code: Select all

char str[] = "Hello World!";
has to be declared as a global variable, so that it is allocated at compile time, not at run-time (the pointer , not the string).

In general you should avoid the use of local variables when writing kernel code, at least until you get more experience with what you can and cannot do with them.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: [Newbie] Switching from assembly to C after boot

Post by Combuster »

In general you should avoid the use of local variables when writing kernel code, at least until you get more experience with what you can and cannot do with them.
What a horrible piece of advice. If you're in such a state local variables can not be used then you have some serious problems yourself (including your knowledge of the language).
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: [Newbie] Switching from assembly to C after boot

Post by jal »

As someone already mentioned, try using str[] instead of *str. See if that works. If so, I'm a bit lost why, but then again I don't know the deep dark secrets of C variable initialization.


JAL
Post Reply