memory problem

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.
Zottri

memory problem

Post by Zottri »

I have a weird problem.

I want to initialize my MemoryMap variable, but it stacks in loop and executes loop infinitelly. I think Im missing something with memory references. ıll be if someone helps..

Here is my code:

Code: Select all

/*********************************************************
/ VARIABLE DECLERATION
*********************************************************/
static unsigned long MemoryMap[MAXPAGENUMBER/32];  //1bit/page
static unsigned long SystemTotalMemory;
static unsigned long SystemTotalPageNumber;
static unsigned long CurrentFreePageNo;

/*********************************************************
/ FUNCTION IMPLEMENTATIONS
*********************************************************/
/*********************************************************
/ Initialising memory
/ in    : None
/ out   : None
*********************************************************/
void InitMemory(void)
{
    unsigned long Cnt;

    SystemTotalMemory = GetMemorySize();
    if(SystemTotalMemory > MAXMEMORY) SystemTotalMemory = MAXMEMORY;

    SystemTotalPageNumber = SystemTotalMemory / PAGESIZE;

    for(Cnt = 0; Cnt < 4096; Cnt++)         //this loop never ends
        MemoryMap[Cnt] = (unsigned long)0;

    CurrentFreePageNo = 0;
}

BoomSukka

Re:memory problem

Post by BoomSukka »

It seems impossible that a FOR loop doesn't end when it's initial and terminal conditions are properly defined, which yours are.

So, in my opinion, you're surpassing the bounds of your MemoryMap[] array (i.e. you don't have 4096 elements in the array) -- and therefore you're writing zeros god-knows-where...

Tim.
Schol-R-LEA

Re:memory problem

Post by Schol-R-LEA »

I agree; the solution I would recommend is to replace the hardcoded '4096' with 'MAXPAGENUMBER/32', or better still, define another constant of that value and use it in both cases:

Code: Select all

#define MAXPAGEBYTES (MAXPAGENUMBER/32)

static unsigned long MemoryMap[MAXPAGEBYTES];  //1bit/page


//....

    for(Cnt = 0; Cnt < MAXPAGEBYTES; Cnt++)        //this loop never ends
        MemoryMap[Cnt] = (unsigned long)0;
HTH.
Zottri

Re:memory problem

Post by Zottri »

Indeed I have tried both you said. Either replacing both definitions with 4096 nor (MAXPAGENUMBER/32) worked. I mean both the codes results in an infinite loop. Also I have tried printing a char in that loop and it prints it infinitelly. BUTT, if I change the counting number from 4096 to 4089, it exits loop successfully. (What makes this problem weird.)

And here is last condition of my code:

Code: Select all

static unsigned long MemoryMap[4096];  //1bit/page
static unsigned long SystemTotalMemory;
static unsigned long SystemTotalPageNumber;
static unsigned long CurrentFreePageNo;

void InitMemory(void)
{
    unsigned long Cnt;

    SystemTotalMemory = GetMemorySize();
    if(SystemTotalMemory > MAXMEMORY) SystemTotalMemory = MAXMEMORY;

    SystemTotalPageNumber = SystemTotalMemory / PAGESIZE;

    for(Cnt = 0; Cnt < 4096; Cnt++) {        //Set all pages free
        MemoryMap[Cnt] = (unsigned long)0;
        if((Cnt % 1024)==0) Print("#");
    }

    CurrentFreePageNo = 0;
}
This piece of code prints '#' char infinitelly. If I chage both 4096 with 4089, it finishes loop successfully. ALSO, if I declare MemoryMap variable under CurrentFreePageNo, as:

Code: Select all

static unsigned long SystemTotalMemory;
static unsigned long SystemTotalPageNumber;
static unsigned long CurrentFreePageNo;
static unsigned long MemoryMap[4096];  //1bit/page
also loop doesnt end even if I change 4096 with 4089(what couse my to think that my problem is something with memory references). Off off.. Ha, Im sure that my computer doesnt crash in loop, it just executes loop infinitelly. Because all my interrupts (keyboard, timer..) works and it prints '#' infinitelly.

What may couse this problem? Ill be glad if someone helps...Thanks...
Schol-R-LEA

Re:memory problem

Post by Schol-R-LEA »

Do you have a function for printing numbers, moving the cursor, and finding the cursor's position? If so, then you could try something like this to help see what the Cnt function is actually doing without take inordinate screen space:

Code: Select all

