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

Ваш аккаунт

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

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

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

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

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

Модуль mtasks.asm

Установка новых прерываний, реализация многозадачности.

;# Тут мы получаем старые вектора ############################################
PROC           getvectors
               ; Сохраняем 08h и 20h прерывания
   IFDEF GlukOS   ;--- Для ГлюкОСы
               call    _di
               push    ds
               xor     bx,bx
               mov     ds,bx
               mov     bx,[ds:0020h]
               mov     es,[ds:0022h]
               mov     [cs:oldseg08],es
               mov     [cs:oldofs08],bx
               mov     bx,[ds:0080h]
               mov     es,[ds:0082h]
               mov     [cs:oldseg20],es
               mov     [cs:oldofs20],bx
               pop     ds
               call    _ei
               ret
   ELSE        ;--- Для ДОСа
               mov     ah,035h
               mov     al,008h
               int     021h
               mov     [cs:oldseg08],es
               mov     [cs:oldofs08],bx
               mov     ah,035h
               mov     al,020h
               int     021h
               mov     [cs:oldseg20],es
               mov     [cs:oldofs20],bx
               ret
   ENDIF       ;--- GlukOS
ENDP           getvectors
;# Тут мы вешаем новые - свои прерывания #####################################
PROC           setvectors
               ; Вешаемся на 08h и 20h прерывания
   IFDEF GlukOS   ;--- Для ГлюкОСы
               call    _di
               push    ds
               xor     bx,bx
               mov     ds,bx
               lea     bx,[cs:kernel]
               mov     [ds:0020h],bx
               mov     [ds:0022h],cs
               lea     bx,[newint20]
               mov     [ds:0080h],bx
               mov     [ds:0082h],cs
               pop     ds
               call    _ei
               ret
   ELSE        ;--- Для ДОСа
               push    ds
               mov     ax,cs
               mov     ds,ax
               lea     dx,[kernel]
               mov     ah,025h
               mov     al,008h
               int     021h
               ; Вешаемся на 20h прерывание
               mov     ax,cs
               mov     ds,ax
               lea     dx,[newint20]
               mov     ah,025h
               mov     al,020h
               int     021h
               pop     ds
               ret
   ENDIF       ;--- GlukOS
ENDP           setvectors
;# Тут мы восстанавливаем старoе прерывания ##################################
PROC           restorevectors
               ; Восстанавлмваем 08h и 20h прерывания
   IFDEF GlukOS   ;--- Для ГлюкОСы
               call    _di
               push    ds
               xor     bx,bx
               mov     ds,bx
               mov     es,[cs:oldseg08]
               mov     bx,[cs:oldofs08]
               mov     [ds:0020h],bx
               mov     [ds:0022h],es
               mov     es,[cs:oldseg20]
               mov     bx,[cs:oldofs20]
               mov     [ds:0080h],bx
               mov     [ds:0082h],es
               pop     ds
               call    _ei
               ret
   ELSE        ;--- Для ДОСа
               push  ds
               mov   ax,[cs:oldseg08]
               mov   ds,ax
               mov   dx,[cs:oldofs08]
               mov   ah,025h
               mov   al,008h
               int   021h
               mov   ax,[cs:oldseg20]
               mov   ds,ax
               mov   dx,[cs:oldofs20]
               mov   ah,025h
               mov   al,020h
               int   021h
               pop   ds
               ret
   ENDIF       ;--- GlukOS
ENDP           restorevectors
; # Переменные в кодовом сегменте ############################################
oldofs08       DW    ?
oldseg08       DW    ?
oldofs20       DW    ?
oldseg20       DW    ?
int08          DW    1                   ; Стоит ли переключать задачи ???
; # Разрешаем переключать задачи #############################################
PROC           _ei
               mov   [Word Ptr cs:int08],1
               ret
ENDP           _ei
; # Запрещаем переключать задачи #############################################
PROC           _di
               mov   [Word Ptr cs:int08],0
               ret
ENDP          _di
;# Прерывание 020h ###########################################################
PROC           newint20                  ; Прерывание 020h (выгрузка задачи)
               call  _di
               pop   ax                  ;¬
               pop   ax                  ;¦ Достаем всякое дерьмо из стека
               pop   ax                  ;+
               push  cs
               pop   ds
               lea   di,[cs:firsttask]   ; DI = Адрес начала структуры TTASK
               mov   al,[cs:numtask]     ; AL = Номер задачи
               xor   ah,ah               ; AX = Номер задачи
               push  dx
                mov   dx,515
                mul   dx                 ; AX = Смещения от начала firsttask
               pop   dx
               add   di,ax               ; DI = Абсолютное смещение вершины
                                         ; стека в структуре TTASK
               mov   [Byte Ptr cs:di],255
               mov   dx,[cs:di+3]
               call    FreeMemory
               call  _ei
               jmp   int08new
ENDP           newint20
;# Прерывание 008h ###########################################################
PROC           kernel                   ; Прерывание 008h
               pushf
               call  [Dword Ptr cs:oldofs08]
               push  di
               push  bx
               push  ax
               push  es
               push  ds
               push  si
               cmp   [cs:int08],0        ;¬ Если нельзя переключать задачи,
               je    kernelend           ;+    то не переключаем их.
               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
               ; Ещем следующую задачу
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
               ; Востанавливаем оттуда 'остальные' регистры следующей задачи
               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
               push  ax
               mov   al,20h
               out   20h,al
               pop   ax
               iret
ENDP           kernel
; Инициализируем дескрипторы задач ###########################################
PROC           inittasks
               mov   [Byte Ptr cs:firsttask],0
               mov   [Byte Ptr cs:tasknum],0
               mov   [Byte Ptr cs:numtask],0
               lea   si,[tasks]
               mov   cx,8
it1:           mov   [Byte Ptr cs:si],255
               mov   [Byte Ptr cs:si+1],254
               add   si,515
               loop  it1
               ret
ENDP           inittasks

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

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог