[Problem] Pointers in C Cause GRUB error 13!

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
binsky3333
Posts: 14
Joined: Sat Jan 01, 2011 12:34 am

[Problem] Pointers in C Cause GRUB error 13!

Post by binsky3333 »

Hey guys! Well i finally got my C kernel running and booting from GRUB! Now that i had that working, i though id get a simple print function working. I made my own and compiled/linked with no errors. Now i copied the binary to my floppy and booted and got a GRUB error 13. I was very confused and starting playing with my code and commenting out certain parts to see which was causing this ERROR 13. I found out that it was my print function! Whenever i called my print function i would get this grub error 13. After that, i narrowed it down to the pointer ARG. It seems to be causing this error 13, but why? Anyone have any ideas. Also my print func is k_printf();

C code:

Code: Select all

//Minux OS kernel main

//Function Defines

//Ports
unsigned char inportb(unsigned short _port);
void outportb(unsigned short _port, unsigned char _data);

//Video
void init_video();
void clear_screen();
void print_character(char c);
void k_printf(unsigned char *text);
//void print_character(char c, unsigned int line);

//Vars
int cursor_x = 0;
int cursor_y = 0;

void kmain( void* mbd, unsigned int magic )
{
   if ( magic != 0x2BADB002 )
   {
      /* Something went not according to specs. Print an error */
      /* message and halt, but do *not* rely on the multiboot */
      /* data structure. */
   }
 
   /* You could either use multiboot.h */
   /* (http://www.gnu.org/software/grub/manual/multiboot/multiboot.html#multiboot_002eh) */
   /* or do your offsets yourself. The following is merely an example. */ 
   char * boot_loader_name =(char*) ((long*)mbd)[16];
 
   /* Print a letter to screen to see everything is working: */
   unsigned char *videoram = (unsigned char *) 0xb8000;
   videoram[0] = 65; /* character 'A' */
   videoram[1] = 0x07; /* forground, background color. */
   clear_screen();
   k_printf("Hello World!");
   //k_printf("Hello!");
   
   /* Write your kernel here. */
}

/* We will use this later on for reading from the I/O ports to get data
*  from devices such as the keyboard. We are using what is called
*  'inline assembly' in these routines to actually do the work */
unsigned char inportb (unsigned short _port)
{
    unsigned char rv;
    __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
    return rv;
}

/* We will use this to write to I/O ports to send bytes to devices. This
*  will be used in the next tutorial for changing the textmode cursor
*  position. Again, we use some inline assembly for the stuff that simply
*  cannot be done in C */
void outportb (unsigned short _port, unsigned char _data)
{
    __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}

void init_video()
{
	clear_screen();
}

void 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]= 0x07;
      i++;
   }
}

void print_character(char c)
{
	if(c == '\n')
	{
		cursor_x =0;
		cursor_y++;
	}
	
	if(cursor_x >= 80)
	{
		cursor_x = 0;
		cursor_y++;
	}
	
	char *vidmem = (char *) 0xb8000;
	int i = 0;
	i = (cursor_y * 80 * 2);
	vidmem[i] = c;
	i++;
	vidmem[i] = 0x07;
}

void k_printf(unsigned char *text)
{
	int i;
	
	for(i = 0; i < 20; i++)
	{
		print_character(text[i]);
	}
}

/*
void print_character(char c, unsigned int line)
{
	char *vidmem = (char *) 0xb8000;
	unsigned int i=0;
	i = (line*80*2);
	vidmem[i] = c;
	i++;
	vidmem[i] = 0x07;	
}
*/
Thanks in advance!
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: [Problem] Pointers in C Cause GRUB error 13!

Post by gerryg400 »

Check the order of the sections in your linker script. In particular, where in your binary does the multiboot header end up ?
If a trainstation is where trains stop, what is a workstation ?
binsky3333
Posts: 14
Joined: Sat Jan 01, 2011 12:34 am

Re: [Problem] Pointers in C Cause GRUB error 13!

Post by binsky3333 »

gerryg400 wrote:Check the order of the sections in your linker script. In particular, where in your binary does the multiboot header end up ?

Code: Select all

ENTRY (loader)

SECTIONS{
    . = 0x00100000;

    .text :{
        *(.text)
    }

    .rodata ALIGN (0x1000) : {
        *(.rodata)
    }

    .data ALIGN (0x1000) : {
        *(.data)
    }

    .bss : {
        sbss = .;
        *(COMMON)
        *(.bss)
        ebss = .;
    }
}

Here is the script. Though the weird thing is, i only have this problem with this one function and only when i use poitners...

Also is partially boots... [multiboot-kludge, loadaddr = 0x100000, text-and-data = 0x2000] then

Error 13.
Laksen
Member
Member
Posts: 140
Joined: Fri Nov 09, 2007 3:30 am
Location: Aalborg, Denmark

Re: [Problem] Pointers in C Cause GRUB error 13!

Post by Laksen »

Try putting your multiboot header in a .init section and then stuff a *(.init) before *(.text) in your linker script

And put a while(1); at the end of your kmain
http://j-software.dk | JPasKernel - My Object Pascal kernel
binsky3333
Posts: 14
Joined: Sat Jan 01, 2011 12:34 am

Re: [Problem] Pointers in C Cause GRUB error 13!

Post by binsky3333 »

OK so i fixed the problem! Woo hoo! It was that the multiboot header was ending up in the wrong spot.

Now could someone help me with this C code. It should be working, but unfortunately is not.

Code: Select all

//Minux OS kernel main

//Function Defines

//Ports
unsigned char inportb(unsigned short _port);
void outportb(unsigned short _port, unsigned char _data);

//Video
void init_video();
void clear_screen();
void print_character(char c);
void k_printf(unsigned char *text);
unsigned int k_printf2(char *message, unsigned int line);
//void print_character(char c, unsigned int line);

