Модуль mtasks.asm
CodingУстановка новых прерываний, реализация многозадачности.
;# Тут мы получаем старые вектора ############################################
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