Printing

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.
DeBeNoPrMa
Posts: 8
Joined: Tue Feb 22, 2011 4:59 pm
Location: Barcelona, Spain

Printing

Post by DeBeNoPrMa »

First of all; Hello World!

I started yesterday with OS Development with a very basic kernel written in C booted from GRUB with QEMU. I wrote a simple kprint function to write some test text and it worked well. Today I thought of a more efficient 'kprint' function and I wrote it. I have just changed it a little bit but it has stopped working. I have been two hours trying to figure out why it's not working and I can't find out. I'm sure I'm missing something very stupid but I can't think so much at 3:11 AM. I've read the OSDev wiki "Printing" page to compare but although it's a different way of doing it I can't find anithing wrong.

The 'kprint' function is the following

Code: Select all

void kprint(int colour, const char *string)
{
	volatile char *vidmem=(volatile char*)0xB8000;
	int end = 0;
	while(end == 0)
	{
		*vidmem=*string; 
		vidmem++;
		*vidmem=colour;
		vidmem++;
		string++;
		end = *string == '/' ? 1 : 0; 
	}
}
Ty in advance and sorry for such a noobish question

Greetings from Spain!
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Printing

Post by NickJohnson »

Don't you want to check for '\0' instead of '\'?
DeBeNoPrMa
Posts: 8
Joined: Tue Feb 22, 2011 4:59 pm
Location: Barcelona, Spain

Re: Printing

Post by DeBeNoPrMa »

NickJohnson wrote:Don't you want to check for '\0' instead of '\'?
Tried that with the same code and not working. Then I tried changing the input string as "Hello World!"+'\0' and it just shows the first two letters ( He )
Thank you for such a quick reply

Edit1: I've tried checking for '1' and it works, dunno why it doesn't work with '\0' or '/'.
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Printing

Post by NickJohnson »

Well, I still don't see the exact issue, but you might as well get rid of the "end" variable and just check *string (it will be zero if the next character is a null), just to remove uncertainties:

Code: Select all

void kprint(int colour, const char *string)
{
   volatile char *vidmem=(volatile char*)0xB8000;
   while (*string)
   {
      *vidmem=*string;
      vidmem++;
      *vidmem=colour;
      vidmem++;
      string++;
   }
}
DeBeNoPrMa
Posts: 8
Joined: Tue Feb 22, 2011 4:59 pm
Location: Barcelona, Spain

Re: Printing

Post by DeBeNoPrMa »

NickJohnson wrote:Well, I still don't see the exact issue, but you might as well get rid of the "end" variable and just check *string (it will be zero if the next character is a null), just to remove uncertainties:

Code: Select all

void kprint(int colour, const char *string)
{
   volatile char *vidmem=(volatile char*)0xB8000;
   while (*string)
   {
      *vidmem=*string;
      vidmem++;
      *vidmem=colour;
      vidmem++;
      string++;
   }
}
Done, just for trying I added 3 missing '*' just to try and now it works :S I don't really understand why ( '*' means value pointed by, right? Or it's too late and my brain is just a soup? ) So finally code it's as follows:

Code: Select all

void kprint(int colour, const char *string)
{
   volatile char *vidmem=(volatile char*)0xB8000;
   while (*string)
   {
      *vidmem=*string;
      *vidmem++;
      *vidmem=colour;
      *vidmem++;
      *string++;
   }
}
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Printing

Post by gerryg400 »

Are you running in Qemu or Bochs ? And clearing interrupts and hlting after returning from your kprintf function ? If so then this is a commonly reported problem. There are many threads about it.
If a trainstation is where trains stop, what is a workstation ?
DeBeNoPrMa
Posts: 8
Joined: Tue Feb 22, 2011 4:59 pm
Location: Barcelona, Spain

Re: Printing

Post by DeBeNoPrMa »

gerryg400 wrote:Are you running in Qemu or Bochs ? And clearing interrupts and hlting after returning from your kprintf function ? If so then this is a commonly reported problem. There are many threads about it.
Sorry, I googled and searched here in the forums but didn't see anything. :?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Printing

Post by gerryg400 »

Sorry I had to run off half way through answering.

Try this thread http://forum.osdev.org/viewtopic.php?f= ... lt#p186149
If a trainstation is where trains stop, what is a workstation ?
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Printing

Post by Solar »

DeBeNoPrMa wrote:Done, just for trying I added 3 missing '*' just to try and now it works :S I don't really understand why ( '*' means value pointed by, right? Or it's too late and my brain is just a soup? ) So finally code it's as follows:

Code: Select all

void kprint(int colour, const char *string)
{
   volatile char *vidmem=(volatile char*)0xB8000;
   while (*string)
   {
      *vidmem=*string;  // OK
      *vidmem++;        // You want to increment the POINTER (to 0xb8001), not the value pointed to ('H'->'I'). No * here!
      *vidmem=colour;   // OK
      *vidmem++;        // See above
      *string++;        // See above - you're trying to turn the 'H' of string into an 'I' here
                        // instead of advancing the pointer to 'e'. Since the values pointed to
                        // by string are const, this shouldn't even compile.
   }
}
If that actually works, my brain is soup, too. See my comments.
Every good solution is obvious once you've found it.
DeBeNoPrMa
Posts: 8
Joined: Tue Feb 22, 2011 4:59 pm
Location: Barcelona, Spain

