CodeNet / Платформы / Пишем ОС / Пишем "многозадачную" ОС в "Real Mode"
Новый обработчик прерываний.
Прежде чем рассматривать этот раздел, советую ознакомится со структурой TTASK.
Вот тут-то и есть самое интересное, тут приведен возможный вариант прерывания 08h, раскажу как все это работает по ходу дела:
PROC kernel ; Прерывание 008h pushf call [Dword Ptr cs:oldofs08]
Человек, не так давно пишущий на ассемблере, может сразу не понять суть этих двух строк, но на самом деле все просто, (pushf) - сохраняем регистр флагов, и потом (call [Dword Ptr cs:oldofs08]) вызываем старый обрабочик прерывания (благодоря этому мою OS можно запусть из-под самой себя, как отдельную задачу). Эти две команды эмудируют приход прерывания - комаду int 08h. Таким образом, после выполнения iret IP будет указывать не следующую после call'а команду.
push di push bx push ax push es push ds push sicmp [cs:int08],0 ;¬ Если нельзя переключать задачи, je kernelend ;+ то не переключаем их.Тут мы сохранили первую партию регистров, все мы сохранить не можем, так как иначе потеряем стек предыдущей задачи (или стек ядра).
Если переменная int08 равна нулю, то задачу переключать не будем - это такой способ выключения прерывания :)))))
mov si,sp ;¬ mov ax,ss ;¦ ES:SI=SS:SP mov es,ax ;+ ; Инитим DS push cs pop ds
Вот тут мы сохраняем стек старой задчи, и иницализируем сегментные регистры для выполнения прерывания.
; Ищем стек задачи lea di,[ds:firsttask] ; DI = Адрес начала структуры TTASK mov al,[ds:numtask] ; AL = Номер задачи xor ah,ah ; AX = Номер задачи push dx mov dx,515 mul dx ; AX = Смещения от начала firsttask pop dx add di,ax ; DI = Абсолютное смещение вершины ; стека в структуре TTASK mov [Word Ptr ds:di+5],ss mov [Word Ptr ds:di+7],sp ; С учетом приоритетов -------------------¬ dec [Word Ptr ds:di+9] ; ¦ cmp [Word Ptr ds:di+9],0 ; ¦ jne kernelend ; ¦ mov ax,[Word Ptr ds:di+11] ; ¦ mov [Word Ptr ds:di+9],ax ;-- kernel_01: add di,515 ;¬SP=DI+515 mov sp,di ;- mov ax,ds ;¬SS=DS mov ss,ax ;-
Вот этот страшный кусок кода, распределяет приоритеты (если приоритет высокий, то просто несколько раз не переключаем задачи - и текущая задача работает дольше)
; Сохранаяем 'остальные' регистры в структуре TTASK push si ; SP push es ; SS push cx ; CX push dx ; DX push bp ; BP
И самое интересное - тут происходит сохранение остальных регистров, но уже не в стек задачи, а в структуру TTASK. В этой структуре помимо всего сохраняется SS:SP (теперь уже ES:SI) указывающие на стек задачи, в котром сохранены остальныу регистры.
; Ещем следующую задачу int08new: xor ax,ax mov al,[ds:numtask] nexttask: inc al ;_следующую_ lea di,[ds:firsttask] cmp al,9 jne int201 xor ax,ax
Тут мы проходимся по дескрипторам задач, и ищем следующую.
int201: push ax mov dx,515 mul dx add di,ax ; DI = Абсолютное смещение вершины ; стека в структуре TTASK pop ax cmp [Byte Ptr ds:di],255 je nexttask
Проверим загружена ли эта задача, если нет, то переходим к следующей.
cmp [Byte Ptr ds:di],254 ; Приостановленная задача je nexttask
Проверим приостановлена ли эта задача, если да, то переходим к следующей.
mov [ds:numtask],al mov ax,di add ax,(515-10) mov sp,ax ; В SP имеем стек (тот что в структуре ; TTASK) следующей задачи push ds pop ss
Нашли регисты сохраненые в структуре TTASK новой задачи.
; Востанавливаем оттуда 'остальные' регистры следующей задачи pop bp pop dx pop cx pop es pop si
Восстановили их.
; SS:SP теперь должны указывать на реальный стек задачи mov ax,es ;¬ mov ss,ax ;¦ SS:SP=ES:SI mov sp,si ;-
Нашли основной стек новой задачи.
kernelend: pop si pop ds pop es pop ax pop bx pop di
И восстановили остальные регистры. Теперь SS:SP указывает на стек новой задачи, и следовательно после оканчания прерывания выполнятся будет другая задача.
push ax mov al,20h out 20h,al pop ax
А вот это обязательно - посылаем контроллеру прерывания команду "конец прерывания". (Прерывание int 08h ведь аппаратное)
iret ENDP kernel
Оставить комментарий
Комментарии
Кто-нибудь, подскажите какие регистры
и в каком порядке хардвар запихивает в стек
при возникновении прерывания?
Просто "эмудируют приход прерывания"
забавно звучит