アセンブラに切り替えればうまくいくんじゃないかと思っていたが甘かったようだ。bochsによればESレジスタが異常な値を取ってるらしい、もう諦めてTSSを使うことにするか
コンテキストスイッチの部分(NASM)
;特権レベル3への切り替え asmContextSwitchToUser: MOV EBX, [g_CurrentTask] MOV ECX, DWORD[g_TSS] MOV EAX, DWORD[EBX + 60] ;g_CrrentTaskからesp0を取り出す MOV DWORD[ECX + 4], EAX ;g_TSSへespの設定 MOV EAX, DWORD[EBX + 0] MOV ECX, DWORD[EBX + 4] MOV EDX, DWORD[EBX + 8] MOV ESP, DWORD[EBX + 16] MOV EBP, DWORD[EBX + 20] MOV ESI, DWORD[EBX + 24] MOV EDI, DWORD[EBX + 28] PUSH DWORD[EBX + 56] ;PUSH SS PUSH DWORD[EBX + 52] ;PUSH ESP PUSH DWORD[EBX + 48] ;PUSH EFALGS PUSH DWORD[EBX + 44] ;PUSH CS PUSH DWORD[EBX + 40] ;PUSH EIP MOV ES, WORD[EBX + 32] MOV DS, WORD[EBX + 36] MOV EBX, DWORD[EBX + 12] IRETD ;特権レベル0への切り替え asmContextSwitchToKernel: MOV EBX, [g_CurrentTask] ;g_CurrentTaskからesp0を取り出し MOV ECX, DWORD[g_TSS] ;g_TSSへesp0の設定 MOV EAX, DWORD[EBX + 60] MOV DWORD[ECX + 4], EAX MOV EAX, DWORD[EBX + 0] MOV ECX, DWORD[EBX + 4] MOV EDX, DWORD[EBX + 8] MOV ESP, DWORD[EBX + 16] MOV EBP, DWORD[EBX + 20] MOV ESI, DWORD[EBX + 24] MOV EDI, DWORD[EBX + 28] PUSH DWORD[EBX + 48] ;PUSH EFLAGS PUSH DWORD[EBX + 44] ;PUSH CS PUSH DWORD[EBX + 40] ;PUSH EIP MOV ES, WORD[EBX + 32] MOV DS, WORD[EBX + 36] MOV EBX, DWORD[EBX + 12] IRETD
g_CurrentTaskの変数の型の構造体
typedef struct{ int eax; //0 int ecx; //4 int edx; //8 int ebx; //12 int esp2; //16 int ebp; //20 int esi; //24 int edi; //28 int es; //32 int ds; //36 int eip; //40 int cs; //44 int eflags; //48 int esp; //52 int ss; //56 int esp0; //60 }TaskData;
アセンブラの呼び出し部分
void timerHandler(){ IO::writePort8(PIC0_OCW2, 0x60); g_TimerManager->tick(); currentTask = (currentTask + 1) % taskCount; g_CurrentTask = &taskData[currentTask]; if(count++ > 1) return; if((g_CurrentTask->cs & 3) > 0) asmContextSwitchToUser(); else asmContextSwitchToKernel(); return; }
タスク追加部分
void addTask(int eip){ taskData[taskCount].eip = eip; char* esp = new char[8 * 1024]; esp = esp + (8 * 1024); char* esp0 = new char[8 * 1024]; esp = esp0 + (8 * 1024); taskData[taskCount].esp = (int)esp; taskData[taskCount].esp2 = (int)esp; taskData[taskCount].esp0 = (int)esp0; taskData[taskCount].eflags = 0x200; taskData[taskCount].cs = 3 * 8 + 3; taskData[taskCount].ss = 4 * 8 + 3; taskData[taskCount].ds = 4 * 8 + 3; taskData[taskCount].es = 4 * 8 + 3; taskCount++; }