Ich habe ein Task-Modul und eine RAM Disk. Wenn ich dort nun eine ausführbare Datei habe, z.B. im COM-Format o.ä., was ist dann der einfachste Weg dieses "Programm" laufen zu lassen? Gibt es dazu ein Tutorial, habe ich bisher nicht gesehen?
09. November 2026, 18:29
Gespeichert
Gespeichert
)
Gespeichert Nachdem Multitasking nun läuft: wo bekommt man ein kleines Beispiel-Programm her? Das könnte man ja über den incbin-Trick ins Memory linken und mit memcpy an eine ausgewählte Stelle senden und dort starten.Das wäre ein erster Anfang. Macht aber nach ein paar Minuten nichtmehr viel Spaß.
Nachdem ich diesen Kernel-Stack-Mechanismus und das Setzen von esp und eip hoffentlich verstanden habe, wie führt tyndur ein Programm aus?Die ersten Programme/Treiber (tyndur & lightOS sind Mikrokernel) werden von Grub in den RAM geladen. Grub übergibt einem nach dem Laden eine Tabelle mit (unter anderem) den Startadressen, Längen und Namen der geladenen Module. Die Module sind bei beiden Kerneln ELF-Dateien. Für jedes dieser Programme wird nach dem initialisieren des Kernels ein Prozess mit einem Thread erstellt. Dann muss vielleicht noch ein bisschen ruminitialisiert werden, aber anschließend wird zum ersten Thread geswitcht und damit das ges. Multitasking angeschoben.
Gespeichert Das wäre ein erster Anfang.Das würde ich gerne erstmal aufgreifen. Spaß macht zunächst das, was man plant, umsetzt und dann auch wirklich so oder ähnlich funktioniert. Daher würde ich diesen "winzigen" Schritt gehen. Ich habe mir Folgendes überlegt. In kernel.map erhalte ich ja bereits einige Einsprünge für im Kernel bereits enthaltene Funktionen. Ein einfaches Beispiel ist settextcolor(Schriftfarbe, Hintergrundfarbe), das laut kernel.map wie folgt liegt:
0x00008614 _settextcolorIch habe also mit lb 0x00008614 einen Breakpoint gesetzt und mir das in Bochs Debugger mit s 1 angeschaut:Next at t=145559835 (0) [0x00008614] 0008:0000000000008614 (unk. ctxt): push ebp ;55
Next at t=145559836 (0) [0x00008615] 0008:0000000000008615 (unk. ctxt): mov ebp, esp ;89e5
Next at t=145559837 (0) [0x00008617] 0008:0000000000008617 (unk. ctxt): mov al, byte ptr ss:[ebp+0xc] ; 8a450c
Next at t=145559838 (0) [0x0000861a] 0008:000000000000861a (unk. ctxt): shl eax, 0x04 ;c1e004
Next at t=145559839 (0) [0x0000861d] 0008:000000000000861d (unk. ctxt): mov dl, byte ptr ss:[ebp+0x8] ; 8a5508
Next at t=145559840 (0) [0x00008620] 0008:0000000000008620 (unk. ctxt): and edx, 0x0000000f ;83e20f
Next at t=145559841 (0) [0x00008623] 0008:0000000000008623 (unk. ctxt): or eax, edx ;09d0
Next at t=145559842 (0) [0x00008625] 0008:0000000000008625 (unk. ctxt): mov byte ptr ds:0xcbf4, al ; a2f4cb0000
Next at t=145559843 (0) [0x0000862a] 0008:000000000000862a (unk. ctxt): pop ebp ;5d
Next at t=145559844 (0) [0x0000862b] 0008:000000000000862b (unk. ctxt): ret ;c3
00000044 <_settextcolor>:
44: 55 push %ebp
45: 89 e5 mov %esp,%ebp
47: 8a 45 0c mov 0xc(%ebp),%al
4a: c1 e0 04 shl $0x4,%eax
4d: 8a 55 08 mov 0x8(%ebp),%dl
50: 83 e2 0f and $0xf,%edx
53: 09 d0 or %edx,%eax
55: a2 54 05 00 00 mov %al,0x554
5a: 5d pop %ebp
5b: c3 ret Wäre dies ein geeignetes überschaubares "ausführbares binäres Programm", das man als weitere Tasks mit verschiedenen Farben konfigurieren und zwischen den anderen Tasks, die Texte ausgeben, ausführen könnte. Hierbei müsste man jeweils die beiden Argumente für Vordergrund- und Hintergrund-Farbe auf dem Stack anbieten. void create_task(void* entry)
{
page_directory_t* directory = clone_directory(current_directory);
task_t* new_task = (task_t*)k_malloc(sizeof(task_t),0,0);
new_task->id = next_pid++;
new_task->page_directory = directory;
new_task->kernel_stack = k_malloc(KERNEL_STACK_SIZE,1,0)+KERNEL_STACK_SIZE;
new_task->next = 0;
task_t* tmp_task = (task_t*)ready_queue;
while (tmp_task->next)
tmp_task = tmp_task->next;
tmp_task->next = new_task; // ... and extend it
ULONG* kernel_stack = (ULONG*) new_task->kernel_stack;
//*(--kernel_stack) = 0x23; // ss
//*(--kernel_stack) = USER_STACK_VIRT + USER_STACK_SIZE - 0x4;
*(--kernel_stack) = 0x0202; // eflags = interrupts aktiviert und iopl = 0
*(--kernel_stack) = 0x08; // cs
*(--kernel_stack) = (ULONG)entry; // eip
*(--kernel_stack) = 0; // interrupt nummer
*(--kernel_stack) = 0; // error code
// general purpose registers
//*(--kernel_stack) = 0; // eins von denen ist esp
*(--kernel_stack) = 0;
*(--kernel_stack) = 0;
*(--kernel_stack) = 0;
*(--kernel_stack) = 0;
*(--kernel_stack) = 0;
*(--kernel_stack) = 0;
*(--kernel_stack) = 0;
// segment registers
*(--kernel_stack) = 0x10;
*(--kernel_stack) = 0x10;
*(--kernel_stack) = 0x10;
*(--kernel_stack) = 0x10;
new_task->ebp = 0xd00fc0de;
new_task->esp = (ULONG)kernel_stack;
new_task->eip = (ULONG)irq_tail;
}Wo packt man da die beiden Argumente für die Farben hin? Jo klar, das war auch mein erster Schritt.ZitatDas wäre ein erster Anfang.Das würde ich gerne erstmal aufgreifen. Spaß macht zunächst das, was man plant, umsetzt und dann auch wirklich so oder ähnlich funktioniert. Daher würde ich diesen "winzigen" Schritt gehen.
Ich nehme an in tyndur war das auch nicht anders. *(--kernel_stack) = 0x0202; // eflags = interrupts aktiviert und iopl = 0
Bei dem ret der Funktion (settextcolor) wirst du allerdings sehr wahrscheinlich eine Exception kriegen, da die Rücksprungadresse ja nicht auf dem Stack liegt.
Gespeichert Bei dem ret der Funktion (settextcolor) wirst du allerdings sehr wahrscheinlich eine Exception kriegen, da die Rücksprungadresse ja nicht auf dem Stack liegt.Ich habe folgendes gemacht:
void create_task2(void* entry, ULONG arg1, ULONG arg2)
{
//...
*(--kernel_stack) = arg2; // arg2
*(--kernel_stack) = arg1; // arg1
*(--kernel_stack) = 0x0202; // eflags = interrupts aktiviert und iopl = 0
//...
}void moo()
{
while(TRUE)
{
settextcolor(2,0);
printformat("MOO %d", getpid()); // <-- kuh
settextcolor(15,0);
}
}
void baa()
{
while(TRUE)
{
settextcolor(4,0);
printformat("BAA %d", getpid()); // <- schaf
settextcolor(15,0);
}
}
void color(ULONG a, ULONG b)
{
settextcolor(a,b);
printformat("%d", getpid()); // <- Farbe
settextcolor(15,0);
}
create_task(moo);
create_task(baa);
create_task2(color, 5,2);
Gespeichert void color(ULONG a, ULONG b)
{
while(TRUE)
{
settextcolor(a,b);
printformat("%d", getpid()); // <- Farbe
settextcolor(15,0);
}
}OO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO1111111111111111111111111111111111111111111Farben vorne hinten sind ja erst mal egal.
OO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2M
OO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2M
OO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2M3BAA 3BAA 3BAA 3BAA 3BAA 3BAA
3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA
3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA
3BAA 444444444444444444444444444444444444444444444444444444444444444444444444444
44444444444444444444444444444444444444444444444444444444444444444444444444444444
44444444444444444444444444444444444444444444444
111111111111111111111111111111111
11111111111111111111111111 111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111

