Page 1 of 1

Weird printing problem

Posted: Wed Aug 25, 2010 7:27 am
by Qeroq
Hello,
as I finally tried to enter operating system development I've encountered a weird problem using the following code:

Code: Select all

struct ConsoleCell cell;

for (i = 0; i < (80 * 25); i++)
{
    cell.character = '0' + (i % 10);
    cell.attributes = 0x07;
    videomem[i] = cell;
}
with ConsoleCell defined as

Code: Select all

struct ConsoleCell
{
    char character;
    unsigned char attributes;
} __attribute__((packed));
and videomem defined as

Code: Select all

videomem = (ConsoleCell*) 0xb8000;
This code obviously is intended to fill the screen with numbers from zero to ten, but it doesn't, at least not completely:
Image

Additionally, when I try to set a random character using the following code after filling the screen, nothing happens.

Code: Select all

    struct ConsoleCell cell;
    cell.character = c;
    cell.attributes = 0x35;
    
    videomem[y * 80 + x] = cell;
In fact, the screenshot above is generated after having called the last code snippet for c='B', x=20 and y=2.

I'm compiling my code on an x86_64 using the following tools:
g++ -m32 -march=i386 -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions -Wall -Wextra
nasm -f elf32
ld -melf_i386

Qemu is used for running the resulting floppy image.

Re: Weird printing problem

Posted: Wed Aug 25, 2010 7:36 am
by Combuster
QEmu is notorious for buffering video memory. If you have a cli;hlt; somewhere in your code, replace it with a spinloop (usually, while(1); or jmp $). You can start by adding one of those at the end of your drawing code to see if that makes it do what you want.

Re: Weird printing problem

Posted: Wed Aug 25, 2010 7:57 am
by Qeroq
Hm, I added a while(true); to the end of my main() leading to more characters to be rendered, but there are still 11 ones missing at the lower right corner, and my 'B' does not get written at all.
Please ask, if I've missed some important information.

Re: Weird printing problem

Posted: Wed Aug 25, 2010 8:43 am
by cristian

Code: Select all

// Try it this way
for (i = 0; i < (80 * 25); i++)
{
    videomem[i].character = '0' + (i % 10);
    videomem[i].attributes = 0x07;
}
EDIT

Code: Select all

void putchar(u16 pos, i8 ch, u8 color)
{
    if(pos < screensize){
        videomem[pos].character = ch;
        videomem[pos].attributes = color;
    } else {
        // You ain't got no pancake mix!
    }
}
Use it like putchar(pos, 'a', 0x07);

EDIT2, 3

Code: Select all

void putchar(u16 x, u16 y, i8 ch, u8 color)
{
    if(x < 80 && y < 25){
        videomem[y*80 + x].character = ch;
        videomem[y*80 + x].attributes = color;
    } else if(y >= 25){
        // Next page?
        // You ain't got no pancake mix!
    } else {
        // You ain't got no pancake mix!
    }
}
Use it like putchar(10, 50, 'a', 0x07);
If it won't work, try using bochs.

Re: Weird printing problem

Posted: Wed Aug 25, 2010 2:01 pm
by gerryg400
Make sure interrupts are enabled before you do the while (1) loop.

Code: Select all

   __asm__ __volatile__ ( "sti" );
   while (1)
      ;
If Qemu reaches a jmp that does not modify the instruction pointer and interrupts are disabled, it stops processing, even if there is not a hlt.

Re: Weird printing problem

Posted: Thu Aug 26, 2010 2:43 am
by Qeroq
Hello,
you have helped me very much as I was kind of going insane not being able to figure out what's wrong with my code. Bochs just does its job well, although it's always rebooting when I call sti before the infinite loop.

Re: Weird printing problem

Posted: Thu Aug 26, 2010 3:42 am
by gerryg400
Time to set up an IDT.

Re: Weird printing problem

Posted: Thu Aug 26, 2010 4:10 am
by Candy
or, short term fix, do some pointless processing.

Code: Select all


int retval = 2937859821;
while (retval) {
   retval = retval * 2436719375 + 29864765;
}

while(1) {}