1
Lowlevel-Coding / Re: Taskswitch
« am: 22. February 2013, 15:57 »
Ich weiß leider immer noch nicht, was das Problem ist. Hat noch jemand eine Idee?
22. November 2024, 14:35
Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.
struct GDTstruct GDT[6];
// ...
CreateGDT(0, 0, 0, 0, 0);
CreateGDT(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
CreateGDT(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
CreateGDT(3, 0, 0xFFFFFFFF, 0x9A | 0x60, 0xCF);
CreateGDT(4, 0, 0xFFFFFFFF, 0x92 | 0x60, 0xCF);
CreateGDT(5, (unsigned int) tss, sizeof(tss), 0x09 | 0x80 | 0x60, 0x0);
Das müsste so passen, oder?
Die Idee dahinter ist, die Programme voreinander zu schützen (daher das "Protected" in "Protected Mode"), indem man die Segmente so einrichtet, dass sie sich nicht überlappen. Programme die versuchen über die Segmentgrenzen hinaus auf Speicher zuzugreifen, werden vom Betriebssystem daran gehindert. So wie ich das beschrieben habe, macht es allerdings niemand und die Segmentierung wird von kommerziellen Systemen ignoriert. Stattdessen wird Paging eingesetzt, das flexibler ist (keine feste Größe der Segmente).ich finde die Idee eigentlich ziemlich interessant, vor allem weil die Segmente und somit eigentlich auch der PM extra dafür gemacht sind. Warum wird das denn nicht gemacht? Nur weil Paging flexibler ist?
SwitchTask:
push ebp
push edi
push esi
push edx
push ecx
push ebx
push eax
push esp
call multitasking_scheduler
mov esp, eax
mov al, 0x20
out 0x20, al
pop eax
pop ebx
pop ecx
pop edx
pop esi
pop edi
pop ebp
push esp
call show_stack
add esp, 0x4
hlt
iret
SwitchTask:
push ebp
push edi
push esi
push edx
push ecx
push ebx
push eax
push esp
call multitasking_scheduler
mov eax, esp
mov al, 0x20
out 0x20, al
pop eax
pop ebx
pop ecx
pop edx
pop esi
pop edi
pop ebp
add esp, 0x8
push esp
call check_stack
add esp, 0x8
iret
void check_stack(unsigned int* stack){
for(int i = 0; i < 25; i++){
print(itoa(*(stack-i*4), 16), i*80, 0xF);
}
while(1);
}
SwitchTask:
push ebp
push edi
push esi
push edx
push ecx
push ebx
push eax
push esp
call multitasking_scheduler
mov eax, esp
pop eax
pop ebx
pop ecx
pop edx
pop esi
pop edi
pop ebp
add esp, 0x8
iret
Ja. Und natürlich den Stack wechseln statt add esp, 4.Was meinst du mit Stack wechseln? Es gibt doch nur ein esp.
struct cpu_state {
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
unsigned int esi;
unsigned int edi;
unsigned int ebp;
unsigned int int_no;
unsigned int err_code;
unsigned int eip;
unsigned int cs;
unsigned int eflags;
unsigned int esp;
unsigned int ss;
};
#include "system.h"
/** GLOBAL VARIABLES **/
void *IRQ_routines[16] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
/** GLOBAL FUNCTIONS **/
void IRQ_install_handler(int irq, void (*handler)(struct cpu_state *r));
void IRQ_uninstall_handler(int irq);
void IRQ_remap();
void IRQ_handler(struct cpu_state *r);
void IRQ_install();
extern void IRQ0();
extern void IRQ1();
extern void IRQ2();
extern void IRQ3();
extern void IRQ4();
extern void IRQ5();
extern void IRQ6();
extern void IRQ7();
extern void IRQ8();
extern void IRQ9();
extern void IRQ10();
extern void IRQ11();
extern void IRQ12();
extern void IRQ13();
extern void IRQ14();
extern void IRQ15();
void IRQ_install_handler(int irq, void (*handler)(struct cpu_state *r)){
IRQ_routines[irq] = handler;
}
void IRQ_uninstall_handler(int irq){
IRQ_routines[irq] = 0;
}
void IRQ_remap(){
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);
}
void IRQ_handler(struct cpu_state *r){
void (*handler)(struct cpu_state *r);
handler = IRQ_routines[r->int_no - 32];
if(handler) handler(r);
if(r->int_no >= 40){
outb(0xA0, 0x20);
}
outb(0x20, 0x20);
}
void IRQ_install(){
IRQ_remap();
CreateIDTGate(32, (unsigned)IRQ0, 0x08, 0x8E);
CreateIDTGate(33, (unsigned)IRQ1, 0x08, 0x8E);
CreateIDTGate(34, (unsigned)IRQ2, 0x08, 0x8E);
CreateIDTGate(35, (unsigned)IRQ3, 0x08, 0x8E);
CreateIDTGate(36, (unsigned)IRQ4, 0x08, 0x8E);
CreateIDTGate(37, (unsigned)IRQ5, 0x08, 0x8E);
CreateIDTGate(38, (unsigned)IRQ6, 0x08, 0x8E);
CreateIDTGate(39, (unsigned)IRQ7, 0x08, 0x8E);
CreateIDTGate(40, (unsigned)IRQ8, 0x08, 0x8E);
CreateIDTGate(41, (unsigned)IRQ9, 0x08, 0x8E);
CreateIDTGate(42, (unsigned)IRQ10, 0x08, 0x8E);
CreateIDTGate(43, (unsigned)IRQ11, 0x08, 0x8E);
CreateIDTGate(44, (unsigned)IRQ12, 0x08, 0x8E);
CreateIDTGate(45, (unsigned)IRQ13, 0x08, 0x8E);
CreateIDTGate(46, (unsigned)IRQ14, 0x08, 0x8E);
CreateIDTGate(47, (unsigned)IRQ15, 0x08, 0x8E);
}
void fault_handler(struct cpu_state *r){
if(r->int_no < 32){
print(exception_messages[r->int_no], 160+44, 0x07);
kernelerror();
restart_pc();
}
}
; ...
[EXTERN] IRQ_handler
IRQ_common_stub:
push ebp
push edi
push esi
push edx
push ecx
push ebx
push eax
push esp
call IRQ_handler
add esp, 4
pop eax
pop ebx
pop ecx
pop edx
pop esi
pop edi
pop ebp
add esp, 0x8
iret
void CreateTask(void* start_addr){
__asm__ __volatile__ ("cli");
struct cpu_state* task_state = pmm_malloc();
task_state->eax = 0;
task_state->ebx = 0;
task_state->ecx = 0;
task_state->edx = 0;
task_state->esi = 0;
task_state->edi = 0;
task_state->ebp = 0;
task_state->eip = (unsigned int) start_addr;
task_state->cs = 0x08;
task_state->eflags = 0x202;
Tasks[task_number+1].status = 1;
Tasks[task_number+1].stack = (unsigned int) task_state;
Tasks[task_number+1].PID = task_number+1;
task_number++;
__asm__ __volatile__ ("sti");
}
Das hat aber leider nichts geändert.
void task_a(){
print_char('a', -1, 0xF);
while(1);
}
void task_b(){
print_char('b', -1, 0xF);
while(1);
}
int main(){
install_start();
CreateTask(task_a);
CreateTask(task_b);
__asm__ __volatile__ ("int $0x20");
while(1);
return 0;
}
/** GLOBAL VARIABLES **/
struct struct_Task Tasks[MAX_TASK_NUM+1];
int task_number = 0;
int currentPID = 1;
/** GLOBAL FUNCTIONS **/
void InitMultitasking();
unsigned int multitasking_scheduler(unsigned int stack);
void CreateTask(void* start_addr);
void InitMultitasking(){
IRQ_install_handler(0, SwitchTask);
}
unsigned int multitasking_scheduler(unsigned int stack){
Tasks[currentPID].stack = stack;
while(!Tasks[currentPID].status == 1){
currentPID++;
if(currentPID > MAX_TASK_NUM) currentPID = 1;
}
print(itoa((unsigned int)Tasks[currentPID].stack), 80, 0xF); // 0x1FFF74
return Tasks[currentPID].stack;
}
void CreateTask(void* start_addr){
unsigned int* stack;
__asm__ __volatile__ ("cli");
stack = (void*)(pmm_malloc()+1024);
*stack-- = 0x202;
*stack-- = 0x8;
*stack-- = (unsigned int)start_addr;
*stack-- = 0x0;
*stack-- = 0x0;
*stack-- = 0x0;
*stack-- = 0x0;
*stack-- = 0x0;
*stack-- = 0x0;
*stack-- = 0x0;
*stack-- = 0x0;
*stack-- = 0x10;
*stack-- = 0x10;
*stack-- = 0x10;
*stack-- = 0x10;
Tasks[task_number+1].status = 1;
Tasks[task_number+1].stack = (unsigned int) stack;
Tasks[task_number+1].PID = task_number+1;
task_number++;
__asm__ __volatile__ ("sti");
}
[BITS 32]
[GLOBAL SwitchTask]
[EXTERN multitasking_scheduler]
SwitchTask:
push esp
call multitasking_scheduler
mov esp, eax
ret
=> 0x1000e8 <main+47>: int $0x20
(gdb)
0x00101111 in IRQ0 ()
1: x/i $pc
=> 0x101111 <IRQ0+1>: push $0x0
(gdb)
0x00101113 in IRQ0 ()
1: x/i $pc
=> 0x101113 <IRQ0+3>: push $0x20
(gdb)
0x00101115 in IRQ0 ()
1: x/i $pc
=> 0x101115 <IRQ0+5>: jmp 0x101180 <IRQ_common_stub>
(gdb)
0x00101180 in IRQ_common_stub ()
1: x/i $pc
=> 0x101180 <IRQ_common_stub>: pusha
(gdb)
0x00101181 in IRQ_common_stub ()
1: x/i $pc
=> 0x101181 <IRQ_common_stub+1>: push %ds
(gdb)
0x00101182 in IRQ_common_stub ()
1: x/i $pc
=> 0x101182 <IRQ_common_stub+2>: push %es
(gdb)
0x00101183 in IRQ_common_stub ()
1: x/i $pc
=> 0x101183 <IRQ_common_stub+3>: push %fs
(gdb)
0x00101185 in IRQ_common_stub ()
1: x/i $pc
=> 0x101185 <IRQ_common_stub+5>: push %gs
(gdb)
0x00101187 in IRQ_common_stub ()
1: x/i $pc
=> 0x101187 <IRQ_common_stub+7>: mov $0x10,%ax
(gdb)
0x0010118b in IRQ_common_stub ()
1: x/i $pc
=> 0x10118b <IRQ_common_stub+11>: mov %eax,%ds
(gdb)
0x0010118d in IRQ_common_stub ()
1: x/i $pc
=> 0x10118d <IRQ_common_stub+13>: mov %eax,%es
(gdb)
0x0010118f in IRQ_common_stub ()
1: x/i $pc
=> 0x10118f <IRQ_common_stub+15>: mov %eax,%fs
(gdb)
0x00101191 in IRQ_common_stub ()
1: x/i $pc
=> 0x101191 <IRQ_common_stub+17>: mov %eax,%gs
(gdb)
0x00101193 in IRQ_common_stub ()
1: x/i $pc
=> 0x101193 <IRQ_common_stub+19>: mov %esp,%eax
(gdb)
0x00101195 in IRQ_common_stub ()
1: x/i $pc
=> 0x101195 <IRQ_common_stub+21>: push %eax
(gdb)0x00101196 in IRQ_common_stub ()
1: x/i $pc
=> 0x101196 <IRQ_common_stub+22>: mov $0x1007ca,%eax
(gdb)
0x0010119b in IRQ_common_stub ()
1: x/i $pc
=> 0x10119b <IRQ_common_stub+27>: call *%eax
(gdb)
0x001007ca in IRQ_handler ()
1: x/i $pc
=> 0x1007ca <IRQ_handler>: push %esi
(gdb)
0x001007cb in IRQ_handler ()
1: x/i $pc
=> 0x1007cb <IRQ_handler+1>: push %ebx
(gdb)
0x001007cc in IRQ_handler ()
1: x/i $pc
=> 0x1007cc <IRQ_handler+2>: sub $0x4,%esp
(gdb)
0x001007cf in IRQ_handler ()
1: x/i $pc
=> 0x1007cf <IRQ_handler+5>: mov 0x10(%esp),%ebx
(gdb)
0x001007d3 in IRQ_handler ()
1: x/i $pc
=> 0x1007d3 <IRQ_handler+9>: mov 0x30(%ebx),%eax
(gdb)
0x001007d6 in IRQ_handler ()
1: x/i $pc
=> 0x1007d6 <IRQ_handler+12>: mov 0x1241c0(,%eax,4),%esi
(gdb)
0x001007dd in IRQ_handler ()
1: x/i $pc
=> 0x1007dd <IRQ_handler+19>: test %esi,%esi
(gdb)
0x001007df in IRQ_handler ()
1: x/i $pc
=> 0x1007df <IRQ_handler+21>: je 0x1007ea <IRQ_handler+32>
(gdb)
0x001007e1 in IRQ_handler ()
1: x/i $pc
=> 0x1007e1 <IRQ_handler+23>: sub $0xc,%esp
(gdb)
0x001007e4 in IRQ_handler ()
1: x/i $pc
=> 0x1007e4 <IRQ_handler+26>: push %ebx
(gdb)
0x001007e5 in IRQ_handler ()
1: x/i $pc
=> 0x1007e5 <IRQ_handler+27>: call *%esi
(gdb)
Breakpoint 1, 0x001011b0 in SwitchTask ()
1: x/i $pc
=> 0x1011b0 <SwitchTask>: push %esp
(gdb)
0x001011b1 in SwitchTask ()
1: x/i $pc
=> 0x1011b1 <SwitchTask+1>: call 0x100cb4 <multitasking_scheduler>
(gdb)
0x00100cb4 in multitasking_scheduler ()
1: x/i $pc
=> 0x100cb4 <multitasking_scheduler>: push %ebx
(gdb)
0x00100cb5 in multitasking_scheduler ()
1: x/i $pc
=> 0x100cb5 <multitasking_scheduler+1>: mov 0x1021c0,%eax
(gdb)
0x00100cba in multitasking_scheduler ()
1: x/i $pc
=> 0x100cba <multitasking_scheduler+6>: lea (%eax,%eax,2),%edx
(gdb)
0x00100cbd in multitasking_scheduler ()
1: x/i $pc
=> 0x100cbd <multitasking_scheduler+9>: mov 0x8(%esp),%ecx
(gdb)
0x00100cc1 in multitasking_scheduler ()
1: x/i $pc
=> 0x100cc1 <multitasking_scheduler+13>: mov %ecx,0x122ac4(,%edx,4)
(gdb)
0x00100cc8 in multitasking_scheduler ()
1: x/i $pc
=> 0x100cc8 <multitasking_scheduler+20>: mov $0x1,%ebx
(gdb)
0x00100ccd in multitasking_scheduler ()
1: x/i $pc
=> 0x100ccd <multitasking_scheduler+25>:
jmp 0x100cdc <multitasking_scheduler+40>
(gdb)
0x00100cdc in multitasking_scheduler ()
1: x/i $pc
=> 0x100cdc <multitasking_scheduler+40>: lea (%eax,%eax,2),%edx
(gdb)
0x00100cdf in multitasking_scheduler ()
1: x/i $pc
=> 0x100cdf <multitasking_scheduler+43>: lea 0x122ac8(,%edx,4),%edx
(gdb)
0x00100ce6 in multitasking_scheduler ()
1: x/i $pc
=> 0x100ce6 <multitasking_scheduler+50>: cmpb $0x0,(%edx)
(gdb)
0x00100ce9 in multitasking_scheduler ()
1: x/i $pc
=> 0x100ce9 <multitasking_scheduler+53>:
je 0x100ccf <multitasking_scheduler+27>
(gdb)
0x00100ceb in multitasking_scheduler ()
1: x/i $pc
=> 0x100ceb <multitasking_scheduler+55>: mov %eax,0x1021c0
(gdb)
0x00100cf0 in multitasking_scheduler ()
1: x/i $pc
=> 0x100cf0 <multitasking_scheduler+60>: lea (%eax,%eax,2),%eax
(gdb)
0x00100cf3 in multitasking_scheduler ()
1: x/i $pc
=> 0x100cf3 <multitasking_scheduler+63>: mov 0x122ac4(,%eax,4),%eax
(gdb)
0x00100cfa in multitasking_scheduler ()
1: x/i $pc
=> 0x100cfa <multitasking_scheduler+70>: pop %ebx
(gdb)
0x00100cfb in multitasking_scheduler ()
1: x/i $pc
=> 0x100cfb <multitasking_scheduler+71>: ret
(gdb)
0x001011b6 in SwitchTask ()
1: x/i $pc
=> 0x1011b6 <SwitchTask+6>: mov %eax,%esp
(gdb)
0x001011b8 in SwitchTask ()
1: x/i $pc
=> 0x1011b8 <SwitchTask+8>: ret
(gdb)
0x001007e7 in IRQ_handler ()
1: x/i $pc
=> 0x1007e7 <IRQ_handler+29>: add $0x10,%esp
(gdb)
0x001007ea in IRQ_handler ()
1: x/i $pc
=> 0x1007ea <IRQ_handler+32>: cmpl $0x27,0x30(%ebx)
(gdb)
0x001007ee in IRQ_handler ()
1: x/i $pc
=> 0x1007ee <IRQ_handler+36>: jbe 0x100802 <IRQ_handler+56>
(gdb)
0x00100802 in IRQ_handler ()
1: x/i $pc
=> 0x100802 <IRQ_handler+56>: sub $0x8,%esp
(gdb)
0x00100805 in IRQ_handler ()
1: x/i $pc
=> 0x100805 <IRQ_handler+59>: push $0x20
(gdb)
0x00100807 in IRQ_handler ()
1: x/i $pc
=> 0x100807 <IRQ_handler+61>: push $0x20
(gdb)
0x00100809 in IRQ_handler ()
1: x/i $pc
=> 0x100809 <IRQ_handler+63>: call 0x100fac <outb>
(gdb)
0x00100fac in outb ()
1: x/i $pc
=> 0x100fac <outb>: push %ebp
(gdb)
0x00100fad in outb ()
1: x/i $pc
=> 0x100fad <outb+1>: mov %esp,%ebp
(gdb)
0x00100faf in outb ()
1: x/i $pc
=> 0x100faf <outb+3>: mov 0x8(%ebp),%dx
(gdb)
0x00100fb3 in outb ()
1: x/i $pc
=> 0x100fb3 <outb+7>: mov 0xc(%ebp),%al
(gdb)
0x00100fb6 in outb ()
1: x/i $pc
=> 0x100fb6 <outb+10>: out %al,(%dx)
(gdb)
0x00100fb7 in outb ()
1: x/i $pc
=> 0x100fb7 <outb+11>: mov %ebp,%esp
(gdb)
0x00100fb9 in outb ()
1: x/i $pc
=> 0x100fb9 <outb+13>: pop %ebp
(gdb)
0x00100fba in outb ()
1: x/i $pc
=> 0x100fba <outb+14>: ret
(gdb)
0x0010080e in IRQ_handler ()
1: x/i $pc
=> 0x10080e <IRQ_handler+68>: add $0x14,%esp
(gdb)
0x00100811 in IRQ_handler ()
1: x/i $pc
=> 0x100811 <IRQ_handler+71>: pop %ebx
(gdb)
0x00100812 in IRQ_handler ()
1: x/i $pc
=> 0x100812 <IRQ_handler+72>: pop %esi
(gdb)
0x00100813 in IRQ_handler ()
1: x/i $pc
=> 0x100813 <IRQ_handler+73>: ret
(gdb)
0x0010119d in IRQ_common_stub ()
1: x/i $pc
=> 0x10119d <IRQ_common_stub+29>: pop %eax
(gdb)
0x0010119e in IRQ_common_stub ()
1: x/i $pc
=> 0x10119e <IRQ_common_stub+30>: pop %gs
(gdb)
0x0010119f in IRQ_common_stub ()
1: x/i $pc
=> 0x10119f <IRQ_common_stub+32>: pop %fs
(gdb)
0x001011a2 in IRQ_common_stub ()
1: x/i $pc
=> 0x1011a2 <IRQ_common_stub+34>: pop %es
(gdb)
0x001011a3 in IRQ_common_stub ()
1: x/i $pc
=> 0x1011a3 <IRQ_common_stub+35>: pop %ds
(gdb)
0x001011a4 in IRQ_common_stub ()
1: x/i $pc
=> 0x1011a4 <IRQ_common_stub+36>: popa
(gdb)
0x001011a5 in IRQ_common_stub ()
1: x/i $pc
=> 0x1011a5 <IRQ_common_stub+37>: add $0x8,%esp
(gdb)
0x001011a8 in IRQ_common_stub ()
1: x/i $pc
=> 0x1011a8 <IRQ_common_stub+40>: iret
(gdb)
0x001000ea in main ()
1: x/i $pc
=> 0x1000ea <main+49>: add $0x10,%esp
(gdb)
0x001000ed in main ()
1: x/i $pc
=> 0x1000ed <main+52>: jmp 0x1000ed <main+52>
(gdb)
0x001000ed in main ()
1: x/i $pc
=> 0x1000ed <main+52>: jmp 0x1000ed <main+52>
(gdb)
0x001000ed in main ()
1: x/i $pc
=> 0x1000ed <main+52>: jmp 0x1000ed <main+52>
(gdb)
0x001000ed in main ()
1: x/i $pc
=> 0x1000ed <main+52>: jmp 0x1000ed <main+52>
(gdb)
0x001000ed in main ()
1: x/i $pc
=> 0x1000ed <main+52>: jmp 0x1000ed <main+52>
(gdb)
0x001000ed in main ()
1: x/i $pc
=> 0x1000ed <main+52>: jmp 0x1000ed <main+52>
(gdb)