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.
typedef struct task_t
{
int pid; // task id
unsigned int stack; // stack of the task
unsigned char state; // is task alive?
void (*thread_start)(void); // a pointer to the first function that will executed (eip) in the task
struct task_t *next; // pointer to the next task
} task_t;
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
I think your problem lies in the popa(d) instruction.
eXeCuTeR wrote:
unsigned int i = 0;
for(;i<8;i++) // pusha = 0
*--stack = 0;
You set everything to 0. If you execute the popa(d) instruction you overwrite esp with 0.
This is just a guess, but that is the only thing I can think of for now.
cyr1x wrote:I think your problem lies in the popa(d) instruction.
eXeCuTeR wrote:
unsigned int i = 0;
for(;i<8;i++) // pusha = 0
*--stack = 0;
You set everything to 0. If you execute the popa(d) instruction you overwrite esp with 0.
This is just a guess, but that is the only thing I can think of for now.
nope, this is not the problem, thanks anyways.
how do you i use the bochs debugger then guys?
I'm trying to implement multitasking. I read about software-trask switching. As I understand current eip value needs be stored and new eip value needs be loaded. I'm writing according to BrokenThorn.com tutorial, that is written in MSVC++. I tried to use that asm (ex.: _asm mov eax, eip) and got an error: eip - unknown symbol. Something like this. So, if anyone know, what need I do?
Thanks.
Don't think a ****, but in ukrainian schools English is TOO BAD!
djsilence wrote:I tried to use that asm (ex.: _asm mov eax, eip) and got an error: eip - unknown symbol. Something like this. So, if anyone know, what need I do?
You can't access the EIP register like any other general purpose register. I suggest you to check how interrupts are working and the IRET instruction (especially their effect on the stack) and after that you can easily figure out how you can change the value of EIP.
cd iodev && \
make libiodev.a
make[1]: Entering directory `/home/executer/Desktop/bochs-20090111/iodev'
g++ -c -I.. -I./.. -I../instrument/stubs -I./../instrument/stubs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES devices.cc -o devices.o
../instrument/stubs/instrument.h: In member function ‘void bx_devices_c::outp(Bit16u, Bit32u, unsigned int)’:
../instrument/stubs/instrument.h:97: error: too many arguments to function ‘void bx_instr_outp(Bit16u, unsigned int)’
devices.cc:958: error: at this point in file
make[1]: *** [devices.o] Error 1
make[1]: Leaving directory `/home/executer/Desktop/bochs-20090111/iodev'
make: *** [iodev/libiodev.a] Error 2
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
global writeto_cr3
writeto_cr3:
mov eax, [esp+4]
mov cr3, eax
ret
global or_cr0
or_cr0:
mov eax, cr0
or eax, 0x80000000
mov cr0, eax
ret
global readfrom_cr2 ; for page faults
readfrom_cr2:
mov eax, cr2
ret
and my current code (i just copied this code now for a tutorial because im so exhausted =[)
#include "task.h"
#include "mm.h"
#include "screen.h"
#include "hardware.h"
typedef struct{ //Simple structure for a thread
unsigned int esp0; //Stack for kernel
unsigned int esp3; //Stack for process
} Thread;
Thread Threads[2]; //Space for our simple threads. Just 2!
int CurrentTask = -1; //The thread currenlty running (-1 == none)
int first = 0;
void initialize_multitasking(void)
{
CreateTask(0, idle);
CreateTask(1, idle);
unsigned int divisor = 1193180 / 50;
outport(0x43, 0x36);
outport(0x40, divisor & 0xFF);
outport(0x40, (divisor >> 8) & 0xFF);
outport(0x21, 0x00); // enable interrupts from IRQ 0-7 (PIT will now start working)
}
void idle()
{
puts("IDLE");
for(;;) ;
}
void idle2()
{
puts("idle");
for(;;) ;
}
//This will create a task
//It will make a stack that looks like it has all
//of the stuff of an IRQ handler 'pushed' on it
void CreateTask(int id, void (*thread)()){
unsigned int *stack;
Threads[id].esp0 = (unsigned int)malloc(0x1000) + 4096; //This allocates 4kb of memory, then puts the pointer at the end of it
stack = (unsigned int* )Threads[id].esp0; //This makes a pointer to the stack for us
//First, this stuff is pushed by the processor
*--stack = 0;
*--stack = 0;
*--stack = 0x0202; //This is EFLAGS
*--stack = 0x08; //This is CS, our code segment
*--stack = (unsigned int)thread; //This is EIP
//Next, the stuff pushed by 'pusha'
*--stack = 0; //EDI
*--stack = 0; //ESI
*--stack = 0; //EBP
*--stack = 0; //Just an offset, no value
*--stack = 0; //EBX
*--stack = 0; //EDX
*--stack = 0; //ECX
*--stack = 0; //EAX
//Now these are the data segments pushed by the IRQ handler
*--stack = 0x10; //DS
*--stack = 0x10; //ES
*--stack = 0x10; //FS
*--stack = 0x10; //GS
Threads[id].esp0 = (unsigned int)stack; //Update the stack pointer
}
//Switch between our two tasks
//Notice how we get the old esp from the ASM code
//It's not a pointer, but we actually get the ESP value
//That way we can save it in our task structure
int TaskSwitch(unsigned int OldEsp){
if(CurrentTask != -1){ //Were we even running a task?
Threads[CurrentTask].esp0 = OldEsp; //Save the new esp for the thread
//Now switch what task we're on
if(CurrentTask == 0) CurrentTask = 1;
else CurrentTask = 0;
} else{
CurrentTask = 0; //We just started multi-tasking, start with task 0
}
unsigned int a = Threads[CurrentTask].esp0;
outport(0x20, 0x20);
// return a;
return OldEsp; //Return new stack pointer to ASM
}