Page 1 of 1

Beginner Problem with executing functions

Posted: Fri Jul 16, 2010 7:52 am
by Ameise
Having an odd problem - haven't done a disassembly yet because I'm simply not good at it, but if I must then I will.

Basically, if I do this, it works fine:

Code: Select all

static char * sVideoAddress = 0x000b8000;

__declspec(noreturn)
	void kernel::boot::kloader (multiboot::multiboot_info *multibootheader, unsigned long signature)
{
	char *addr = (char*)sVideoAddress;
	for (int i = 0; i < 80 * 25 * 2; ++i)
		*addr++ = 0;

	__asm { hlt }
}
If I do this, it fails (no rendering done):

Code: Select all

static char * sVideoAddress = 0x000b8000;

void * memset (void *dst, int val, int len)
{
	char *dest = (char*)dst;
	for (int i = 0; i < len; ++i)
		*dest++ = val;
	return dst;
}

void cls ()
{
	memset(sVideoAddress, 0, 80 * 25 * 2);
}

__declspec(noreturn)
	void kernel::boot::kloader (multiboot::multiboot_info *multibootheader, unsigned long signature)
{
	cls();
}
Any thoughts as to why? This is a PE binary with a multiboot header.

Re: Beginner Problem with executing functions

Posted: Fri Jul 16, 2010 10:05 am
by blobmiester
First off, you need to be a bit more specific when asking questions:
  • Is that all the code?
  • Is there another loader that gets called first? Are you setting up in the stack in this loader (if not you need to be)?
  • What compiler are you using (though I think I can tell it's Visual C++, the less the person responding needs to think about it - the more likely they are to answer)?
Now, to answer your question: I don't have any clue as to why simply adding two functions in the source file (that aren't being called) would fail (another thing, how does it fail? Any helpful error messages?).

The only thing I can suggest is have you read the wiki on Visual C++? There are a ton of settings that need to be changed in order for a kernel to be loaded right.

One last thing: How are you booting your kernel? Custom, grub, ... ?

Re: Beginner Problem with executing functions

Posted: Fri Jul 16, 2010 11:05 am
by Ameise
My computer isn't with me, so I can't post source, but I will when I get home.

There is a true entry point that starts with the multiboot loader (same as any tutorial). There are other source files that ARE compiled, but they aren't referenced and just take up code space.

Visual Studio 2010 / C++ would be the compiler that I'm using, and the project SHOULD be set up properly. By failing, it doesn't clear the screen. Can't tell if it's actually died or not... it doesn't clear the GRUB screen, I continuously see 'Starting Kernel' or so.

The stack appears to be set up, as it is in one of the tutorials,

Code: Select all

__declspec(naked) void __multiboot_entry__(void)
{
          __asm {
          
          multiboot_header:
                    dd(0x1BADB002)               ; magic
                    dd(1 << 16)                    ; flags
                    dd(-(0x1BADB002 + (1 << 16)))     ; checksum
                    dd(0x00101000)               ; header_addr
                    dd(0x00101000)               ; load_addr
                    dd(0x0010200F)               ; load_end_addr
                    dd(0x0010200F)               ; bss_end_addr
                    dd(0x00101030)               ; entry_addr
                    dd(0x00000000)               ; mode_type
                    dd(0x00000000)               ; width
                    dd(0x00000000)               ; height
                    dd(0x00000000)               ; depth

          kernel_entry:
                    mov     esp,     KERNEL_STACK

                    xor     ecx,     ecx
                    push     ecx
                    popf

                    push     eax
                    push     ebx
                    call     kernel::boot::kloader

                    jmp     $
          }
}
is fairly equivalent to my header.


An odd thing to note is that other times, when I had fewer/different functions in my source files, it would work, even calling functions. Then I add one more function, and it fails. The file itself, compiled, is 12KiB.


I also made a mistake on the code above... second block should be

Code: Select all

static char * sVideoAddress = 0x000b8000;

void * memset (void *dst, int val, int len)
{
	char *dest = (char*)dst;
	for (int i = 0; i < len; ++i)
		*dest++ = val;
	return dst;
}

void cls ()
{
	memset(sVideoAddress, 0, 80 * 25 * 2);
}

__declspec(noreturn)
	void kernel::boot::kloader (multiboot::multiboot_info *multibootheader, unsigned long signature)
{
	cls();
}
I left out the cls() call. And if I put the clearing loop after cls(), it still fails.

Re: Beginner Problem with executing functions

Posted: Fri Jul 16, 2010 4:01 pm
by neon
Hello,

Your multiboot header structure looks weird. header address is same as load address; entry point hard coded; adding additional functions can move these addresses around. I am not aware of what tutorial you used but this doesnt look right.

Re: Beginner Problem with executing functions

Posted: Fri Jul 16, 2010 6:02 pm
by Ameise

Re: Beginner Problem with executing functions

Posted: Sat Jul 17, 2010 9:56 am
by neon
Hello,

May I suggest trying the method outlined in this thread? I use a variant of this method and never ran into issues.

Re: Beginner Problem with executing functions

Posted: Sat Jul 17, 2010 10:48 am
by Ameise
What guarantees that it will be at the beginning of the .text segment, and some other variable won't be put before it?

Re: Beginner Problem with executing functions

Posted: Sat Jul 17, 2010 10:56 am
by neon
Hello,

Its a little tricky. You should know how section naming works in MSVC to better understand how it works. The section name (.a$0) is what guarantees that its before .text, please see the 6th post for info.

Re: Beginner Problem with executing functions

Posted: Mon Jul 19, 2010 6:26 am
by Fanael
You can also place the multiboot header inside MZ header, it's toolchain-independent (but somewhat hackish instead ;)) and works fine (at least for me ;)).

Sorry for self-advertisement ;)