Page 1 of 2

Weird Problem

Posted: Sat Dec 10, 2005 12:00 am
by alsig
I?ve a very simple system with a very weird problem.

When I run my kernel in VMWare with the ?for?-loop excluded the system stalls. It doesn't reset or triple-faults, it just hangs. It writes "Hello" and hangs.
If I include the "for"-loop it write "Hello", my cpu name and "Done!".
I?ve also included my startup file, lnker script and the implementation of ?get_cpu_id?.

My main:

Code: Select all

int main()
{
  int max_cpuid_call,i;
  unsigned char cpu_sign[13];
 
  init_video();
  printf("Hello\n");
	
  //for(i = 0; i < strlen(cpu_sign); i++)
  //cpu_sign[i]= 0;
	
  max_cpuid_call = get_cpu_id(cpu_sign);
  cpu_sign[13] = 0;
  printf("%s\n",cpu_sign);
  printf("Done!");
  for (;;);
  return 0;
}
My linker script

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    . = ALIGN(4096);
  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    . = ALIGN(4096);
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(COMMON)
	*(.bss)
    . = ALIGN(4096);
	bss_end = .;
  }
  end = .;
}
My startup code:

Code: Select all

    ; Switches gdt's
	lgdt [gdt_ptr]

	mov ax,LINEAR_DATA_SEL
	mov ds,ax
	mov es,ax
	mov ss,ax
	mov fs,ax
	mov gs,ax
	jmp LINEAR_CODE_SEL:sbat
sbat:
	
	EXTERN bss, bss_end
	mov edi,bss
	mov ecx,bss_end
	sub ecx,edi
	xor eax,eax
	rep stosb

	mov esp,_sys_stack

	call _main
    jmp $
My implementation of "get_cpu_id"

Code: Select all

	push ebp
	mov	 ebp, esp
	xor	eax,eax
	cpuid
	push eax
	mov	eax, [ebp + 8]
	mov DWORD [eax],     ebx
	mov DWORD [eax + 4], edx
	mov DWORD [eax + 8], ecx
	pop	eax
	pop	ebp
	ret
[/code]

Re: Weird Problem

Posted: Sat Dec 10, 2005 12:00 am
by dave
There is nothing wierd about what is happening. You boot code has an endless loop in it ( jmp $ ). When you call you "main" it pushes the return address on the stack so main has somewhere to return too. Which in this case is jmp $. This cause your computer to endlessly loop on this jmp instruction.

dave

Re: Weird Problem

Posted: Sat Dec 10, 2005 12:00 am
by alsig
That isn't my problem...
My problem is that I have to include the "for"-loop to be able to print the "cpu_sign" variable.
If I exclude the "for"-loop my kernel hangs right after the "Hello"-printf.

Regards
Jens Alsig

Re: Weird Problem

Posted: Sat Dec 10, 2005 12:00 am
by bluecode
hi,

how did you declare get_cpu_id()? Normally your compiler would just push a pointer on the stack and not the whole structure. If so you might be trashing your stack within your get_cpu_id() function...

have fun ;)

Re: Weird Problem

Posted: Sun Dec 11, 2005 12:00 am
by alsig
how did you declare get_cpu_id()
I declared my get_cpu_id like this:

Code: Select all

extern unsigned int get_cpu_id(unsigned char *string); 
Regards
Jens Alsig

Re: Weird Problem

Posted: Sun Dec 11, 2005 12:00 am
by deadmutex
how is get_cpu_id() defined?

Edit:
oops, I didn't see where it was...

Re: Weird Problem

Posted: Mon Dec 12, 2005 12:00 am
by Da_Maestro
Your problem is that you are trying to determine the length of an uninitialised string.

Instead of:

Code: Select all

 for(i = 0; i < strlen(cpu_sign); i++) 
use:

Code: Select all

 
#define CPU_SIGN_LEN    13
...
unsigned char cpu_sign[CPU_SIGN_LEN];
...
for(i = 0; i < CPU_SIGN_LEN; i++ )
strlen will scan the string until it finds the null terminator character...if there isn't one it will keep going forever. Thusly you must initialise the string at a known length first.

Adam

Re: Weird Problem

