Understanding Bare Bones

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.
gsingh2011
Member
Member
Posts: 83
Joined: Tue Feb 03, 2009 11:37 am

Understanding Bare Bones

Post by gsingh2011 »

For those of you who were helping me set up GCC on windows recently, I just wanted to say thanks for the help, but I switched to linux. It was just pissing me way to much.. Anyway, now that I know how to boot a basic floppy image, I'm trying to understand the code. First of all, I know what's all of this about a multiboot header in the bare bones tutorial loader.s? What is a multiboot header? Then there's the code:

Code: Select all

unsigned char *videoram = (unsigned char *) 0xb8000;
   videoram[0] = 65; /* character 'A' */
   videoram[1] = 0x07; /* forground, background color. */
Why 0xb8000? Can I display longer strings? What else can I do with this?

And is the linker script written in a certain language? Where can I learn more about how this works?
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Re: Understanding Bare Bones

Post by piranha »

0xb8000 is the standard memory position to write text to the screen. Its just a standard.

To display longer strings, you need to go though the string and display each character.

Code: Select all

puts(char *s) {
     while(*s) {
          videoram[offset++] = *s; /* character 'A' */
          videoram[offset++] = 0x07; /* forground, background color. */
          s++;
      }
}
Offset should be a number that shows where the current position on screen is. You can also find it by creating cursor_x and y variables that keeps track of the x, y position.

-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
User avatar
Steve the Pirate
Member
Member
Posts: 152
Joined: Fri Dec 15, 2006 7:01 am
Location: Brisbane, Australia
Contact:

Re: Understanding Bare Bones

Post by Steve the Pirate »

gsingh2011 - the Multiboot header is what gives Grub (the bootloader) the information it needs to boot your kernel executable.

piranha - That should be

Code: Select all

puts(const char * s)
, shouldn't it? GCC will complain if you try to call puts like

Code: Select all

puts("A string to print");
because implicitly converting a const char * to a char * is being depreciated.
My Site | My Blog
Symmetry - My operating system.
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Re: Understanding Bare Bones

Post by piranha »

Yeah, sure. But that wasn't supposed to be copied, that was just an example. Proper implementation should be done.

-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Understanding Bare Bones

Post by Troy Martin »

piranha wrote:Yeah, sure. But that wasn't supposed to be copied, that was just an example. Proper implementation should be done.
OP: Adding on what piranha said, a slightly more proper implementation must have at least a newline handler (print \r\n when \n is encountered) a method of calculating the offset from 0xB8000 using the cursor position, and updating the cursor. I'd say a fully complete implementation of string printing is a working printf() function.
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
gsingh2011
Member
Member
Posts: 83
Joined: Tue Feb 03, 2009 11:37 am

Re: Understanding Bare Bones

Post by gsingh2011 »

Could you give me the code to display the text "Hi"? I think that would clear things up for me...
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Re: Understanding Bare Bones

Post by piranha »

This code is very simple, with newline parsing. You can figure out backspaces, etc.

Code: Select all

int x=0, y=0;
void puts(const char *str) {
     while(*str) {
          if(*str == '\n')
          { //Handle newline
                str++;
                x=0;y++;
          }
          videoram[y*80+x] = *str; /* character */
          videoram[y*80+x+1] = 0x07; /* forground, background color. */
          x++;
          if(x > 80)
          { //If we reached to edge of the screen
                 x=0;
                 y++;
          }
          str++;
     }
}

int main() {
     ...
     puts("Hi\n");
     ...
}
Note: You should also add code for scrolling, so when the code gets to the bottom of the screen it scrolls up one line. That can be done by copying all lines of memory back the length of one line.

-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
gsingh2011
Member
Member
Posts: 83
Joined: Tue Feb 03, 2009 11:37 am

Re: Understanding Bare Bones

Post by gsingh2011 »

Hmm.. My code looks like this now and nothing shows up when I boot it:

Code: Select all

unsigned char *videoram = (unsigned char *) 0xb8000;
int x=0, y=0;

void puts(const char *str) {
     while(*str) {
          if(*str == '\n')
          { //Handle newline
                str++;
                x=0;y++;
          }
          videoram[y*80+x] = *str; /* character */
          videoram[y*80+x+1] = 0x07; /* forground, background color. */
          x++;
          if(x > 80)
          { //If we reached to edge of the screen
                 x=0;
                 y++;
          }
          str++;
     }
}

void kmain( void* mbd, unsigned int magic )
{
	puts("Hi\n");
}
What did I do wrong?

And about the multiboot header, is it's purpose so that you can boot different types of OS's from that one bootloader? What do the operations 1<<0 and 1<<1 do in assembly? I couldn't find them in any tutorials...
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Re: Understanding Bare Bones

Post by piranha »

OOO, ouch I fail.

the x++ should be x+=2.

-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
gsingh2011
Member
Member
Posts: 83
Joined: Tue Feb 03, 2009 11:37 am

Re: Understanding Bare Bones

Post by gsingh2011 »

Same thing, nothing shows up... Does that exact code I pasted work for you when you run it?
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Re: Understanding Bare Bones

Post by piranha »

Yes, that should show something. But I do fail again.

I don't have time to explain why you should not use the code that I posted, so I'm going to forward you to http://jamesmolloy.co.uk/tutorial_html/ ... creen.html

-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
gsingh2011
Member
Member
Posts: 83
Joined: Tue Feb 03, 2009 11:37 am

Re: Understanding Bare Bones

Post by gsingh2011 »

Ok, I looked at the site and I tried the code but I get an error. Here's the code I have in the monitor.h:

Code: Select all

// monitor.h -- Defines the interface for monitor.h
// From JamesM's kernel development tutorials.

#ifndef MONITOR_H
#define MONITOR_H