Das verstehe ich nicht. #define DECL_SYSCALL0(fn) int syscall_##fn();
#define DECL_SYSCALL1(fn,p1) int syscall_##fn(p1);
#define DECL_SYSCALL2(fn,p1,p2) int syscall_##fn(p1,p2);
#define DECL_SYSCALL3(fn,p1,p2,p3) int syscall_##fn(p1,p2,p3);
#define DECL_SYSCALL4(fn,p1,p2,p3,p4) int syscall_##fn(p1,p2,p3,p4);
#define DECL_SYSCALL5(fn,p1,p2,p3,p4,p5) int syscall_##fn(p1,p2,p3,p4,p5);
#define DEFN_SYSCALL0(fn, num) \
int syscall_##fn() \
{ \
int a; \
asm volatile("int $0x80" : "=a" (a) : "0" (num)); \
return a; \
}etc.
Gespeichert create_task(moo);
create_task(baa);
create_task2(0x00008664,4,2); //stimmt das so?
Jetzt dürften wir bei deiner Vorhersage sein. Wie kann ich die GPF umgehen? Denn wenn ich das so nicht schaffe, wie soll ich dann Programme ausführen?Wie kann ich die GPF umgehen? Denn wenn ich das so nicht schaffe, wie soll ich dann Programme ausführen?Einfach nicht die Funktionen als Task aufrufen. Die Funktion weiß nichts davon, dass du die missbrauchst. Außerdem solltest du kein "ret" an dieser Stelle haben, sondern einen Systemaufruf, um den Prozess zu beenden.
Gespeichert Die Funktion weiß nichts davon, dass du die missbrauchst.Von diesem Vorwurf distanziere ich mich ausdrücklich, denn es ist Aufgabe einer Funktion zu funktionieren.