Posted: Mon Dec 12, 2005 12:00 am
by alsig
Hi everybody.

I just read my first post and there were a BIG error....

My problem is that I HAVE to include the "for"-loop to get my kernel to run!

Sorry, for the trouble!

Just to clarify my problem is the following:

If I include the "for"-loop the kernel works (strlen or const value).
If I exclude the "for"-loop the kernel stalls at the function call "get_cpu_id".

I have done a bit of debugging and it seems that I mess up my stack in the "get_cpu_id" function.
If I modify the function so that I only pushes and pops "ebp" the kernel works (No cpu id though)
If I pushes and pops two values (ebp and ex. eax) the kernels stalls!

Regards Jens Alsig

Re: Weird Problem

Posted: Mon Dec 12, 2005 12:00 am
by Da_Maestro
Let me get this straight....if you include the for loop...the code works..yes?


Then just include the for loop...problem solved :-p

Adam

Re: Weird Problem

Posted: Tue Dec 13, 2005 12:00 am
by alsig
Let me get this straight....if you include the for loop...the code works..yes?
Jep!
Then just include the for loop...problem solved :-p
Nope ;) That isn't a option! I have to know why ;)

Regards Jens Alsig

Re: Weird Problem

Posted: Tue Dec 13, 2005 12:00 am
by Da_Maestro
Beats me

Try single stepping your code in Bochs. I know it's painfull to do but it has to be done sometimes.

TIP: Learn how to place breakpoints in the code. Getting nasm to disassemble the kernel image directly will help with this. Good luck!

Adam

Re: Weird Problem

Posted: Wed Dec 14, 2005 12:00 am
by mrd
ok buddy. strlen(cpu_sign) when cpu_sign is unitialized string = asking for trouble. who knows where you're writing zeroes to in that for loop.
cpu_sign[13] = 0 once again you're writing outside the bounds of the array. you declared it 13 bytes long, and you're referencing the 14th byte.

get_cpu_id() fills the first 12 bytes of the array, and the 13th is left untouched. it's possible whatever random value is in this position is causing printf() to crash..

other than that, i'd ensure your final image is linked properly and all generated addresses are accurate.

Re: Weird Problem

Posted: Wed Dec 14, 2005 12:00 am
by Da_Maestro
You know that correct programming practices should call for ALL variables to be properly initialised. This is just plain common sense!

Yes strlen is a BIG no-no on an uninitialised string. The code that I suggested with the #define defining the length is good programming practice for 3 reasons:
1. You can now change the length of that string by just changing one number (maintainability).
2. The length is consistent throughout the entire program now
3. The string is properly initialised.

Sorry dude, but it looks like leaving the for loop in there is your best option. Either that, or you can initialise the string statically by declaring it like this:

Code: Select all

unsigned char cpu_sign[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
I don't know if that is the correct syntax (if anyone wants to correct me feel free to do so) but you get the idea of what I'm doing I hope.

In future peoples, always initialise every variable in your code. Otherwise you run into all sorts of troubles including:
1. Bugs that are not obvious
2. Security issues
3. Code that is not maintainable

'Nuff said.

Adam

Re: Weird Problem

Posted: Wed Dec 14, 2005 12:00 am
by Da_Maestro
oh and one other thing....null terminators are needed in C-style strings. Your "get_cpu_id" method forgets to do that

Re: Weird Problem

Posted: Fri Dec 16, 2005 12:00 am
by mrd
Da_Maestro wrote:

Code: Select all

unsigned char cpu_sign[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
you don't need all that..

Code: Select all

unsigned char cpu_sign[13] = {0};
this will initialize the entire array to zero.
Da_Maestro wrote:In future peoples, always initialise every variable in your code.
initializing every variable will increase the size of your image and your footprint. you can safely utilize uninitialized variables if you are careful in your code. however, it's a good rule for beginners or if you don't want to spend the time to optimize.
Da_Maestro wrote:oh and one other thing....null terminators are needed in C-style strings. Your "get_cpu_id" method forgets to do that
this is a great point. although in your code you add the null char after the call, you should get in the habit of writing your code to be portable. if your function fills a text buffer, it should either null terminate or return the length of the string.