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 si
Тут мы сохранили первую партию регистров, все мы сохранить не можем, так как
иначе потеряем стек предыдущей задачи (или стек ядра).
cmp [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
Оставить комментарий
Комментарии


Кто-нибудь, подскажите какие регистры
и в каком порядке хардвар запихивает в стек
при возникновении прерывания?


Просто "эмудируют приход прерывания"
забавно звучит