void moo(){...}
void baa() {...}
void surprise(ULONG a, ULONG b) // die Parameter werden nicht von settextcolor verwendet??
{
while(TRUE) {printformat("%d", getpid()); settextcolor(15,0);}
}
int main()
{
//...
create_task(moo);
create_task(baa);
create_task2(surprise,4,2);
//...
while(TRUE) {settextcolor(15,0); printformat("%d", getpid());}
return 0;
}... und das läuft zumindest, allerdings, ohne dass die "missbrauchte" Funktion ihre Parameter verwendet. Wie schaffe ich das? 

void surprise(ULONG a, ULONG b)
{
while(TRUE)
{
asm("jmp 0x00008664");
printformat("%d", getpid());
settextcolor(15,0);
}
}Wie kann ich settextcolor verwenden, ohne es aufzurufen? void surprise(ULONG a, ULONG b)
{
while(TRUE)
{
asm("call 0x00008664");
printformat("%d", getpid());
settextcolor(15,0);
}
}Dann passiert etwas ganz Merkwürdiges: es läuft (siehe unten Ausdruck mittels copy in Bochs), aber Vorder- und Hintergrundfarbe sind beide schwarz, also beide Parameter leider noch 0. Gibt es da eine Hilfe, dass die Funktion weiß, dass sie da was abzuholen hat? 
2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 444444444444444444444444444444444444444444444444444444444444444444444444444Na, da müssen wir die Parameter wohl erneut pushen?
44444444444444444444444444444444444444444444444444444444444444444444444444444444
44444444444444444444444444444444444444444444411111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111