#include "common.h"

int cursor_x, cursor_y = 0;
unsigned char *video_memory = (unsigned char *) 0xb8000;

// Scrolls the text on the screen up by one line.
static void scroll()
{

   // Get a space character with the default colour attributes.
   u8int attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
   u16int blank = 0x20 /* space */ | (attributeByte << 8);

   // Row 25 is the end, this means we need to scroll up
   if(cursor_y >= 25)
   {
       // Move the current text chunk that makes up the screen
       // back in the buffer by a line
       int i;
       for (i = 0*80; i < 24*80; i++)
       {
           video_memory[i] = video_memory[i+80];
       }

       // The last line should now be blank. Do this by writing
       // 80 spaces to it.
       for (i = 24*80; i < 25*80; i++)
       {
           video_memory[i] = blank;
       }
       // The cursor should now be on the last line.
       cursor_y = 24;
   }

// Updates the hardware cursor.
static void move_cursor()
{
   // The screen is 80 characters wide...
   u16int cursorLocation = cursor_y * 80 + cursor_x;
   outb(0x3D4, 14);                  // Tell the VGA board we are setting the high cursor byte.
   outb(0x3D5, cursorLocation >> 8); // Send the high cursor byte.
   outb(0x3D4, 15);                  // Tell the VGA board we are setting the low cursor byte.
   outb(0x3D5, cursorLocation);      // Send the low cursor byte.
}

// Clears the screen, by copying lots of spaces to the framebuffer.
void monitor_clear()
{
   // Make an attribute byte for the default colours
   u8int attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
   u16int blank = 0x20 /* space */ | (attributeByte << 8);

   int i;
   for (i = 0; i < 80*25; i++)
   {
       video_memory[i] = blank;
   }

   // Move the hardware cursor back to the start.
   cursor_x = 0;
   cursor_y = 0;
   move_cursor();
}

// Writes a single character out to the screen.
void monitor_put(char c)
{
   // The background colour is black (0), the foreground is white (15).
   u8int backColour = 0;
   u8int foreColour = 15;

   // The attribute byte is made up of two nibbles - the lower being the
   // foreground colour, and the upper the background colour.
   u8int  attributeByte = (backColour << 4) | (foreColour & 0x0F);
   // The attribute byte is the top 8 bits of the word we have to send to the
   // VGA board.
   u16int attribute = attributeByte << 8;
   u16int *location;

   // Handle a backspace, by moving the cursor back one space
   if (c == 0x08 && cursor_x)
   {
       cursor_x--;
   }

   // Handle a tab by increasing the cursor's X, but only to a point
   // where it is divisible by 8.
   else if (c == 0x09)
   {
       cursor_x = (cursor_x+8) & ~(8-1);
   }

   // Handle carriage return
   else if (c == '\r')
   {
       cursor_x = 0;
   }

   // Handle newline by moving cursor back to left and increasing the row
   else if (c == '\n')
   {
       cursor_x = 0;
       cursor_y++;
   }
   // Handle any other printable character.
   else if(c >= ' ')
   {
       location = video_memory + (cursor_y*80 + cursor_x);
       *location = c | attribute;
       cursor_x++;
   }

   // Check if we need to insert a new line because we have reached the end
   // of the screen.
   if (cursor_x >= 80)
   {
       cursor_x = 0;
       cursor_y ++;
   }

   // Scroll the screen if needed.
   scroll();
   // Move the hardware cursor.
   move_cursor();
}

// Outputs a null-terminated ASCII string to the monitor.
void monitor_write(char *c)
{
   int i = 0;
   while (c[i])
   {
       monitor_put(c[i++]);
   }
}

#endif // MONITOR_H
I get the errors:

Code: Select all

In file included from Source Files/kernel.c:2:
/home/gulshan/Documents/OS/monitor.h: In function ‘scroll’:
/home/gulshan/Documents/OS/monitor.h:43: error: invalid storage class for function ‘move_cursor’
/home/gulshan/Documents/OS/monitor.h: In function ‘monitor_put’:
/home/gulshan/Documents/OS/monitor.h:114: warning: assignment from incompatible pointer type
Source Files/kernel.c: In function ‘scroll’:
Source Files/kernel.c:9: error: expected declaration or statement at end of input
Source Files/kernel.c: At top level:
Source Files/kernel.c:5: warning: unused parameter ‘mbd’
Source Files/kernel.c:5: warning: unused parameter ‘magic’
User avatar
Steve the Pirate
Member
Member
Posts: 152
Joined: Fri Dec 15, 2006 7:01 am
Location: Brisbane, Australia
Contact:

Re: Understanding Bare Bones

Post by Steve the Pirate »

Code: Select all

       // The cursor should now be on the last line.
       cursor_y = 24;
   }

} // <- You forgot to add this.

// Updates the hardware cursor.
static void move_cursor()
Apart from that, I wouldn't recommend having that code in a header (usually you just put prototypes of the functions you need to access from other source files)... But for now it will do, I suppose.

Stephen
My Site | My Blog
Symmetry - My operating system.
gsingh2011
Member
Member
Posts: 83
Joined: Tue Feb 03, 2009 11:37 am

Re: Understanding Bare Bones

Post by gsingh2011 »

I've been having a few problems. I'm getting the errors:

Code: Select all

Source Files/kernel.h:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘default_console’
Source Files/kernel.c:7: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘:’ token
Source Files/kernel.c:14: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘:’ token
For the respective lines:

Code: Select all

class default_console
void default_console::default_console()
void default_console::clear()
Did I declare the class wrong or something? If you need more code just ask.
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Understanding Bare Bones

Post by Troy Martin »

Classes don't exist in C. You'll have to do without them.
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
Post Reply