46166 (665415), страница 3
Текст из файла (страница 3)
void sem_wait(int sem)
{
while (1)
{
asm cli
// проверяем семафор
if (semaphore[sem])
break;
asm sti // ожидаем установки семафора
asm nop
asm nop
}
asm sti
}
4.6 Файл TIMER.C. Процедуры для работы с таймером и диспетчер задач.
Cодержит обработчик аппаратного прерывания таймера, который периодически выдаёт звуковой сигнал и инициирует работу диспетчера задач. Диспетчер задач циклически перебирает селекторы TSS задач, участвующих в процессе разделения времени, возвращая селектор той задачи, которая должна стать активной. В самом конце обработки аппаратного прерывания таймера происходит переключение именно на эту задачу.
#include
#include
#include
#include
#include "tos.h"
// -------------------------------------------
// Модуль обслуживания таймера
// -------------------------------------------
#define EOI 0x20
#define MASTER8259A 0x20
extern void beep(void);
extern void flipflop_task(void);
void Timer_int(void);
word dispatcher(void);
word timer_cnt;
// ------------------------------------------
// Обработчик аппаратного прерывания таймера
// ------------------------------------------
void Timer_int(void)
{
asm pop bp
// Периодически выдаём звуковой сигнал
timer_cnt += 1;
if ((timer_cnt & 0xf) == 0xf)
{
beep();
}
// Выдаём в контроллер команду конца
// прерывания
asm mov al,EOI
asm out MASTER8259A,al
// Переключаемся на следующую задачу,
// селектор TSS которой получаем от
// диспетчера задач dispatcher()
jump_to_task(dispatcher());
asm iret
}
// --------------------------------------
// Диспетчер задач
// --------------------------------------
// Массив селекторов, указывающих на TSS
// задач, участвующих в параллельной работе,
// т.е. диспетчеризуемых задач
word task_list[] =
{
MAIN_TASK_SELECTOR,
FLIP_TASK_SELECTOR,
KEYBIN_TASK_SELECTOR,
TASK_2_SELECTOR
};
word current_task = 0; // текущая задача
word max_task = 3; // количество задач - 1
// Используем простейший алгоритм диспетчеризации -
// выполняем последовательное переключение на все
// задачи, селекторы TSS которых находятся
// в массиве task_list[].
word dispatcher(void)
{
if (current_task < max_task)
current_task++;
else
current_task = 0;
return(task_list[current_task]);
}
4.7 Файл EXCEPT.C. Обработка исключений.
#include
#include
#include
#include
#include "tos.h"
void prg_abort(int err);
// Номер текущей строки для вывода на экран
extern unsigned int y;
// Обработчики исключений
void exception_0(void) { prg_abort(0); }
void exception_1(void) { prg_abort(1); }
void exception_2(void) { prg_abort(2); }
void exception_3(void) { prg_abort(3); }
void exception_4(void) { prg_abort(4); }
void exception_5(void) { prg_abort(5); }
void exception_6(void) { prg_abort(6); }
void exception_7(void) { prg_abort(7); }
void exception_8(void) { prg_abort(8); }
void exception_9(void) { prg_abort(9); }
void exception_A(void) { prg_abort(0xA); }
void exception_B(void) { prg_abort(0xB); }
void exception_C(void) { prg_abort(0xC); }
void exception_D(void) { prg_abort(0xD); }
void exception_E(void) { prg_abort(0xE); }
void exception_F(void) { prg_abort(0xF); }
void exception_10(void) { prg_abort(0x10); }
void exception_11(void) { prg_abort(0x11); }
void exception_12(void) { prg_abort(0x12); }
void exception_13(void) { prg_abort(0x13); }
void exception_14(void) { prg_abort(0x14); }
void exception_15(void) { prg_abort(0x15); }
void exception_16(void) { prg_abort(0x16); }
void exception_17(void) { prg_abort(0x17); }
void exception_18(void) { prg_abort(0x18); }
void exception_19(void) { prg_abort(0x19); }
void exception_1A(void) { prg_abort(0x1A); }
void exception_1B(void) { prg_abort(0x1B); }
void exception_1C(void) { prg_abort(0x1C); }
void exception_1D(void) { prg_abort(0x1D); }
void exception_1E(void) { prg_abort(0x1E); }
void exception_1F(void) { prg_abort(0x1F); }
// ------------------------------
// Аварийный выход из программы
// ------------------------------
void prg_abort(int err)
{
vi_print(1, y++,"ERROR!!! ---> Произошло исключение", 0xc);
real_mode(); // Возвращаемся в реальный режим
// В реальном режиме выводим сообщение об исключении
gotoxy(1, ++y);
cprintf(" Исключение %X, нажмите любую клавишу", err);
getch();
textcolor(WHITE);
textbackground(BLACK);
clrscr();
exit(0);
}
4.8 Файл INTPROC.C. Заглушки для аппаратных прерываний.
#include
#include
#include
#include
#include "tos.h"
// Заглушки для необрабатываемых
// аппаратных прерываний.
void iret0(void)
{ // первый контроллер прерываний
asm {
push ax
mov al,EOI
out MASTER8259A,al
pop ax
pop bp
iret
}
}
// -----------------------------------------------------------
// второй контроллер прерываний
void iret1(void)
{
asm {
push ax
mov al,EOI
out MASTER8259A,al
out SLAVE8259A,al
pop ax
pop bp
iret
}
}
4.9 Файл KEYB.C. Ввод символа с клавиатуры.
#include
#include
#include
#include
#include "tos.h"
extern word key_code;
// Функция, ожидающая нажатия любой
// клавиши и возвращающая её скан-код
unsigned int kb_getch(void)
{
asm int 30h
return (key_code);
}
4.10 Файл KEYBOARD.ASM. Процедуры для работы с клавиатурой.
IDEAL
MODEL SMALL
RADIX 16
P286
include "tos.inc"
; ------------------------------------------
; Модуль обслуживания клавиатуры
; ------------------------------------------
PUBLIC _Keyb_int, _Int_30h_Entry, _key_code, _keyb_status
EXTRN _beep:PROC
DATASEG
_key_flag db 0
_key_code dw 0
ext_scan db 0
_keyb_status dw 0
CODESEG
PROC _Keyb_int NEAR
cli
call _beep
push ax
mov al, [ext_scan]
cmp al, 0
jz normal_scan1
cmp al, 0e1h
jz pause_key
in al, 60h
cmp al, 2ah
jz intkeyb_exit_1
cmp al, 0aah
jz intkeyb_exit_1
mov ah, [ext_scan]
call Keyb_PutQ
mov al, 0
mov [ext_scan], al
jmp intkeyb_exit
pause_key:
in al, 60h
cmp al, 0c5h
jz pause_key1
cmp al, 45h
jz pause_key1
jmp intkeyb_exit
pause_key1:
mov ah, [ext_scan]
call Keyb_PutQ
mov al, 0
mov [ext_scan], al
jmp intkeyb_exit
normal_scan1:
in al, 60h
cmp al, 0feh
jz intkeyb_exit
cmp al, 0e1h
jz ext_key
cmp al, 0e0h
jnz normal_scan
ext_key:
mov [ext_scan], al
jmp intkeyb_exit
intkeyb_exit_1:
mov al, 0
mov [ext_scan], al
jmp intkeyb_exit
normal_scan:
mov ah, 0
call Keyb_PutQ
intkeyb_exit:
in al, 61h
mov ah, al
or al, 80h
out 61h, al
xchg ah, al
out 61h, al
mov al,EOI
out MASTER8259A,al
pop ax
sti
iret
jmp _Keyb_int
ENDP _Keyb_int
PROC Keyb_PutQ NEAR
push ax
cmp ax, 002ah ; L_SHIFT down
jnz @@kb1
mov ax, [_keyb_status]
or ax, L_SHIFT
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb1:
cmp ax, 00aah ; L_SHIFT up
jnz @@kb2
mov ax, [_keyb_status]
and ax, NL_SHIFT
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb2:
cmp ax, 0036h ; R_SHIFT down
jnz @@kb3
mov ax, [_keyb_status]
or ax, R_SHIFT
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb3:
cmp ax, 00b6h ; R_SHIFT up
jnz @@kb4
mov ax, [_keyb_status]
and ax, NR_SHIFT
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb4:
cmp ax, 001dh ; L_CTRL down
jnz @@kb5
mov ax, [_keyb_status]
or ax, L_CTRL
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb5:
cmp ax, 009dh ; L_CTRL up
jnz @@kb6
mov ax, [_keyb_status]
and ax, NL_CTRL
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb6:
cmp ax, 0e01dh ; R_CTRL down
jnz @@kb7
mov ax, [_keyb_status]
or ax, R_CTRL
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb7:
cmp ax, 0e09dh ; R_CTRL up
jnz @@kb8
mov ax, [_keyb_status]
and ax, NR_CTRL
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb8:
cmp ax, 0038h ; L_ALT down
jnz @@kb9
mov ax, [_keyb_status]
or ax, L_ALT
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb9:
cmp ax, 00b8h ; L_ALT up
jnz @@kb10
mov ax, [_keyb_status]
and ax, NL_ALT
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb10:
cmp ax, 0e038h ; R_ALT down
jnz @@kb11
mov ax, [_keyb_status]
or ax, R_ALT
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb11:
cmp ax, 0e0b8h ; R_ALT up
jnz @@kb12
mov ax, [_keyb_status]
and ax, NR_ALT
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb12:
cmp ax, 003ah ; CAPS_LOCK up
jnz @@kb13
mov ax, [_keyb_status]
xor ax, CAPS_LOCK
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb13:
cmp ax, 00bah ; CAPS_LOCK down
jnz @@kb14
jmp keyb_putq_exit
@@kb14:
cmp ax, 0046h ; SCR_LOCK up
jnz @@kb15
mov ax, [_keyb_status]
xor ax, SCR_LOCK
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb15:
cmp ax, 00c6h ; SCR_LOCK down
jnz @@kb16
jmp keyb_putq_exit
@@kb16:
cmp ax, 0045h ; NUM_LOCK up
jnz @@kb17
mov ax, [_keyb_status]
xor ax, NUM_LOCK
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb17:
cmp ax, 00c5h ; NUM_LOCK down
jnz @@kb18
jmp keyb_putq_exit
@@kb18:
cmp ax, 0e052h ; INSERT up
jnz @@kb19
mov ax, [_keyb_status]
xor ax, INSERT
mov [_keyb_status], ax
jmp keyb_putq_exit
@@kb19:
cmp ax, 0e0d2h ; INSERT down
jnz @@kb20
jmp keyb_putq_exit
@@kb20:
test ax, 0080h
jnz keyb_putq_exit
mov [_key_code], ax
mov al, 0ffh
mov [_key_flag], al
keyb_putq_exit:
pop ax
ret
ENDP Keyb_PutQ
; Обработчик программного прерывания
; для ввода с клавиатуры. По своим функциям
; напоминает прерывание INT 16 реального
; режима.
PROC _Int_30h_Entry NEAR
push ax dx
; Ожидаем прерывание от клавиатуры
keyb_int_wait:
sti
nop
nop
cli
; Проверяем флаг, который устанавливается
; обработчиком аппаратного прерывания клавиатуры
mov al, [_key_flag]
cmp al, 0
jz keyb_int_wait
; Сбрасываем флаг после прихода прерывания
mov al, 0
mov [_key_flag], al
sti
pop dx ax
iret
ENDP _Int_30h_Entry
END
4.11 Файлы SCREEN.H и SCREEN.C – модуль для работы с видеоадаптером.
4.11.1 SCREEN.H
#ifndef SCREEN_H
#define SCREEN_H
// Границы перемещения бегунков
#define B_SIZE 70
// Структура, описывающая бегунок
typedef struct _TLabel
{
char Pos; // Позиция бегунка
char Dir; // Направление движения
} TLabel;
extern void StepLabel(TLabel* Label1, TLabel* Label2, char* Buf);
#endif
4.11.2 SCREEN.C
#include
#include
#include
#include
#include "tos.h"
#include "screen.h"
void vi_putch(unsigned int x, unsigned int y ,char c, char attr);
char hex_tabl[] = "0123456789ABCDEF";
// Вывод байта на экран, координаты (x,y),
// выводится шестнадцатеричное представление
// байта chr с экранными атрибутами attr.
void vi_put_byte(unsigned int x,
unsigned int y, unsigned char chr, char attr)
{
unsigned char temp;
temp = hex_tabl[(chr & 0xf0) >> 4];
vi_putch(x, y, temp, attr);
temp = hex_tabl[chr & 0xf];
vi_putch(x+1, y, temp, attr);
}
// Вывод слова на экран, координаты (x,y),
// выводится шестнадцатеричное представление
// слова chr с экранными атрибутами attr.
void vi_put_word(unsigned int x,
unsigned int y, word chr, char attr)
{
vi_put_byte(x, y, (chr & 0xff00) >> 8, attr);
vi_put_byte(x+2, y, chr & 0xff, attr);
}
// Вывод символа c на экран, координаты - (x,y),
// атрибут выводимого символа - attr
void vi_putch(unsigned int x,
unsigned int y ,char c, char attr)
{
register unsigned int offset;
char far *vid_ptr;