void surprise(ULONG a, ULONG b)
{
while(TRUE)
{
asm volatile("push %0" : "=m" (b));
asm volatile("push %0" : "=m" (a));
asm volatile("call 0x00008674");
printformat("%d", getpid());
settextcolor(15,0);
}
}(volatile kann man auch weg lassen)2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO
2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO
3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA
3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA
3BAA 3BAA 3BAA 3BAA 3BAA 3BAA 3BAA444444444444444444444444444444444444444444444
44444444444444444444444444444444444444444444444444444444444444444444444444444444
44444444444444444444444444444444444444444444444444444444444444444444444444444444
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
111111111111
2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2M
OO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2M
OO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2MOO 2
TSS log:
esp0: 4010A000h ss0: 00000010h cr3: 00000000h eip: 00000000h eflags: 00000000h e
ax: 00000000h ecx: 00000000h edx: 00000000h ebx: 00000000h esp: 401096BCh ebp: 0
0000000h esi: 00000000h edi: 00000000h es: 00000010h cs: 00000008h ss: 00000010h
ds: 00000010h fs: 00000010h gs: 00000010h
err_code: 00000034h address(eip): 0000849Bh
edi: 000084B0h esi: 00000005h ebp: 401056FCh eax: 401096BCh ebx: 000007BBh ecx:
000B8000h edx: 00000020h
cs: 8 ds: 16 es: 16 fs: 35031 gs 38620 ss 35031
int_no 13 eflags 00010006h useresp 00000034h
General Protection Fault >>> Exception. System Halted! <<<
Ist mir schon klar, dass das alles ziemlich wild ist, aber der Übergang 4->1 hat sogar geklappt. Seltsam, dass es nun ausgerechnet bei 2->3 nicht klappt. Beim ersten Durchgang geht dies problemlos, erst nach dem Einschalten dieser Überraschungsfunktion kommt der Tasswitch-Mechanismus aus dem Takt. Da staune ich jetzt wirklich. Ihr habt da sicher eine Idee. 
2MOO 2MOO 2MOO 2MOO 2MO
TSS log:
esp0: 4010A000h ss0: 00000010h cr3: 00000000h eip: 00000000h eflags: 00000000h eax: 00000000h ecx: 00000000h edx: 00000000h ebx: 00000000h esp: 401096C0h ebp: 00000000h esi: 00000000h edi: 00000000h es: 00000010h cs: 00000008h ss: 00000010h ds: 00000010h fs: 00000010h gs: 00000010h
err_code: 0000D7F4h address(eip): 00008499h edi: 000084B0h esi: 00000220h ebp: 401056FCh eax: 401096C0h ebx: 00000AC7h ecx:
000B84D9h edx: 00000020h cs: 8 ds: 16 es: 16 fs: 16 gs 0 ss 34135
int_no 13 eflags 00010016h useresp 4010D7F4h
General Protection Fault >>> Exception. System Halted! <<<
Eine C-Funktion erwartet vor den Argumenten noch die Rücksprungadresse auf dem Stack. Wenn die Funktion nicht zurückkehrt, kann das natürlich ein beliebiger Wert sein.ZitatBei dem ret der Funktion (settextcolor) wirst du allerdings sehr wahrscheinlich eine Exception kriegen, da die Rücksprungadresse ja nicht auf dem Stack liegt.Ich habe folgendes gemacht:Code: [Auswählen]void create_task2(void* entry, ULONG arg1, ULONG arg2)
{
//...
*(--kernel_stack) = arg2; // arg2
*(--kernel_stack) = arg1; // arg1
*(--kernel_stack) = 0x0202; // eflags = interrupts aktiviert und iopl = 0
//...
}
Gespeichert void surprise(ULONG a, ULONG b)
{
while(TRUE)
{
asm ("push %0" : "=m" (b));
asm ("push %0" : "=m" (a));
asm ("call 0x00008484");
printformat("%d", getpid());
settextcolor(15,0);
}
}| STACK 0x001fffdc [0x00008423]
| STACK 0x001fffe0 [0x0000000f]
| STACK 0x001fffe4 [0x00000000]
| STACK 0x401057e0 [0x000082e9]
| STACK 0x401057e4 [0x0000000f]
| STACK 0x401057e8 [0x00000000]
| STACK 0x401097e0 [0x00008308]
| STACK 0x401097e4 [0x00000004]
| STACK 0x401097e8 [0x00000000]
| STACK 0x4010d7b0 [0x00008341]Hier sieht man nur türkis, die Zahl 4 sieht man nicht.
| STACK 0x4010d7b4 [0x00000004]
| STACK 0x4010d7b8 [0x123890ab]
| STACK 0x4010d7bc [0x00000004]
... immer abwechselnd so weiter ...
| STACK 0x4010d7ec [0x00008330]
| STACK 0x4010d670 [0x00008363]Hier sieht man türkis Hintergrund und in rot die Zahl 4.
| STACK 0x4010d674 [0x0000000f]
| STACK 0x4010d678 [0x00000000]

