Assembler - язык неограниченных возможностей


Переключение задач - часть 4


; задача 1 task_1: mov byte ptr ds:[edi],al ; вывести символ на экран inc al ; увеличить код символа add edi,2 ; увеличить адрес символа ; переключиться на задачу 0 db 0EAh dd 0 dw SEL_TSS0 ; сюда будет приходить управление, когда задача 0 начнет выполнять переход ; на задачу 1 во всех случаях, кроме первого mov ecx,02000000h ; небольшая пауза, зависящая от скорости loop $ ; процессора jmp task_1

PM_seg ends

stack_seg segment para stack "STACK" stack_start db 100h dup(?) ; стек задачи 0 stack_l = $ - stack_start stack_task2 db 100h dup(?) ; стек задачи 1 stack_l2 = $ - stack_start stack_seg ends

end start

Чтобы реализовать многозадачность в реальном времени в нашем примере, достаточно создать обработчик прерывания системного таймера IRQ0 в виде отдельной (третьей) задачи и поместить в IDT шлюз этой задачи. Текст обработчика для нашего примера мог быть крайне простым:

task_3: ; это отдельная задача - не нужно сохранять регистры! mov al,20h out 20h,al jmp task_0 mov al,20h out 20h,al jmp task_1 jmp task_3

Но при вызове обработчика прерывания старая задача помечается как занятая в GDT и повторный JMP на нее приведет к ошибке. Вызов задачи обработчика прерывания, так же как и вызов задачи командой CALL, подразумевает, что она завершится командой IRET. Именно команду IRET оказывается проще всего вызвать для передачи управления из такого обработчика — достаточно только подменить селектор вызвавшей нас задачи в поле связи и выполнить IRET.

task_3: ; при инициализации DS должен быть установлен на PM_seg mov al,20h out 20h,al mov word ptr TSS_3,SEL_TSS0 iret mov al,20h out 20h,al mov word ptr TSS_3,SEL_TSS1 iret jmp task_3

Единственное дополнительное изменение, которое нужно внести, — инициализировать дескриптор TSS задачи task_1 уже как занятый, так как управление на него будет передаваться командой IRET, что, впрочем, не составляет никаких проблем.

Помните, что во вложенных задачах команда IRET не означает конца программы — следующий вызов задачи всегда передает управление на следующую после IRET команду.





Начало  Назад  Вперед