Page 1 of 2

Problem Outputing Proper Text

Posted: Thu Nov 02, 2006 8:04 pm
by Fear
For some reason, any time I code a "print text to screen function", it can only produce single 'S's. I am using DJGPP and its all in C. Also, I'm using Bochs to run it. The problem code:

Code: Select all

void Write(const char* Text)
{
    char* VidMem = (char*) 0xB8000;
    int Offset;
    long X;

    Out(0x3D4, 14);
    Offset = In(0x3D5) << 8;
    Out(0x3D4, 15);
    Offset |= In(0x3D5);

    VidMem += Offset << 1;

    X = 0;
    while (*Text != 0)
    {
        *VidMem++ = *Text++;
        *VidMem++ = 0xF;
        X++;
    }

    Offset += X - 1;
    Out(0x3D5, (unsigned char) Offset);
    Out(0x3D4, 14);
    Out(0x3D5, (unsigned char) Offset >> 8);
}
And the calling code:

Code: Select all

const char* LineOne = "Welcome to Sharp!";
void Main()
{
    Write(LineOne);
}
I'm a little new to the whole OSDev thing, so if somebody can tell me whats wrong with it...

Posted: Thu Nov 02, 2006 8:28 pm
by Mike
Just a shot in the dark, but is your read-only data section properly linked? I don't know the specifics because I use MSVC, but failing to link the .rodata segment (I think...) is often the cause of strange string printing bugs.

Search the forum, this type of thing seems to happen often.

Nothing looks wrong from a quick glance at the code, although I would recommend using a global variable or something to store the X and Y position rather than using seven port I/O instructions per character. This could get slow. But slowness is secondary: getting it working is the top priority.

Mike

Posted: Thu Nov 02, 2006 9:05 pm
by Fear
I had it set up for global variables, but I had even odder bugs before. So, once it writes properly, I'll try and fix the globals.

Posted: Fri Nov 03, 2006 4:28 am
by Combuster
You probably have a linker issue. Check that you indeed link the .rodata section as your program does need it.
The code itself is perfectly fine - it runs in my os without problems:

Code: Select all

Booting from Floppy...
MOS V1.3.0 bootloader executing
Loading MOS86..............................
MEM A20 GDT TXT Welcome to Sharp!
Mike: its 7 I/Os a string, not each character :)

Posted: Fri Nov 03, 2006 6:55 am
by Fear
Can you post the linker script you used to compile it? Because I tried some examples with the rodata section in it, and it still compiled the same way....

Posted: Fri Nov 03, 2006 7:29 am
by gaf
Maybe you just have to add an asterix to include all rodata sections:

Code: Select all

SECTIONS 
{ 
    .text 0xDEADBEEF : 
    { 
        *(.text) 
        *(.rodata*) 
    } 

    .data : 
    { 
        *(.data) 
    } 

    .bss : 
    { 
        *(.bss*) 
        *(.comment*) 
    } 
}
cheers,
gaf

Posted: Fri Nov 03, 2006 2:43 pm
by Fear
I just can't get it to work. It's as if my computer is against me. I've tried close to 100 different linker scripts and none of them will work with me...
If anyone else has a good suggestion, speak up.

Posted: Fri Nov 03, 2006 3:23 pm
by nick8325
Well, what linker script are you using? I agree with everyone else: your code looks fine.

Posted: Fri Nov 03, 2006 3:37 pm
by Fear
My script:

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(Start)
phys = 0x100000;
SECTIONS 
{ 
    .text phys : 
    { 
        code = .;
        *(.text) 
        *(.rdata*) 
    } 

    .data : 
    { 
        data = .;
        *(.data) 
    } 

    .bss : 
    { 
        bss = .;
        *(.bss*) 
        *(.comment*) 
    }
    end = .; 
}

Posted: Fri Nov 03, 2006 3:39 pm
by nick8325
Ah, you have a typo: *(.rdata*) should be *(.rodata*)...

Posted: Fri Nov 03, 2006 3:41 pm
by Fear
I've tried with both. Neither worked.

Edit: I ran was looking at a dump of the code, and both of my strings are there. I don't know if this means that the linker is not the problem, but maybe its something to consider.

Posted: Fri Nov 03, 2006 3:59 pm
by nick8325
OK, but stick with .rodata* as .rdata* is definitely wrong. (Just in case that was also a problem.)

Also, change "int Offset" to "unsigned int Offset". What is the type of In? If it returns a char, change it to return an unsigned char.

(A char might be signed. If the call to In() returns some character >= 128, it'll be negative as a signed char, so when the compiler casts the char into an int (to store it in Offset), it'll stick 1s at the beginning instead of 0s, which will make everything go wrong.)

EDIT: I didn't notice your edit. I suppose the linker script is OK then.

Posted: Fri Nov 03, 2006 4:07 pm
by Fear
I still can't make it work, but I did change what you said. It just won't co-operate with me.

Sidenote: Anyone know of any places where I can learn to write a 64-bit OS. I think that would be cooler...

Posted: Fri Nov 03, 2006 4:13 pm
by nick8325
If you upload your kernel binary and maybe the .o file containing Write (you'll need to zip them, apparently), I can look at them and see if anything looks strange...

Posted: Fri Nov 03, 2006 4:23 pm
by Fear
All my code, and objects, as well as the compiled bootloader and kernel.