//Vars
int cursor_x = 0;
int cursor_y = 0;

void kmain( void* mbd, unsigned int magic )
{
   if ( magic != 0x2BADB002 )
   {
      /* Something went not according to specs. Print an error */
      /* message and halt, but do *not* rely on the multiboot */
      /* data structure. */
   }
 
   /* You could either use multiboot.h */
   /* (http://www.gnu.org/software/grub/manual/multiboot/multiboot.html#multiboot_002eh) */
   /* or do your offsets yourself. The following is merely an example. */ 
   char * boot_loader_name =(char*) ((long*)mbd)[16];
 
   /* Print a letter to screen to see everything is working: */
   unsigned char *videoram = (unsigned char *) 0xb8000;
   videoram[0] = 65; /* character 'A' */
   videoram[1] = 0x07; /* forground, background color. */
   clear_screen();
   //k_printf2("Hello World!",0);
   k_printf("AA");
   //k_printf("Hello!");
   
   while(1)
   {
   	
   	
	}
   
   /* Write your kernel here. */
}

/* We will use this later on for reading from the I/O ports to get data
*  from devices such as the keyboard. We are using what is called
*  'inline assembly' in these routines to actually do the work */
unsigned char inportb (unsigned short _port)
{
    unsigned char rv;
    __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
    return rv;
}

/* We will use this to write to I/O ports to send bytes to devices. This
*  will be used in the next tutorial for changing the textmode cursor
*  position. Again, we use some inline assembly for the stuff that simply
*  cannot be done in C */
void outportb (unsigned short _port, unsigned char _data)
{
    __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}

void init_video()
{
	clear_screen();
}

void 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]= 0x07;
      i++;
   }
}

void print_character(char c)
{
	if(c == '\n')
	{
		cursor_x =0;
		cursor_y++;
	}
	
	if(cursor_x >= 80)
	{
		cursor_x = 0;
		cursor_y++;
	}
	
	char *vidmem = (char *) 0xb8000;
	int i = 0;
	//i = (cursor_y * 80 * 2);
	i = (cursor_y * 80 + cursor_x);
	vidmem[i] = c;
	i++;
	vidmem[i] = 0x07;
	cursor_x++;
}

void k_printf(unsigned char *text)
{
	int i;
	
	for(i = 0; i < 2; i++)
	{
		print_character(text[i]);
	}
}

unsigned int k_printf2(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]=0x07;
         i++;
      };
   };

   return(1);
};

/*
void print_character(char c, unsigned int line)
{
	char *vidmem = (char *) 0xb8000;
	unsigned int i=0;
	i = (line*80*2);
	vidmem[i] = c;
	i++;
	vidmem[i] = 0x07;	
}
*/


Specifically with k_printf();

And yes i know the for loop is messed up, but im only printing two characters.

Thanks in advance!
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: [Problem] Pointers in C Cause GRUB error 13!

Post by gerryg400 »

Now could someone help me with this C code. It should be working, but unfortunately is not.
Specifically with k_printf();
Specifically what ? What is not working ?
If a trainstation is where trains stop, what is a workstation ?
binsky3333
Posts: 14
Joined: Sat Jan 01, 2011 12:34 am

Re: [Problem] Pointers in C Cause GRUB error 13!

Post by binsky3333 »

Its only printing one character. I think the formula to find out the vid mem addr is messed up.
Tosi
Member
Member
Posts: 255
Joined: Tue Jun 15, 2010 9:27 am
Location: Flyover State, United States
Contact:

Re: [Problem] Pointers in C Cause GRUB error 13!

Post by Tosi »

Yes, the formula to calculate it is wrong. Since you're using a pointer to a char (1 byte) instead of a short/word (2 bytes), you will have to multiply the offset by 2 in order to get the correct number of bytes.

My way of doing it is like this:

Code: Select all

static volatile Word * const txtptr = (Word*)0xB8000;
...
Word val = a_char | (attr << 8);
...
txtptr[xpos + ypos*80] = val;
The pointer to text mode memory itself is never modified, so I declared it * const.
binsky3333
Posts: 14
Joined: Sat Jan 01, 2011 12:34 am

Re: [Problem] Pointers in C Cause GRUB error 13!

Post by binsky3333 »

Tosi wrote:Yes, the formula to calculate it is wrong. Since you're using a pointer to a char (1 byte) instead of a short/word (2 bytes), you will have to multiply the offset by 2 in order to get the correct number of bytes.

My way of doing it is like this:

Code: Select all

static volatile Word * const txtptr = (Word*)0xB8000;
...
Word val = a_char | (attr << 8);
...
txtptr[xpos + ypos*80] = val;
The pointer to text mode memory itself is never modified, so I declared it * const.
Arnt i doing that in this code?

Code: Select all

 	char *vidmem = (char *) 0xb8000;
	int i = 0;
	//i = (cursor_y * 80 * 2);
	i = (cursor_y * 80 + cursor_x);
	vidmem[i] = c;
	i++;
	vidmem[i] = 0x07;
	cursor_x++;   
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: [Problem] Pointers in C Cause GRUB error 13!

Post by neon »

Arnt i doing that in this code?
No, of course not (Do you see it anywhere in your code?). As mentioned above, you need to multiply the offset by 2 sense you are working with a byte pointer - your code doesnt do that. clear_screen() in your provided code performs this calculation correctly - just do the same for your character display routine.

Alternatively, just use a word pointer and write the attribute and character bytes at the same time.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
binsky3333
Posts: 14
Joined: Sat Jan 01, 2011 12:34 am

Re: [Problem] Pointers in C Cause GRUB error 13!

Post by binsky3333 »

Fixed everything, thanks guys!
Post Reply