Unable to call a C-Function after task switch
Unable to call a C-Function after task switch
Hi,
I just implemented Multitasking in my os and it works .. But there is a big problem left ..
I can't use any C-Functions .. If I do that, it crashs with a general protection fault :/
inline asm works fine .. now I have a operating system, which beeps all the time (with outb) but
can't do anything else
Any Idea?
I just implemented Multitasking in my os and it works .. But there is a big problem left ..
I can't use any C-Functions .. If I do that, it crashs with a general protection fault :/
inline asm works fine .. now I have a operating system, which beeps all the time (with outb) but
can't do anything else
Any Idea?
- NickJohnson
- Member
- Posts: 1249
- Joined: Tue Mar 24, 2009 8:11 pm
- Location: Sunnyvale, California
Re: Unable to call a C-Function after task switch
Is your stack in a reasonable state after the task switch? Inline assembly doesn't always use the stack, but C functions do.
Re: Unable to call a C-Function after task switch
hmm.. it's working in QEmu .. But VMWare 8 shows a panic :/
My Task Switch looks like this:
this returns the cpu registers of the next task ..
And struct regs looks like this:
Any Idea?
Edit:
I have printed the registers before and after the switch ..
As I am a beginner, here is what i have noticed.
Isn't fs a 16 bit register? why is fs so high in vmware? And why does it work fine in Qemu?
What could be the problem?
btw .. it doesn't work in vmware neither on a real pc
My Task Switch looks like this:
Code: Select all
extern _irq_handler
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push esp
call _irq_handler
mov esp, eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret
Code: Select all
struct regs* irq_handler(struct regs *r)
{
struct regs* new_cpu = r;
/* ... */
if (r->int_no == 0x20) {
new_cpu = schedule(r);
}
/*... */
return new_cpu;
}
Code: Select all
struct regs
{
unsigned int gs, fs, es, ds;
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
unsigned int int_no, err_code;
unsigned int eip, cs, eflags, useresp, ss;
};
Edit:
I have printed the registers before and after the switch ..
As I am a beginner, here is what i have noticed.
Isn't fs a 16 bit register? why is fs so high in vmware? And why does it work fine in Qemu?
What could be the problem?
btw .. it doesn't work in vmware neither on a real pc
- thepowersgang
- Member
- Posts: 734
- Joined: Tue Dec 25, 2007 6:03 am
- Libera.chat IRC: thePowersGang
- Location: Perth, Western Australia
- Contact:
Re: Unable to call a C-Function after task switch
As I noted in your other thread, you didn't quite get the idea of cdecl. Parameters are passed on the stack in reverse order (going upwards - return address, param1, param2)
Parameters also need to be removed by the caller, not the callee. You don't do this after calling the irq handler, so the your state restore fails.
Parameters also need to be removed by the caller, not the callee. You don't do this after calling the irq handler, so the your state restore fails.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Re: Unable to call a C-Function after task switch
hmm .. ok .. I'm still learning
correct code would be:
this would fix the first problem, right?
2.
for
i need to pop 19 times, right?
Could you tell me if I'm getting closer or completely wrong?
thx
Am I right that I forgot to pop the esp again?Parameters are passed on the stack in reverse order (going upwards - return address, param1, param2)
correct code would be:
Code: Select all
extern _irq_handler
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push esp
call _irq_handler
pop esp
mov esp, eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret
2.
Hmm.. so I need to pop the stack items pushed by the c-function? (I mean the return struct)Parameters also need to be removed by the caller, not the callee. You don't do this after calling the irq handler, so the your state restore fails.
for
Code: Select all
struct regs
{
unsigned int gs, fs, es, ds;
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
unsigned int int_no, err_code;
unsigned int eip, cs, eflags, useresp, ss;
};
Could you tell me if I'm getting closer or completely wrong?
thx
- thepowersgang
- Member
- Posts: 734
- Joined: Tue Dec 25, 2007 6:03 am
- Libera.chat IRC: thePowersGang
- Location: Perth, Western Australia
- Contact:
Re: Unable to call a C-Function after task switch
Your first part was right (but only on a technicality, because doing "pop esp" is in most cases a bad idea) However, you do not need to care about what the C function does with the stack, only that it will return to the stack pointer to the same value as when it was called.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Re: Unable to call a C-Function after task switch
OK, what should I pop in then? ebx?
What I don't really understand is, what happens to the stack pointer?
What do I have to do with it after the call ?
source would look like this atm:
hmpf :/
Edit:
OK, i found this: http://www.cs.umbc.edu/~chang/cs313.s02/stack.shtml
So, do I need to pop the struct from the esp by doing "add esp, [num of bytes]"?
With the struct of 19 ints I would do a "add esp, 76" ?
I'm a little clueless right now :/
What I don't really understand is, what happens to the stack pointer?
What do I have to do with it after the call ?
source would look like this atm:
Code: Select all
extern _irq_handler
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push esp
call _irq_handler
pop ebx
mov esp, eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret
Edit:
OK, i found this: http://www.cs.umbc.edu/~chang/cs313.s02/stack.shtml
So, do I need to pop the struct from the esp by doing "add esp, [num of bytes]"?
With the struct of 19 ints I would do a "add esp, 76" ?
I'm a little clueless right now :/
Re: Unable to call a C-Function after task switch
You don't have to pop the values from stack individually because you no longer need them. You simply reset the stack pointer to the value it had before you started pushing values to it for the function call.
Every good solution is obvious once you've found it.
Re: Unable to call a C-Function after task switch
Hell yeah, it works
I just forgot to init variables in the struct
Thx guys for helping me
If somebody is interested in my solution, here are some pieces ..
irq stub inside my asm file:
The timer handler (fired by pic) calls a simple scheduling function
and returns the registers of the next task (in a struct):
The Struct looks like this:
thx anyone
I just forgot to init variables in the struct
Thx guys for helping me
If somebody is interested in my solution, here are some pieces ..
irq stub inside my asm file:
Code: Select all
extern _irq_handler
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push esp
call _irq_handler
mov esp, eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret
Code: Select all
struct regs* irq_handler(struct regs *r) {
/* ... */
struct regs* new_cpu = r;
new_cpu = schedule(r);
/* ... */
return new_cpu;
}
The Struct looks like this:
Code: Select all
struct regs
{
unsigned int gs, fs, es, ds;
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
unsigned int int_no, err_code;
unsigned int eip, cs, eflags, useresp, ss;
};