Hallo,
ich schreibe auch gerade ein Betriebssystem und hänge gerade beim Multitasking.
Aus irgendeinen Grund krieg ich das Beispiel aus dem Tutorial nicht hin.
Statt As und Bs zu schreiben schreibt er nur As
Hier meine multitasking.c
#include "main.h"
int yPos = 0;
int xPos = 0;
void task_a(void)
{
while (1) {
print_string_at_pos("A", 0x02, xPos, yPos);
xPos++;
}
}
void task_b(void)
{
while (1) {
print_string_at_pos("B", 0x04, xPos, yPos);
xPos++;
}
}
static char stack_a[4096];
static char stack_b[4096];
/*
* Jeder Task braucht seinen eigenen Stack, auf dem er beliebig arbeiten kann,
* ohne dass ihm andere Tasks Dinge ueberschreiben. Ausserdem braucht ein Task
* einen Einsprungspunkt.
*/
struct cpu_state* init_task(char* stack, void* entry)
{
/*
* CPU-Zustand fuer den neuen Task festlegen
*/
struct cpu_state new_state = {
.eax = 0,
.ebx = 0,
.ecx = 0,
.edx = 0,
.esi = 0,
.edi = 0,
.ebp = 0,
//.esp = unbenutzt (kein Ring-Wechsel)
.eip = (unsigned long) entry,
/* Ring-0-Segmentregister */
.cs = 0x08,
//.ss = unbenutzt (kein Ring-Wechsel)
/* IRQs einschalten (IF = 1) */
.eflags = 0x202,
};
/*
* Den angelegten CPU-Zustand auf den Stack des Tasks kopieren, damit es am
* Ende so aussieht als waere der Task durch einen Interrupt unterbrochen
* worden. So kann man dem Interrupthandler den neuen Task unterschieben
* und er stellt einfach den neuen Prozessorzustand "wieder her".
*/
struct cpu_state* state = (void*) (stack + 4096 - sizeof(new_state));
*state = new_state;
return state;
}
static int current_task = 1;
static int num_tasks = 2;
static struct cpu_state* task_states[2];
void init_multitasking(void)
{
task_states[0] = init_task(stack_a, task_a);
task_states[1] = init_task(stack_b, task_b);
}
/*
* Gibt den Prozessorzustand des naechsten Tasks zurueck. Der aktuelle
* Prozessorzustand wird als Parameter uebergeben und gespeichert, damit er
* beim naechsten Aufruf des Tasks wiederhergestellt werden kann
*/
struct cpu_state* schedule(struct cpu_state* cpu)
{
/*
* Wenn schon ein Task laeuft, Zustand sichern. Wenn nicht, springen wir
* gerade zum ersten Mal in einen Task. Diesen Prozessorzustand brauchen
* wir spaeter nicht wieder.
*/
if (current_task >= 0) {
task_states[current_task] = cpu;
}
/*
* Naechsten Task auswaehlen. Wenn alle durch sind, geht es von vorne los
*/
if(current_task == 0)
current_task = 1;
else if(current_task == 1)
current_task = 0;
/* Prozessorzustand des neuen Tasks aktivieren */
cpu = task_states[current_task];
return cpu;
}
Ausschnitt aus der main.asm:
...
irq_common_stub:
push ebp
push edi
push esi
push edx
push ecx
push ebx
push eax
; // Handler aufrufen
; // Der Rueckgabewert ist der Prozessorzustand des moeglicherweise
; // gewechselten Tasks. Wir muessen also den Stack dorthin wechseln
; // um die Register wiederherzustellen.
push esp
call irq_handler
mov esp, eax
; // CPU-Zustand wiederherstellen
pop eax
pop ebx
pop ecx
pop edx
pop esi
pop edi
pop ebp
; // Fehlercode und Interruptnummer vom Stack nehmen
add esp, 8
; // Ruecksprung zum unterbrochenen Code
iret
...
Multitasking initialisiere ich, direkt bevor ich die Hardwareinterrupts aktiviere, über init_multitasking();
Als Compiler verwende ich GCC und als Assembler NASM
Danke im Voraus für Hilfe