int xpos = 0;
int ypos = 0;
// ...

    Print("Now clearing memory map section #");
    xpos = get_x();
    ypos = get_y();
    for(Cnt = 0; Cnt < 4096; Cnt++) {        // Set all pages free
        MemoryMap[Cnt] = (unsigned long) 0;

        // print out counter value periodically for debugging purposes
        if (Cnt % 16)  {                    // set granularity as needed for testing
            move_cursor(xpos, ypos);        // return cursor to start position of counter
            Print_Decimal(Cnt);
         }
    }
You would have to replace these functions with your own equivalents, of course. The effect should be an in-place counter, like the memory test counter on older PCs (newer ones usually have it, but it's disabled by default).

BTW, you might want to wrap these test operations in a macro
like this one, so that you can select or deselect them at compile time:

Code: Select all

#define __DEBUG__ 1
#if __DEBUG__
#define DEBUG(x) {x}
#elif
#define DEBUG(x)
#endif
A more sophisticated version of this would be a 'verbose' or 'logging' mode which can be enabled or disabled by an initialization script, which could allow you to show this and other system startup information.
zottri

Re:memory problem

Post by zottri »

I printed out the value of Cnt. I counts normally until 4086. And then restarts counting:
..
4083
4084
4085
4086
0
1
2
3
..
Also, if I declare some variables before declaring Cnt, it counts less then 4086 and restarts counting. I mean if I declare some other variables before Cnt:

Code: Select all

void InitMemory(void)
{
    unsigned int dummyVar1;
    unsigned int dummyVar2;
    unsigned int dummyVar3;

    unsigned long Cnts;
then screen is like this:
..
4082
4083
0
1
2
..

I think, but dont know how, my memory map variable (MemoryMap[4096]) share same memory location with my Cnt variable. Because, If I fill my MemoryMap array with, for instance, 50, then Cnt value changes like this:
..
4083
4084
4085
4086
50
51
52
..

How this may happen? I compile and run my code under different computers and they gave same results. So my fool computer works fine. But my brain leave me alone. Please help before I got crazy.. What may couse such a problem?
Schol-R-LEA

Re:memory problem

Post by Schol-R-LEA »

I don't like the sound of that; since Cnt is a local variable, it implies that the stack is getting so low that it is overlapping your data area (I am assuming that this is running in flat mode, since gcc doesn't like any other memory models :).) How are you setting up the segment selectors?

BTW, why do you need to cast 0 to (unsigned long)? I hadn't notced that earlier, but I can't see why it woul dbe necessary. It isn't as if you are assigning an integer to a pointer.
zottri

Re:memory problem

Post by zottri »

Schol-R-LEA wrote: How are you setting up the segment selectors?
What do u mean and how can I do that?
(My english is not so good, sorry.)
Schol-R-LEA

Re:memory problem

Post by Schol-R-LEA »

EDIT: I should clarify what I wrote earlier.

I ran some tests with a mockup of you code, and it worked exactly as intended, more or less. Whatever the problem is, it probably isn't in the InitMemory() function itself. This supports my conjecture that it is some kind of problem with the system environment which is causing you data segment to overlap with you stack.

In testing, I found another possible problem, one which is probably unrelated but nonntheless probably should be addressed.

In you current setup, is the MAXMEMORY constant set to 4294967296 (2[sup]32[/sup]) or to 4294967295 (2[sup]32[/sup] - 1)? Either one will cause a problem, but the former is more serious - a 32-bit long will overflow with that value. The result will be that the assignment

[tt]SystemTotalMemory = MAXMEMORY;[/tt]

SystemTotalMemory set to zero, not 2[sup]32[/sup].

