マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

アセンブラに切り替えても動かなかった

アセンブラに切り替えればうまくいくんじゃないかと思っていたが甘かったようだ。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++;
}