Page 1 of 1

Confused Noob - why is the value not being set?

Posted: Thu Dec 20, 2012 3:39 pm
by nigelren
I haven't really programmed much in C for some time, so I've been using the JamesM's tutorial to try and play with a new kernel. I have changed it to be a 64 bit binary and most things seem to work, except global variables don't seem to be able to retain their value. The simplest test code I came up with is.

Code: Select all

// main.c -- Defines the C-code kernel entry point, calls initialisation routines.
//           Made for JamesM's tutorials <www.jamesmolloy.co.uk>

#include "monitor.h"
#include "multiboot.h"

u8int cursor_x1 = 1;

void temp_write(u16int *videoOut, u32int n)	{

    s32int tmp;
    char noZeroes = 1;
    int i;
    for (i = 28; i > 0; i -= 4)
    {
        tmp = (n >> i) & 0xF;
        if (!tmp && noZeroes)
        {
            continue;
        }

        if (tmp >= 0xA)
        {
            noZeroes = 0;
            *videoOut++ = (tmp-0xA+'a') + (0x1e<<8);
        }
        else
        {
            noZeroes = 0;
            *videoOut++ = (tmp+'0') + (0x1e<<8);
        }
    }

    tmp = n & 0xF;
    if (tmp >= 0xA)
    {
    	*videoOut++ = (tmp-0xA+'a') + (0x1e<<8);
    }
    else
    {
    	*videoOut++ = (tmp+'0') + (0x1e<<8);
    }
}

int main(struct multiboot_info *mboot_ptr)
{
	temp_write((u16int *)0xB8000+400, cursor_x1++);
	temp_write((u16int *)0xB8000+420, cursor_x1++);
   return 0;
}

The problem I have is that cursor_x1 always comes out as 0. However if I make it a local variable, it works OK. I'm really confused as to what I'm doing and would appreciate it if anyone can point to what I'm doing wrong.

I'm compiling with Eclipse and it uses...
gcc -I/usr/src/linux-headers-3.2.0-33 -O0 -g3 -Wall -c -fmessage-length=0 -ffreestanding -m64 -nostdlib -mno-red-zone -Map=out.map -MMD -MP -MF"srcOriginal/main.d" -MT"srcOriginal/main.d" -o "srcOriginal/main.o" "../srcOriginal/

The link script is

Code: Select all

ENTRY(start)
SECTIONS
{

    .text 0x100000 :
    {
        code = .; _code = .; __code = .;
        *(.text)
        . = ALIGN(4096);
    }

    .data :
    {
        data = .; _data = .; __data = .;
        *(.data)
        *(.rodata)
        . = ALIGN(4096);
    }

    .bss :
    {
        bss = .; _bss = .; __bss = .;
        *(.bss)
        . = ALIGN(4096);
    }

    end = .; _end = .; __end = .;
}
If there is anything else that would be useful, I can easily add it.

Thanks!

Re: Confused Noob - why is the value not being set?

Posted: Thu Dec 20, 2012 5:05 pm
by dozniak
You're not handling the case

Code: Select all

tmp = (n >> 0) & 0xF;

Re: Confused Noob - why is the value not being set?

Posted: Fri Dec 21, 2012 3:38 am
by nigelren
I've stripped the code down even further to avoid anything else potentially interfering.

Code: Select all

// main.c -- Defines the C-code kernel entry point, calls initialisation routines.
//           Made for JamesM's tutorials <www.jamesmolloy.co.uk>

#include "monitor.h"
#include "multiboot.h"
//#include "console.h"

u8int cursor_x1 = 1;

int main(struct multiboot_info *mboot_ptr)
{
        // u8int cursor_x1 = 1;  // It works if I use this variable instead

	u16int *video = (u16int *)0xB8000;
	video[0] = (cursor_x1+'0') + (0x1e << 8);
	cursor_x1++;
	video = (u16int *)0xB8000+80;
	video[0] = (cursor_x1+'0') + (0x1e << 8);

   return 0;
}

This still only displays the value as being 0 and 0.
If I put the declaration of cursor_x1 as a local variable for main - it displays 1 & 2 - which shows the display is working correctly.

Re: Confused Noob - why is the value not being set?

Posted: Fri Dec 21, 2012 3:44 am
by bluemoon
objdump and see what's the actual code for "global variable version" and where it want to access.
video[0] = (cursor_x1+'0') + (0x1e << 8);
Note the datatype remain as uint8_t on the RHS, a sane compiler should generate an overflow warning.
gcc -I/usr/src/linux-headers-3.2.0-33 ...
By the way, this is not a good idea to drag the monster into your OS, you never know if it feel like injecting any static object to your kernel.

Re: Confused Noob - why is the value not being set?

Posted: Fri Dec 21, 2012 7:28 am
by Gigasoft
video[0] = (cursor_x1+'0') + (0x1e << 8) ;
Note the datatype remain as uint8_t on the RHS, a sane compiler should generate an overflow warning.
No, '0' is an int, so cursor_x1 is promoted to int. 0x1e and 8 are also ints. The result of the calculation is an int ranging from 0x1e30 to 0x1f2f, so there can't be an overflow. Or if this was C++, we would have an int ranging from 0x1e00 to 0x1eff.

Re: Confused Noob - why is the value not being set?

Posted: Fri Dec 21, 2012 7:34 am
by bluemoon
or it can be promoted to unsigned int and give you surprise, anyway that is not a cool coding style.

Re: Confused Noob - why is the value not being set?

Posted: Sat Dec 22, 2012 11:36 am
by nigelren
I managed to find that it was loading the .data section at 101000, and the hex dump looked 'right' ( i.e. the values I was expecting to see - were there ).
I still couldn't get the values to work - and it all seems to do with being a 64bit executable. I've changed back to 32 bit and it all seems to work OK.
I'm using grub2 to load the executable - is there an example set of code somewhere which I can read through to work out what I might be doing wrong.

Re: Confused Noob - why is the value not being set?

Posted: Mon Dec 24, 2012 4:56 pm
by Combuster
I suggest you compile yourself a copy of bochs+debugger, and go single step through the code to see what the effective differences are.