The easiest solution is probably to use unsigned long long, a 64-bit type which gcc supports now (on a side note, there's no reason that Cnt has to be a long, in fact even an unsigned short will do nicely here). It may seem a waste of memory, but it's probably less so than the other possibilities.

The test code I used is

Code: Select all

#include <stdio.h>

/*********************************************************
/ VARIABLE DECLERATION
*********************************************************/

#define MAXMEMORY 4294967296 // 4 gigabytes
#define PAGESIZE 32768     // 32 kilobytes
#define MAXPAGENUMBER (MAXMEMORY / PAGESIZE)
#define MAXPAGEBLOCKS (MAXPAGENUMBER / 32)

static unsigned long MemoryMap[MAXPAGEBLOCKS];  //1bit/page
static unsigned long long SystemTotalMemory;
static unsigned long SystemTotalPageNumber;
static unsigned long CurrentFreePageNo;


// this function added for testing purposes
unsigned long long GetMemorySize()
{
  return (unsigned long long) MAXMEMORY;
}


/*********************************************************
/ FUNCTION IMPLEMENTATIONS
*********************************************************/
/*********************************************************
/ Initialising memory
/ in    : None
/ out  : None
*********************************************************/
void InitMemory(void)
{
    unsigned short Cnt;

    SystemTotalMemory = GetMemorySize();
    printf("%I64d\n", SystemTotalMemory);
    getch();
    if(SystemTotalMemory > (unsigned long long) MAXMEMORY) {
        SystemTotalMemory = (unsigned long long) MAXMEMORY;
    }
    SystemTotalPageNumber = (unsigned long) (SystemTotalMemory / PAGESIZE);
    
    printf("%lu\n", SystemTotalPageNumber);
    getch();
    for(Cnt = 0; Cnt < MAXPAGEBLOCKS; Cnt++) {        //this loop never ends
        MemoryMap[Cnt] = 0;
        printf("%hu\n", Cnt);
    }

    CurrentFreePageNo = 0;
}


main()
{
  InitMemory();
  getch();
}
Schol-R-LEA

Re:memory problem

Post by Schol-R-LEA »

Have you made any prograss on this, Zottri?
Zottri

Re:memory problem

Post by Zottri »

As you said, I suspect overlapping stack segment over data segment. Afer jumping to protected mode, when I set all segment registers, I set my esp to 0xffff. I changed it to 0x9ffff and my problem is solved.

Now, there is another thing confusing me. I set my gdt in my second stage loader. But it doesnt have any stack segment. I wonder if it is necessarry to set up a stack segment in gdt to avoid this kind of problems.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:memory problem

Post by Candy »

Zottri wrote: Now, there is another thing confusing me. I set my gdt in my second stage loader. But it doesnt have any stack segment. I wonder if it is necessarry to set up a stack segment in gdt to avoid this kind of problems.
a stack segment is only called a stack segment either because it contains a stack (and is in fact a normal data segment) or because it grows downwards (which might just contain data or even code). You can always use a data segment for your stack.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:memory problem

Post by Pype.Clicker »

one thing that looks suspect to me in your code is that i cannot see the definition of memorymap[]. are you sure it's long enough to hold what you put in it? is it an array or a pointer ? if it's a pointer, has it been correctly initialized ?

it looks like mmap[] overwites the (future) stack until it reaches 'counter' and resets it to 0.
Zottri

Re:memory problem

Post by Zottri »

I have found my problem. It was in my WriteCR0 functions. But now something weird occurs.
My WriteCR0 function was like this before I correct it:

Code: Select all

    mov     eax, [esp+8]
    mov     cr0, eax
    ret
And it writes wrong value in cr0. The correct one is:

Code: Select all

    push    ebp
    mov     ebp, esp
    mov     eax, [ebp+8] 
    mov     cr0, eax
    pop     ebp
    ret
Indeed I know that using esp is wrong but in tasm it gaves a compile time error. But in nasm it didnt warn me for anything and so I have thought that using esp couses no problem. But my WriteCR0 function gaves error until I change it. (Ill be glad if someone explain the difference between these codes.)

And also my WriteCR3 function, even I changed according to WriteCR0 function, works in both ways. I mean both:

Code: Select all

    mov     eax, [esp+8]
    mov     cr3, eax
    ret
and

Code: Select all

    push    ebp
    mov     ebp, esp
    mov     eax, [ebp+8] 
    mov     cr3, eax
    pop     ebp
    ret
works for writing cr3 register. Is there anything Im missing or the behave of cpu's writing cr0 or cr3 registers are different???
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:memory problem

Post by Pype.Clicker »

there's no reason for nasm to complain about mov eax,[esp+8], while it's a perfectly valid instruction.

The problem is that if you have

Code: Select all

setCR0:
   mov eax,[esp+8]
   mov cr0,eax
   ret
[esp+8] do not point to the first argument of setCR0(value), but rather to the second inexistent parameter.
Before you use [ebp+8], you pushed old ebp on the stack, which means you decreased esp ...
In other words,

Code: Select all

setCR0:
   mov eax,[esp+4]
   mov cr0,eax
would have worked perfectly (though using ebp leads to less future troubles, indeed).

The reason while CR3 seems unaffected is that the paging base directory register is less sensitive to garbage loading: as long as you give it a correct memory address it will take it as the future page table. If after calling setCR3(directory) with [esp+8], you read back CR3, you may discovery getCR3()!=directory.
But this becomes a problem *only* if you filled directory[0]... rather than *getCR3().

Did i make myself clear ?
Post Reply