CodeNet / Языки программирования / Ассемблер / Пишем "многозадачную" ОС в "Real Mode"
CodeNet / Платформы / Пишем ОС / Пишем "многозадачную" ОС в "Real Mode"
CodeNet / Платформы / Пишем ОС / Пишем "многозадачную" ОС в "Real Mode"
Модуль 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
Оставить комментарий
Оставлять комментарии могут только зарегистрированные пользователи.
Если вы не являетесь зарегистрированным пользователем, то вам необходимо зарегистрироваться. Регистрация бесплатна. Если вы уже зарегистрированы на CodeNet, то вам необходимо ввести логин и пароль в верхней (Alt-U) части страницы.
