How to setup the stack?

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.
Post Reply
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

How to setup the stack?

Post by pcmattman »

I've run into a problem in my multitasker... whenever I create a process, it never returns (and with the current design, doing so causes exceptions). The problem is, I would like others to write their processes as though they are just functions.

At the moment, a process must do this (note that Yield is just basically resetting the processes timeslice, my multitasker is preemptive):

Code: Select all

void MyProcess()
{
	printf( "Hello World!" );

	while( true ) { Yield(); };
}
I want to be able to do this:

Code: Select all

void MyProcess()
{
	printf( "Hello World!" );
}
The multitasker sets up the stack like so:

Code: Select all

*stackSpace-- = (unsigned int) &procret;
Unfortunately, whenever a process tries to return it crashes with an "Invalid Opcode" error. I'm assuming this means that the process stack isn't setup right.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: How to setup the stack?

Post by Brendan »

Hi,
pcmattman wrote:Unfortunately, whenever a process tries to return it crashes with an "Invalid Opcode" error. I'm assuming this means that the process stack isn't setup right.
You can't "return" unless there's something to return to.... ;)

Normally for C there's a run time library, with something like this:

Code: Select all

void STARTUP_ENTRY_POINT(char *commandLineString) {
    int argc;
    char *argv[];
    int status;

    parseCommandLine(&argc, &argv);
    status = main(argc, argv);
    exit(status);
}
This means when "main()" returns it returns to the C library, and the C library calls some function to terminate the task (which never returns, as the task is terminated).

Of course the code above is just an example - someone who is more familiar with C would have a better idea of what is actually in the C library's startup code. I can imagine a collection of OS dependant things, like setting up STDIN, STDOUT and STDERR, initialising the heap, installing default signal handlers, etc.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

I suspect that the Yield() is corrupting your stack. Can you put the code for this function/procedure?

I recommend reading the value of ESP at the beginning of each of the processes' code and print it to the screen and do the same BEFORE the procedure is about to exit.
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

When I set up my stack for my tasks I push the value of a Exit_Task function onto the stack. When the task finally returns it returns the to Exit_Task function which kills the task. This way I don't have to worry about calling Exit_Task from the task and there is no way the task could return to bogus memory.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

That's what I'm trying to do at the moment, I just don't know how to push that onto the stack :(
User avatar
carbonBased
Member
Member
Posts: 382
Joined: Sat Nov 20, 2004 12:00 am
Location: Wellesley, Ontario, Canada
Contact:

Post by carbonBased »

pcmattman wrote:That's what I'm trying to do at the moment, I just don't know how to push that onto the stack :(
Uhm... well... you would have created the stack for the task, so just write to it!

I find its easier (and more scalable) to simply have a common entry for all tasks, which accepts, as parameters, the user task entry function, and a parameter for it, as well, perhaps (similar to Brendan's suggestion):

Code: Select all

void commonEntry(void (*userEntry)(void*), void *param)
{
  // do all your initialization here
  userEntry(param);
  // do all your task clean up here
}
--Jeff
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

That's a really good idea...

I did create the stack, I did try to write to it but it didn't work... If you had read my first post I'm sure I put the stack writing code there...

Either way, your idea sounds much better because I can (finally) send arguments to processes :D.

Edit: would it work to move the process stack address into ESP, then execute push instructions, then restore the old ESP value?
Post Reply