Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Последние темы форума

Показать новые сообщения »

Почтовая рассылка

Подписчиков: 11639
Последний выпуск: 19.06.2015

Новый обработчик прерываний.

Прежде чем рассматривать этот раздел, советую ознакомится со структурой 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

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
66K
09 декабря 2010 года
Forward Space FCG
0 / / 09.12.2010
Мне нравитсяМне не нравится
1 апреля 2011, 19:28:39
Извините за ОЧЕНЬ ламерский вопрос :}].
Кто-нибудь, подскажите какие регистры
и в каком порядке хардвар запихивает в стек
при возникновении прерывания?
2.
Аноним
Мне нравитсяМне не нравится
9 февраля 2006, 06:19:41
Я не пошляк
Просто "эмудируют приход прерывания"
забавно звучит
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог