Eigenes OS?
-
read_eip() is fine. But you could try:
readEip: pop eax push eax ret
You are having some drivers, right?
When switching tasks, you change the registers, and the cr3. When a task does something with a device, and there is not good code implemented to handle multitasking in device drivers, the device will move data. But when in that time a task switch occurs, some problems may come. The task switch at 20seconds is very bad. The process doesn't need to know it is EVER switched. 100Hz may be nice (100 switches each second). Play something with it.
Consoles: you got it
typedef struct { uint32_t id; // console id, just for making some things easier uint8_t keystroke[KEYSTROKE_LENGTH]; // make this the way you did with keystrokes uint32_t *videoBuffer; // a pointer to some place in memory, size: width*height*2 bytes (probably 80*25*2) uint32_t cursorX; uint32_t cursorY; // coordinates of the cursor for this console uint8_t colorAttribute; // attributes curently used by console } console_t struct task { .... console_t *console; // put console in task .... };
That is an example for a console structure. Be sure of:
- Create one console when initializing screen (VGA), set it into a global variable, currentConsole
- Be sure the functions work to the right console. Each time a task switch occurs, it should use another console structure. But not the currentConsole, because that is the console currently SHOWED. En when not watching task 2, it should be able to print text, so the user can see it later.You can determine the console of the current task by just using currentTask->console(->cursorX, ->cursorY etc.)
It is simple, but much work. Also be sure to make a backup from all you have first, it is a lot of work to remove the console code from your VGA driver.
Good luck, I think it will work with this.
// PHPnerd
-
global _read_eip _read_eip: pop eax push eax ret
... looks better and works fine, but does not help with the page fault due to the strange EIP.
Thanks for the consoles' code. Nice feature.
-
Does the page fault trigger after setting eip, or after setting cr3? or something else?
// PHPnerd
-
Ich habe mit HLT im asm-code probiert, der page fault erfolgt beim *jmp %%ecx;
Was bedeutet eigentlich dieser * vor %%ecx ? Wenn ich ihn weglasse, passiert genau das gleiche.
Ich habe eip,esp,ebp,cur_dir->phys direkt vor dem asm-code geloggt:
..
Schalten nach 0,01 sec:task_switch before asm: eip: 0000D306h esp: 0018FF3Ch ebp: 0018FF54h cur_dir->phys: 00001000h
Page Fault (page not present) at 0F000123h - EIP: 0F000123hSchalten nach 1 sec: (dann wurden zumindest die neuen Tasks angelegt)
task_switch before asm: eip: 0000D4C2h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 0041E000h
Page Fault (page not present) at 0040FCA0h - EIP: 0040FCA0hWenn ich das richtig sehe, liegt das Problem eher bei current_directory->physicalAddr als bei eip, oder?.
Im Lowlevel Forum meinte man dazu, dass das Problem vom C-Compiler kommen könnte (nicht alle register wurden gespeichert und zurück geschrieben), und man empfahl mir das komplett in Assembler zu machen analog tyndur.
Ohne die Clobber List kommt übrigens wieder der GPF:
... jmp %%ecx; " : : "r"(eip), "r"(esp), "r"(ebp), "r"(current_directory->physicalAddr) );
task_switch before asm: eip: 0000D4C2h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 0041E000h
General Protection Fault >>> Exception. System Halted! <<<Erst, wenn ich sowohl ebx als auch edx "clobbere", kommt der PF, einzeln GPF. edi und esi kann ich leider nicht clobbern wegen Fehlermeldung des Compilers.
Fundstelle zur Clobber List:
http://groups.google.im/group/comp.lang.asm.x86/browse_thread/thread/cf89391bb64126f7
..Das kommt mir inzwischen alles suspekt vor, was gcc da schafft. Mit dem Clobbern habe ich wenig Erfahrung.
-
Erhard Henkes schrieb:
Was bedeutet eigentlich dieser * vor %%ecx ?...
Siehe hier http://www.c-plusplus.net/forum/viewtopic-var-t-is-238553.html
-
Did you try to get the assembly code generated by GCC?
Are you sure that the currentDir->physical is physical?
And are the new page tables, and page directories you made, page aligned?// PHPnerd
-
Did you try to get the assembly code generated by GCC?
Yes, I was interested in the consequence of putting (or not putting) registers into the clobber list. Here is the result:
clobbering ebx and edx ==> Page Fault:
asm volatile(" \ cli; \ mov %0, %%ecx; \ mov %1, %%esp; \ mov %2, %%ebp; \ mov %3, %%cr3; \ mov $0x12345, %%eax; \ sti; \ jmp %%ecx; " : : "r"(eip), "r"(esp), "r"(ebp), "r"(current_directory->physicalAddr) : "ebx","edx" );
objdump task.o -D > task.txt
35f: fa cli 360: 89 f1 mov %esi,%ecx 362: 89 fc mov %edi,%esp 364: 89 cd mov %ecx,%ebp 366: 0f 22 d8 mov %eax,%cr3 369: b8 45 23 01 00 mov $0x12345,%eax 36e: fb sti 36f: ff e1 jmp *%ecx
The first thing you see is why we cannot clobber edi and esi, too.
Empty clobber list ==> GPF
351: fa cli 352: 89 d9 mov %ebx,%ecx 354: 89 f4 mov %esi,%esp 356: 89 fd mov %edi,%ebp 358: 0f 22 d8 mov %eax,%cr3 35b: b8 45 23 01 00 mov $0x12345,%eax 360: fb sti 361: ff e1 jmp *%ecx
clobbering ebx ==> GPF
35f: fa cli 360: 89 f1 mov %esi,%ecx 362: 89 fc mov %edi,%esp 364: 89 d5 mov %edx,%ebp 366: 0f 22 d8 mov %eax,%cr3 369: b8 45 23 01 00 mov $0x12345,%eax 36e: fb sti 36f: ff e1 jmp *%ecx
clobbering edx ==> GPF
351: fa cli 352: 89 d9 mov %ebx,%ecx 354: 89 f4 mov %esi,%esp 356: 89 fd mov %edi,%ebp 358: 0f 22 d8 mov %eax,%cr3 35b: b8 45 23 01 00 mov $0x12345,%eax 360: fb sti 361: ff e1 jmp *%ecx
-
..
-
Ich habe nun noch eine Variable für die physikalische Adresse in fork() eingefügt, um diese dort auszugeben:
// Create a new process. ULONG phys; task_t* new_task = (task_t*) k_malloc( sizeof(task_t),0,&phys ); printformat("placement_address after creating a new process: %x phys: %x\n", placement_address, phys);
VFS & RAM Disk install
placement_address after ram disk install: 40200000h
ramdisk_start: 40081000h file_data_start: 0000A2E0h file_data_end: 0000B652h
After set_kernel_stack ==> tss_entry.esp0: 40101800h> IRQ 127 <<<
Hello, user world!
...
placement_address after creating a new process: 40200000h phys: 0041CBE8h
fork() returned: 00000002h and getpid() returned: 00000001h
placement_address after creating a new process: 40200000h phys: 0041CC18h
fork() returned: 00000003h and getpid() returned: 00000001h
placement_address after creating a new process: 40200000h phys: 0041CC48h
fork() returned: 00000004h and getpid() returned: 00000001h
SS: 00000010h, ESP: 0018FFE0h, EBP: 0018FFF0h, CS: 00000018h, DS: 00000020h
task_switch before asm: eip: 0000D4CFh esp: 0018FFD8h ebp: 0018FFF0h cur_dir->ph
ys: 0041E000h
Page Fault (page not present) at 0040FCC0h - EIP: 0040FCC0h
-
I will explain the kmalloc for you.
size = size (doh)
align = page aligned, this makes your address page aligned, usable for paging structures and TSS (and others)
phys = get the physical address. You can put NULL in it, or a pointer to a variable. Like:uint32_t phys = 0; uint32_t ptr = kmallocAP(0x100, 1, &phys); printf("Phys: 0x%X, Virt: 0x%X\n",phys,ptr);
Getting physical address and doing nothing with it won't solve your problem.
The task doesn't have to be page aligned, since it is Software Multitasking, and you made it your own (nah, JamesM did :P)The kmalloc code is 100% fine. (I used it my own some time ago)
// PHPnerd
-
Yes, the k_malloc(...) of James Molloy (I have his written permission to use his source code as a base for own experiments in an OS tutorial, if I like, but I am not sure, if his code is really robust enough) is usable and is not the problem (Other people think, JM has put too much into paging.h/paging.c, because phys./virt. memory management should be separated clearly. This can be done easily.).
OK, alignment is not important. I was not quite sure about it.
Currently, I do not understand the difference in the result of EIP between cases 1) and 3). In 3) I just save the physical address at 0x01 or a variable phys. The reason must be in the way of saving details of the tasks. Hence, the clobbering can influence the deficient process.
I think, I should go back to the test code where the task switch really works and analyze the effects by looking at all the details again. I just did and the page fault came, too. Thus, the failure has another reason. That's good.
As soon as I have analyzed it, I will come back.@PHPnerd: Thanks for staying with me in times of confusion.
I use the following "stable version":
ckernel.c (like main.c):UCHAR c=0; while(TRUE) { if( k_checkKQ_and_print_char() ) { ++c; if(c>5) { c=0; settextcolor(4,0); printformat("\nT: %x H: %x WRITE: %i Read: %i ", pODA->pTailKQ, pODA->pHeadKQ, pODA->KQ_count_write, pODA->KQ_count_read); printformat("*T: %c %i *H: %c %i\n", *(pODA->pTailKQ),*(pODA->pTailKQ),*(pODA->pHeadKQ),*(pODA->pHeadKQ)); settextcolor(2,0); task_switch(); settextcolor(getpid(),0); } } }
kjsdfhsdkjksdjfhksdjfhsdkjfhksdjfhksdjfhsdkjfhsdkjfhksdjfhkjsdfhksjdhfß
T: 0000D80Fh H: 0000D80Fh WRITE: 66 Read: 66 *T: d 100 *H: d 100rnel_stack: 4010
task_switch before asm: eip: 0000D303h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->ph
ys: 00426000hk install
placement_address after ram disk install: 40200000h
ramdisk_start: 40081000h file_data_start: 0000A2C0h file_data_end: 0000B632h
After set_kernel_stack ==> tss_entry.esp0: 40101800h> IRQ 127 <<<
Hello, user world!
Found file dev
(directory)
Found file f1
contents: "PrettyOS: My filename is test1.txt!"
Found file f2
contents: "PrettyOS: My filename is test2.txt!"
Found file f3
contents: "PrettyOS: My filename is test3.txt!"
placement_address after creating a new process: 40200000h phys: 0041CBE8h
fork() returned: 00000002h and getpid() returned: 00000001h
placement_address after creating a new process: 40200000h phys: 0041CC18h
fork() returned: 00000003h and getpid() returned: 00000001h
placement_address after creating a new process: 40200000h phys: 0041CC48h
fork() returned: 00000004h and getpid() returned: 00000001h
SS: 00000010h, ESP: 0018FFE0h, EBP: 0018FFF0h, CS: 00000018h, DS: 00000020hWhile entering keystrokes, the task is switched after every sixth keystroke.
The logs of 'task_switch before asm:' with the original and 3 forked tasks are:task_switch before asm: eip: 0000D4AFh esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 0041E000h //PID 2
task_switch before asm: eip: 0000D4AFh esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 00422000h //PID 3
task_switch before asm: eip: 0000D4AFh esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 00426000h //PID 4
task_switch before asm: eip: 0000D303h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 00001000h //PID 1
task_switch before asm: eip: 0000D303h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 0041E000h //PID 2
task_switch before asm: eip: 0000D303h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 00422000h //PID 3
task_switch before asm: eip: 0000D303h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 00426000h //PID 4
task_switch before asm: eip: 0000D303h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 00001000h //PID 1 - the same as line 4
ff.
These are the data of the forked tasks:
phys: 0041CBE8h
fork() returned: 00000002hphys: 0041CC18h
fork() returned: 00000003hphys: 0041CC48h
fork() returned: 00000004hSS: 00000010h, ESP: 0018FFE0h, EBP: 0018FFF0h, CS: 00000018h, DS: 00000020h
The task switch runs "unclobbered". Now it comes:
If I clobber ebx and edx (see above), then I get a PF:
task_switch before asm: eip: 0000D4AFh esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 0041E000h
Page Fault (page not present) at 0040FCA0h - EIP: 0040FCA0hIf I shift the task switch to timer handler, then I get an "Absturz":
task_switch before asm: eip: 0000D303h esp: 0018FE74h ebp: 0018FE8Ch cur_dir->phys: 00001000h
...
task_switch before asm: eip: 0000D303h esp: 0018FE74h ebp: 0018FE8Ch cur_dir->phys: 00001000h
...
task_switch before asm: eip: 0000D303h esp: 0018FF70h ebp: 0018FF88h cur_dir->phys: 00001000h
...
task_switch before asm: eip: 0000D303h esp: 0018FE74h ebp: 0018FE8Ch cur_dir->phys: 00001000h
...
task_switch before asm: eip: 0000D4AFh esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 0041E000h
...
placement_address after creating a new process: 40200000h phys: 0041CC18h
fork() returned: 00000003h and getpid() returned: 00000002h
placement_address after creating a new process: 40200000h phys: 0041CC48h
fork() returned: 00000004h and getpid() returned: 00000002h
SS: 00000010h, ESP: 0018FFE0h, EBP: 0018FFF0h, CS: 00000008h, DS: 00000010h==> Absturz (no exception, no reboot, just nothing besides blinking cursor)
I think, this shows that JM's function task_switch() does not correctly work. Caring only for eip, esp, ebp seems to be not enough! Right?
-
@PHPnerd: How do you switch tasks? Are you willing to show your new kmalloc?
-
I do not switch tasks yet. I will explain main for it later here
And, I am using DogLea Algorithm with my own code.
So:
Headers and footers
List containing free blocks, sorted by sizeLike the JamesM one, but than all my own code (like it more :P)
Maybe look deeper in Intel Manuals of the source of other OSes to get idea's
// PHPnerd
-
With the multitasker:
Try to save more registers, since you don't have a TSS.
Save:
EFLAGS <--
Segment registers: CS, DS, ES, FS, GS
Possible save some general registers (can be done later)Maybe the EFLAGS will save the problem.
Oh, and, did you do a end-of-interrupt before task switch when using switching in PIT? May be important.// PHPnerd
-
Save: FLAGS/EFLAGS
How can I do that? Is there a name for it in assembler? But I have read that you need not save them for task switch.
I think the problem is with eip. I have logged it just before the asm code and directly after the task_switch():
task_switch before asm: eip: 0000D54Fh esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 0041E000h PID: 2 after task_switch: eip: 00008B11h esp: 0018FFE0h ebp: 0018FFF0h cur_dir->phys: 0041E000h PID: 2
D54Fh vs. 8B11h ? But the task switch runs in this special case:
///TEST printformat("task_switch before asm: eip: %x esp: %x ebp: %x cur_dir->phys: %x PID: %d\n",eip,esp,ebp,current_directory->physicalAddr, getpid()); ///TEST asm volatile(" \ cli; \ mov %%ebx, %%esp; \ mov %%edx, %%ebp; \ mov %%eax, %%cr3; \ mov $0x12345, %%eax; \ sti; \ jmp *%%ecx; " : : "c"(eip), "b"(esp), "d"(ebp), "a"(current_directory->physicalAddr) );
... changed to named registers.
while(TRUE) { if( k_checkKQ_and_print_char() ) { ++c; if(c>5) { c=0; settextcolor(4,0); printformat("\nT: %x H: %x WRITE: %i Read: %i ", pODA->pTailKQ, pODA->pHeadKQ, pODA->KQ_count_write, pODA->KQ_count_read); printformat("*T: %c %i *H: %c %i\n", *(pODA->pTailKQ),*(pODA->pTailKQ),*(pODA->pHeadKQ),*(pODA->pHeadKQ)); settextcolor(2,0); task_switch(); ///TEST printformat("after task_switch: eip: %x esp: %x ebp: %x cur_dir->phys: %x PID: %d\n",read_eip(),fetchESP(),fetchEBP(),current_directory->physicalAddr, getpid()); ///TEST settextcolor(getpid(),0); } } }
-
Does it work now?
// PHP
-
Only in the while loop at the above shown location. I think that the failure is at another place, perhaps concerning kernel_stack of the task. I come back to that.
EDIT: One failure was in fork(): now new_task->kernel_stack instead of current_task->...
I log the processes with its data, the first task looks strange:
HEAP start: 40081000h end: 40100000h max: 4FFFF000h kernel mode: 0 read-only: 0 hole 40081000h hole-size: 0007F000h after create_heap: placement_address: 0030C020h allocated frames: 795 VFS & RAM Disk install placement_address after ram disk install: 40200000h ramdisk_start: 40081000h file_data_start: 0000A200h file_data_end: 0000B572h tasking install move stack, ESP: 0018FFD0h After init first task, p_a: 40200000h After k_malloc kernel_stack, p_a: 40200000h k_stack: 40101000h placement_address after creating a new process: 40200000h phys: 0041C814h fork(): 00000002h and getpid(): 00000001h placement_address after creating a new process: 40200000h phys: 0041C844h fork(): 00000003h and getpid(): 00000001h placement_address after creating a new process: 40200000h phys: 0041C874h fork(): 00000004h and getpid(): 00000001h t->id: 1, esp: 00000000h, eip: 00000000h k_stack: 40101000h, p_dir: 00000000h next: 40101814h t->id: 2, esp: 0018FFD8h, eip: 0000D3C9h k_stack: 40105000h, p_dir: 40102000h next: 40101844h t->id: 3, esp: 0018FFD8h, eip: 0000D3C9h k_stack: 40109000h, p_dir: 40106000h next: 40101874h t->id: 4, esp: 0018FFD8h, eip: 0000D3C9h k_stack: 4010D000h, p_dir: 4010A000h next: 00000000h SS: 00000010h, ESP: 0018FFE0h, EBP: 0018FFF0h, CS: 00000008h, DS: 00000010h
after typing keys and taskswitching by that:
kjdfghjkkhjkhkjkhkjhkkjh task_switch before asm: eip: 0000D216h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 00001000h PID: 1 after task_switch in ckernel.c: eip: 000089C7h esp: 0018FFE0h ebp: 0018FFF0h cur_dir->phys: 00001000h PID: 1
Improved Sourcecode: http://www.henkessoft.de/OS_Dev/Downloads/40.zip
I think it is not yet ready for the timer_handler, but I am on the right track now.
-
Good!~
I almost finished my kmalloc. Working on Shrink now. Next is krealloc, but I may skip that one for now.
I will continue ordering my OS, and then the MultiTasker.
// PHP
-
To my mind, the crucial point is that the source code stays transparent.
There was a create_heap(...) inside of paging_install(). I have taken it out, because the heap is more complicated to visualize by printformat(...), and process' stacks were created in the heap!
Now there is a new exception, if you put the task_switch() to practice inside the time_handler (k_m_nonheap means "pushing" placement_address, no heap):
k_m_nonheap k_m_nonheap k_m_nonheap k_m_nonheap k_m_nonheap
p_a: 0040D000h allocated frames: 1053
frames: 00400000h NFRAMES: 524288
k_dir->phys: 00406000h
p_a: 0040D000h allocated frames: 1053k_m_nonheap
tasking install
stack, ESP: 0018FFD0h k_m_nonheap Init first task, p_a: 00410020h cur_task: 00410004h k_m_nonheap After k_malloc k_stack, p_a: 00411800h k_stack: 00411000hk_m_nonheap k_m_nonheap placement_address after creating a new process: 00414020h phys: 00414004h
k_m_nonheap fork(): 00000002h and getpid(): 00000001h
k_m_nonheap k_m_nonheap placement_address after creating a new process: 00418020h phys: 00418004h
k_m_nonheap fork(): 00000003h and getpid(): 00000001h
t->id: 1, esp: 00000000h, eip: 00000000h k_stack: 00411000h, p_dir: 0040E000h next: 00414004h
t->id: 2, esp: 0018FFD8h, eip: 0000D379h k_stack: 00415000h, p_dir: 00412000h next: 00418004h
t->id: 3, esp: 0018FFD8h, eip: 0000D379h k_stack: 00419000h, p_dir: 00416000h next: 00000000hp_a: 00419800h
SS: 00000010h, ESP: 0018FFE0h, EBP: 0018FFF0h, CS: 00000008h, DS: 00000010h
task_switch before asm: cur_task->p_dir: 00412000h task_switch before asm:
eip: 0000D379h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 00413000h PID: 2
Invalid Opcode >>> Exception. System Halted! <<<Wie kann man den "Invalid Opcode" besser auswerten? z.B. Invalid Opcode ... at address ...? Ich habe mir z.B. r->eip angeschaut. Das passt einfach nicht zu dem in task_t. Verflixt!
Tippt man vor dem Timer Handler schnell noch ein paar task switches, dann findet man:
klxdfgjkldfgjdfkgjkldfgjkldfgjkldfgjkldfjglkdfgjlkdfgjkldfjgkldfjglk
task_switch before asm: cur_task->p_dir: 0040E000h task_switch before asm: eip: 0000D1BBh esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 0040F000h PID: 10h ebp: 0018FFF0h cur
Invalid Opcode >>> Exception. System Halted! <<<This is the test code in ckernel.c (main.c):
int main() { //... settextcolor(2,0); printformat("paging install\n"); settextcolor(15,0); paging_install(); settextcolor(2,0); printformat("tasking install\n"); settextcolor(15,0); tasking_install(); settextcolor(15,0); int retValFork1 = fork(); int retValGetPid1 = getpid(); printformat("fork(): %x and getpid(): %x\n", retValFork1, retValGetPid1); int retValFork2 = fork(); int retValGetPid2 = getpid(); printformat("fork(): %x and getpid(): %x\n", retValFork2, retValGetPid2); int retValFork3 = fork(); int retValGetPid3 = getpid(); printformat("fork(): %x and getpid(): %x\n", retValFork3, retValGetPid3); task_t* t = current_task; while(TRUE) { while(t->next) { printformat("t->id: %d, esp: %x, eip: %x k_stack: %x, p_dir: %x next: %x\n", t->id, t->esp, t->eip, t->kernel_stack, t->page_directory, t->next); t = t->next; } printformat("t->id: %d, esp: %x, eip: %x k_stack: %x, p_dir: %x next: %x\n", t->id, t->esp, t->eip, t->kernel_stack, t->page_directory, t->next); break; } printformat("p_a: %x \n", placement_address); printformat("SS: %x, ESP: %x, EBP: %x, CS: %x, DS: %x\n", fetchSS(),fetchESP(),fetchEBP(),fetchCS(),fetchDS()); settextcolor(2,0); UCHAR c=0; while(TRUE) { if( k_checkKQ_and_print_char() ) { ++c; if(c>5) { c=0; task_switch(); printformat("after task_switch in ckernel.c: eip: %x esp: %x ebp: %x cur_dir->phys: %x PID: %d\n",read_eip(),fetchESP(),fetchEBP(),current_directory->physicalAddr, getpid()); settextcolor(getpid(),0); } } } return 0; }
EDIT:
I have printed now the infos from the struct reg by evaluating the exception in the IRQ/fault handler:placement_address: 00419800h
SS: 00000010h, ESP: 0018FFE0h, EBP: 0018FFF0h, CS: 00000008h, DS: 00000010h
task_switch before asm: cur_task->p_dir: 00412000h eip: 0000D4D9h esp: 0018FFD8h ebp: 0018FFF0h cur_dir->phys: 00413000h PID: 2Invalid Opcode >>> Exception. System Halted! <<<
err_code: 00000000h address(eip): 0000024Bh edi: 00000020h esi: 00000000h ebp: 00000008h esp: 0018FFE8h eax: 000000D7h ebx: 00000000h ecx: 00012345h edx: 0000D7F0h cs: 8 ds: 16 es: 16 fs: 16 gs 16 ss 2097144 int_no 6 eflags 00010202h useresp 00000000hThese should be the data direct after the asm-code in task switch.
address: 24Bh (eip) cannot be correct, if we enter with D4D9h.
The ss 2097144 = 1FFFF8h looks "kaput". It should be 16 (10h).
eflags: 10000001000000010b = 10202hThe whole task_management has to be looked thru.
JM's code in this area is not robust, it was only for short demos.
-
Ich habe jetzt mal pushf und popf eingebaut, um die flags zu sichern:
asm volatile(" \ cli; \ pushf; \ mov %%ebx, %%esp; \ mov %%edx, %%ebp; \ mov %%eax, %%cr3; \ mov $0x12345, %%eax; \ popf; \ sti; \ jmp *%%ecx; " : : "c"(eip), "b"(esp), "d"(ebp), "a"(current_directory->physicalAddr) );
Ergebnis via task_switch mittels timer:
p_a: 00419800h
SS: 00000010h, ESP: 0018FFE0h, EBP: 0018FFF0h, CS: 00000008h, DS: 00000010h
task_switch before asm: cur_task->p_dir: 00412000h eip: 0000D519h esp: 0018FFD8
h ebp: 0018FFF0h cur_dir->phys: 00413000h PID: 2 ss: 16
err_code: 00000000h address(eip): 0000D40Bh
edi: 0018FFF0h esi: 0018FFD8h ebp: 0018FFF0h esp: 0018FFC8h eax: 00012345h ebx:
0018FFD8h ecx: 0000D519h edx: 0018FFF0h
cs: 8 ds: 16 es: 16 fs: 16 gs 16 ss 55376
int_no 1 eflags 00007FC6h useresp 00418000h
Debug >>> Exception. System Halted! <<<Jetzt haben wir eine DEBUG Exception.
Übrigens: Wenn ich pushfd / popfd verwenden will, macht mein oldtimer gcc (verwendet wegen aout Format von NASM um den Asemblercode einzubinden) das nicht mit:
c:/djgpp/tmp/cc5s5oYe.s: Assembler messages:
c:/djgpp/tmp/cc5s5oYe.s:237: Error: no such instruction:pushfd' c:/djgpp/tmp/cc5s5oYe.s:237: Error: no such instruction:
popfd'kann also nur die FLAGS nicht die EFLAGS sichern.
EDIT: Ich denke inzwischen, dass JM's Sourcecode im Bereich (multi)tasking für PrettyOS einfach unbrauchbar ist.
Auf jeden Fall hat mir die Beschäftigung mit den Themen viel gebracht, bin nun auch oft genug gegen den Baum gefahren, um zu wissen, was etwas taugt und was einem bei Problemen nur noch den Rest gibt.
Daher mache ich nun einen kompletten "roll-back" und setze am Ende des Tutorials an. !!!Schnitt!!!