| STACK 0x401057e0 [0x000082ca]Umschalten auf weiß:
| STACK 0x401057e4 [0x00000002]
| STACK 0x401057e8 [0x00000000]
| STACK 0x401057e0 [0x000082e9]
| STACK 0x401057e4 [0x0000000f]
| STACK 0x401057e8 [0x00000000]
Chaos
| STACK 0x4010ca08 [0x00008341]richtig:
| STACK 0x4010ca0c [0x00000004]
| STACK 0x4010ca10 [0x123890ab]
| STACK 0x4010c9f8 [0x00008363]Na immerhin liegt ein while(1) zwischen den Parametern und meinem Push-Vorgang:
| STACK 0x4010c9fc [0x0000000f]
| STACK 0x4010ca00 [0x00000000]
#define HEAP_MAGIC 0x123890ABDie Kernel-Stacks befinden sich ja auf dem Heap. Liegt daran, dass k_malloc Platz auf dem Heap sucht, sobald einer da ist (Erbe von James Molloy's Code). Ich habe nach diesem Wert in kheap.h/kheap.c gesucht: // Sanity checks.
ASSERT(header->magic == HEAP_MAGIC);
ASSERT(footer->magic == HEAP_MAGIC);
Da kommt also in task 4 etwas quer gehuscht. 
Gespeichert void surprise(ULONG a, ULONG b)
{
asm volatile ("push %0" :/* no output registers */: "r" (b));
asm volatile ("push %0" :/* no output registers */: "r" (a));
while(TRUE)
{
asm volatile ("call 0x00008484");
printformat("%d", getpid());
settextcolor(15,0);
}
}Aber alles hat sein Gutes. Der Debug-Prozess oben hat mir mehr Einsichten in die Abläufe auf dem Stack rund um C-Funktionen und Parameter gegeben. | STACK 0x4010d7e0 [0x00008343]
| STACK 0x4010d7e4 [0x00000004]
| STACK 0x4010d7e8 [0x123890ab]
| STACK 0x4010d7ec [0x00008330]
| STACK 0x4010d7f0 [0x00000008]
| STACK 0x4010d7f4 [0x00000000]
| STACK 0x4010d7f8 [0x00000002]
| STACK 0x4010d7fc [0x00000004]
| STACK 0x4010d800 [0x123890ab]
| STACK 0x4010d804 [0x4010cff4]
| STACK 0x4010d808 [0x123890ab]
| STACK 0x4010d80c [0x00000001]
| STACK 0x4010d810 [0x000007f8]
| STACK 0x4010d814 [0x00000000]
| STACK 0x4010d818 [0x00000000]
| STACK 0x4010d81c [0x00000000]
| STACK 0x4010d7d0 [0x00008365]
| STACK 0x4010d7d4 [0x0000000f]
| STACK 0x4010d7d8 [0x00000000]
| STACK 0x4010d7dc [0x4010d7f4]
| STACK 0x4010d7e0 [0x00008343]
| STACK 0x4010d7e4 [0x00000004]
| STACK 0x4010d7e8 [0x123890ab]
| STACK 0x4010d7ec [0x00008330]
| STACK 0x4010d7f0 [0x00000008]
| STACK 0x4010d7f4 [0x00000000]
| STACK 0x4010d7f8 [0x00000002]
| STACK 0x4010d7fc [0x00000004]
| STACK 0x4010d800 [0x123890ab]
| STACK 0x4010d804 [0x4010cff4]
| STACK 0x4010d808 [0x123890ab]
| STACK 0x4010d80c [0x00000001]
Aber schon mal ein netter Anfang. id: 1 ebp: 00000000h esp: 00000000h eip: 00000000h PD: 00000000h k_stack: 40101800h next: 40101814h
id: 2 ebp: D00FC0DEh esp: 401057C0h eip: 00008299h PD: 40102000h k_stack: 40105800h next: 40101844h
id: 3 ebp: D00FC0DEh esp: 401097C0h eip: 00008299h PD: 40106000h k_stack: 40109800h next: 40101874h
id: 4 ebp: D00FC0DEh esp: 4010D7B8h eip: 00008299h PD: 4010A000h k_stack: 4010D800h next: 00000000h
Jede Task hat einen Kernel Stack und eine eigene Page Directory. 0x000082f6 _baa
0x00008330 _surprise
0x000082b8 _moo
Bei call wird die Rücksprungadresse doch automatisch auf dem Stack abgelegt?Ja, aber task_create macht keinen call. Wenn der Task das erste Mal aktiv wird, dann wird der in task_create erstellte Stack abgebaut, und im Laufe dessen landet der Kontrollfluss am Anfang der Funktion surprise.
dann schaltet die Hintergrundfarbe auf Türkis(5) um (wahrscheinlich vorne/hinten falsch übergeben?)Türkis ist nicht 5 sondern 0x0b, und zwar genau das 0xb von 0x123890ab.
Gespeichert Zu diesem Zeitpunkt (so die C-Aufrufkonvention) muss oben auf dem Stack die Rücksprungadresse liegen und darunter die Parameter."Oben und unten" habe ich verdreht. Dieses Bild muss man sich bezüglich des Codes in create_task auf dem Kopf vorstellen:
*(--kernel_stack) = arg2; // arg2
*(--kernel_stack) = arg1; // arg1
*(--kernel_stack) = 0x0; // return address dummy
*(--kernel_stack) = 0x0202; // eflags = interrupts aktiviert und iopl = 0void surprise(ULONG a, ULONG b)
{
asm volatile ("push %0" :/* no output registers */: "r" (b));
asm volatile ("push %0" :/* no output registers */: "r" (a));
while(TRUE)
{
asm volatile ("call 0x00008484");
printformat("%d", getpid());
settextcolor(15,0);
}
}
Wenn ich es richtig verstanden habe, kommt "von oben gesehen" zuerst die Rücksprungadresse, dann die Argumente 1 ... n, richtig? //TEST
//*(--kernel_stack) = arg2; // arg2
//*(--kernel_stack) = arg1; // arg1
//*(--kernel_stack) = 0x0; // return address dummy
*(--kernel_stack) = 0x0202; // eflags = interrupts aktiviert und iopl = 0
void surprise(ULONG a, ULONG b)
{
//asm volatile ("push %0" :/* no output registers */: "r" (b));
//asm volatile ("push %0" :/* no output registers */: "r" (a));
while(TRUE)
{
//asm volatile ("call 0x00008484");
settextcolor(4,2);//TEST
printformat("%d", getpid());
settextcolor(15,0);
}
}Der komplizierte Fall: *(--kernel_stack) = arg2; // arg2
*(--kernel_stack) = arg1; // arg1
*(--kernel_stack) = 0x0; // return address dummy
*(--kernel_stack) = 0x0202; // eflags = interrupts aktiviert und iopl = 0void surprise(ULONG a, ULONG b)
{
asm volatile ("push %0" :/* no output registers */: "r" (b));
asm volatile ("push %0" :/* no output registers */: "r" (a));
while(TRUE)
{
asm volatile ("call 0x00008484");
printformat("%d", getpid());
settextcolor(15,0);
}
}Beide ergeben den gleichen Ablauf. Nun habe ich endlich ganz klar verstanden, was der Aufruf einer C-Funktion auf dem Stack bewirkt. Warum rufst du eigentlich nicht einfach settextcolor(a, b) auf, sondern bastelst am Stack rum und jonglierst mit Konstanten?Gute Frage. Ich wollte den Mechanismus für das Ausführen von Code - sprich von Programmen - auf PrettyOS antesten. Dafür hatte ich mir settextcolor(...) ausgesucht, weil diese Funktion eine leicht sichtbare Funktion hat und darüber hinaus auch keine weiteren Funktionen in ihrem Inneren aufruft, so dass zwischen entry und ret nur wenige Schritte liegen, die man leicht per Debugger kontrollieren kann. Vielleicht bin ich da auf dem Holzweg.
Bei .com-Dateien von DOS ist der Rest einfach: Das sind flache Binaries, sobald sie im Speicher liegen, muß man also nur noch einen Task erstellen, die Segmentregister für den Task richtig setzen und eip auf das erste Byte der Datei zeigen lassen. Das eigentliche Reinspringen in den Code sollte dann der Interrupthandler übernehmen, der das auch schon bei den Kerneltasks gemacht hat.Wie auch immer, ich lerne momentan eine Menge über C-Funktionen. So "low level" schaue ich mir diese selten an.

Gespeichert asm volatile ("call _settextcolor");
Gespeichert nasmw -O32 -f bin file_data.asm -o file_data.datund mittels incbin in den kernel eingeschleust:global _file_data_start
global _file_data_end
_file_data_start:
incbin "file_data.dat"
_file_data_end:Dann wird es als Task 5 aufgerufen:void test()
{
while(TRUE)
{
asm volatile ("call _file_data_start");
printformat("%d", getpid());
settextcolor(15,0);
}
}
task_t* task5 = create_task0(test);
[BITS 32]
start:
Mov [0x000b8000], byte 'T'
Mov [0x000b8002], byte 'e'
Mov [0x000b8004], byte 's'
Mov [0x000b8006], byte 't'
Retklappt es, allerdings bisher nur im Debugger sichtbar, weil ansonsten zu schnell. Dennoch super. 
Gespeichert 