В общем есть три задачи: главная, задача №1 и задача №2. Есть Шлюз задачи он находится на IRQ0. На все остальных аппратных прерываниях стоит обычный шлюз прерывания (с пустыми обработчиками). идея такая: на каждом первом прерывании (irq0) возвращаю управление главной задаче, на каждом втором прерывании возвращаю управление задаче №1, на каждом третьем - задача №2, на каждом четвёртом главной задаче. с кодом главной задачи проблем нет и он заканчивается так Код (Text): MainTask: ;загружаем IDTR, инициализируем контроллеры прерываний..... .... sti jmp $ с кодом задачи №1 и задачи №2 тоже проблем нет, объявлены они так Код (Text): TASK_NUMBER_1: jmp $ TASK_NUMBER_2: jmp $ проблема с кодом обработчика irq0 (шлюз задачи) Код (Text): counter dd 0h db 0 irq0_handler: .repeat: mov edi, Irq0_handler_Tss virtual at edi .edi TSS32 ; структуру объявил сам, с ней тоже вроде проблем нет end virtual cli inc dword [counter] mov edx, [counter] and edx, 011b cmp edx, 0 jz .end_dispatch cmp edx, 11b jnz @f mov [.edi.PreviousTaskLink],MainTask_Selektor jmp .end_dispatch @@: cmp edx, 01b jnz @f mov [.edi.PreviousTaskLink], TASK_NUMBER_1_Selektor jmp .end_dispatch @@: cmp edx, 10b mov [.edi.PreviousTaskLink],TASK_NUMBER_2_Selektor .end_dispatch: mov al, 20h out 020h, al out 0a0h, al sti iretd jmp .repeat тестирую в Bochs 2.3, проблема в том что программа застревает при первой же генерации прерывания IRQ0. c сообщением ired : CF делал так что бы во всех случаях в поле PreviousTaskLink ставилось значение MainTask_Selektor, всё работало! Вопрос: почему не работает, с тремя задачами.
бит B в дескрипторе TSS, который соответствует заменяемому селектору, сбрасывается? см. 3А, 6.4.2 (Modifying Task Linkages)
Возможно, проблема в флаге занятости задачи. Перед тем как выходить в задачу по iret необходимо поставить флаг занятости во входящей задаче. Ну и соответсвенно снять его в той, которая лежит в prev_task, иначе в нее нельзя будет войти повторно. rei3er опередил .
всё понятно! TASK_NUMBER_1_Selektor у меня НЕ busy (как и TASK_NUMBER_2_Selektor). т.е. при выходе по команде iret, в новой задаче должен быть выставлен бит busy. и ещё 3A, 6.3 (пункт 4).
ОПЯТЬ ПРОБЛЕМА! теперь почему то не вызывается обработчик прерывания. управление передаётся первой задаче и остаётся там навсегда. После выкидывания лишних наворотов и примочек от ообработчика прерывания осталось вот это : Код (Text): interrupt_mes db "Interupt message " counter dd 11111111h db 0 irq0_handler: mov edi, Irq0_handler_Tss virtual at edi .edi TSS32 end virtual .repeat: inc dword [counter] ; передача параметров функции для вывода строки mov esi,interrupt_mes ; указатель на ZS строку mov al, 0 ;столбец mov ah, 4 ;строка mov bl, "5" ;цвет символа и цвет фона call OutText ;после строки должны выводится четыре закорючки ;эта функция работает нормально проблем с ней нет cli xor eax, eax mov ax, [.edi.PreviousTaskLink] call ClearBusyFlag cmp ax, TASK_NUMBER_1_Selektor jz @f mov ax, TASK_NUMBER_1_Selektor call SetBusyFlag mov [.edi.PreviousTaskLink], TASK_NUMBER_1_Selektor jmp .end_dispatch @@: mov ax, TASK_NUMBER_2_Selektor call SetBusyFlag mov [.edi.PreviousTaskLink], TASK_NUMBER_2_Selektor .end_dispatch: mov al, 20h out 020h, al out 0a0h, al sti iretd jmp .repeat соглано этому коду обработчик прерывания получив управление первый раз, передаст управление задаче №1, потом по очереди при каждом вызове передавать управление обоим задачам. но так не получается: задача №1 получает управление навсегда (тестил так: кидал в обе задачи код вывода строки, задача №2 строку не выводит, а задача №1 выводит). а обработчик прерывания после первого вызова никогда не получает управление, т.е. после строки "Interupt message " стоят неподвижно 4 закорючки, хотя четыре закорючки должны постоянно изменяться. Задача №1 и №2 пустые: в них только одна команда- jmp $. Функции SetBusyFlag и ClearBusyFlag тестил отдельно, работают нормально. У в чем же может быть причина того что обработчик прерывания не вызывается повторно?
Не совсем понял, кто должен печатать "закорючку", если обе задачи состоят из 'jmp $', а обработчик прерывания, судя по коду, печатает строку а одном и том же месте? А сам код, вроде, правильный.
Код (Text): interrupt_mes db "Interupt message " ;;здесь нет нуля counter dd 11111111h ;; это и есть закорючки db 0 ;; <-----ноль counter инкрементится при каждом вызове обработчика, и строка выводится самим обработчиком, отличаться должны только четыре последних "закорючки" Код (Text): inc dword [counter] ............... call OutText проблема не в закорючках (просто ещё нет преобразователя числа в строку), а пролема в том что обработчик вызывается только один раз, т.е. закорючки у меня не меняются, а должны постоянно изменяться (при каждом вызове обработчика).
пробуй так Код (Text): mov al, 20h out 020h, al out 0a0h, al sti and dword [0FEE000B0h], 0 ;Local APIC EOI ...
rpy3uH может в TSS задачи, которой соответствует TASK_NUMBER_1_Selektor, сброшен IF в EFLAGS? тогда в контексте этой задачи все маскируемые прерывания запрещены