Re: Printing

Post by DeBeNoPrMa »

Solar wrote:
DeBeNoPrMa wrote:Done, just for trying I added 3 missing '*' just to try and now it works :S I don't really understand why ( '*' means value pointed by, right? Or it's too late and my brain is just a soup? ) So finally code it's as follows:

Code: Select all

void kprint(int colour, const char *string)
{
   volatile char *vidmem=(volatile char*)0xB8000;
   while (*string)
   {
      *vidmem=*string;  // OK
      *vidmem++;        // You want to increment the POINTER (to 0xb8001), not the value pointed to ('H'->'I'). No * here!
      *vidmem=colour;   // OK
      *vidmem++;        // See above
      *string++;        // See above - you're trying to turn the 'H' of string into an 'I' here
                        // instead of advancing the pointer to 'e'. Since the values pointed to
                        // by string are const, this shouldn't even compile.
   }
}
If that actually works, my brain is soup, too. See my comments.
I know it doesn't make sense, but actually works, while the previous one didn't. I'm confused. I just tried as a desperate mesure and it worked :?
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Printing

Post by Solar »

OK, rebuild from scratch. Delete all images, executables and object files and whatnot, make double sure all that's remaining is the sources, rebuild from those sources, and make double sure that what you are executing is actually what's in the sources in their latest version.

Also double-check any assumptions you're making ("if this light flashes green, it's working OK").

The source above shouldn't compile (modifying a const value), let alone run correctly. There's no magic where computers are concerned, there is no way that wrong source can result in correct operation. (Well, there is, but that requires malignancy. :twisted: )

Currently I'm suspecting something like "editing sources in one directory, but compiling from a different directory".
Every good solution is obvious once you've found it.
uri
Posts: 8
Joined: Tue Feb 22, 2011 12:53 pm

Re: Printing

Post by uri »

Solar wrote:
DeBeNoPrMa wrote:

Code: Select all

      *vidmem++;        // You want to increment the POINTER (to 0xb8001), not the value pointed to 
IIRC, according to the C operator precedence rules it is the pointer that's incremented. Since the post-increment operator is used, the exact sequence of operations should be: dereference pointer and ignore the result, then increment the pointer. I don't see how that makes any difference, though. It might be interesting to compare the generated assembler code for both variants.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Printing

Post by Solar »

#-o #-o #-o

You're right, of course! The three extra asterixes do nothing in that code... I can't believe I've fallen into that trap.

:oops: :roll: :oops:

Really. Is this age beginning to show?
Every good solution is obvious once you've found it.
DeBeNoPrMa
Posts: 8
Joined: Tue Feb 22, 2011 4:59 pm
Location: Barcelona, Spain

Re: Printing

Post by DeBeNoPrMa »

uri wrote:
Solar wrote:
DeBeNoPrMa wrote:

Code: Select all

      *vidmem++;        // You want to increment the POINTER (to 0xb8001), not the value pointed to 
IIRC, according to the C operator precedence rules it is the pointer that's incremented. Since the post-increment operator is used, the exact sequence of operations should be: dereference pointer and ignore the result, then increment the pointer. I don't see how that makes any difference, though. It might be interesting to compare the generated assembler code for both variants.
To satiate your interest (its not the whole kprint, just the inside of the while loop that is what changes)
With the 3 *:

Code: Select all

	movl	12(%ebp), %eax  //*vidmem = *string                  
	movzbl	(%eax), %edx                    
	movl	-4(%ebp), %eax
	movb	%dl, (%eax)
	movl	-4(%ebp), %eax
	movzbl	(%eax), %eax
	addl	$1, -4(%ebp)    //*vidmem++
	movl	8(%ebp), %eax
	movl	%eax, %edx
	movl	-4(%ebp), %eax 
	movb	%dl, (%eax)
	movl	-4(%ebp), %eax
	movzbl	(%eax), %eax
	addl	$1, -4(%ebp)    //*vidmem++
	addl	$1, 12(%ebp)   //*string++
Without:

Code: Select all

	movl	12(%ebp), %eax
	movzbl	(%eax), %edx
	movl	-4(%ebp), %eax
	movb	%dl, (%eax)
	addl	$1, -4(%ebp)
	movl	8(%ebp), %eax
	movl	%eax, %edx
	movl	-4(%ebp), %eax
	movb	%dl, (%eax)
	addl	$1, -4(%ebp)
	addl	$1, 12(%ebp)
I've now tried to compile with and without, and without some errors appear (chars missing, bad position, etc...)
quok
Member
Member
Posts: 490
Joined: Wed Oct 18, 2006 10:43 pm
Location: Kansas City, KS, USA

Re: Printing

Post by quok »

Solar wrote:Really. Is this age beginning to show?
It's ok Solar. They say memory is the second thing to go. Unfortunately I don't remember what the first one is! :lol:
Post Reply