{ (word)&exception_4, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 4
{ (word)&exception_5, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 5
{ (word)&exception_6, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 6
{ (word)&exception_7, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 7
{ (word)&exception_8, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 8
{ (word)&exception_9, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 9
{ (word)&exception_A, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // A
{ (word)&exception_B, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // B
{ (word)&exception_C, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // C
{ (word)&exception_D, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // D
{ (word)&exception_E, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // E
{ (word)&exception_F, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // F
{ (word)&exception_10, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 10
{ (word)&exception_11, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 11
{ (word)&exception_12, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 12
{ (word)&exception_13, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 13
{ (word)&exception_14, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 14
{ (word)&exception_15, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 15
{ (word)&exception_16, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 16
{ (word)&exception_17, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 17
{ (word)&exception_18, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 18
{ (word)&exception_19, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 19
{ (word)&exception_1A, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 1A
{ (word)&exception_1B, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 1B
{ (word)&exception_1C, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 1C
{ (word)&exception_1D, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 1D
{ (word)&exception_1E, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 1E
{ (word)&exception_1F, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 }, // 1F
// Обработчик прерываний таймера
{ (word)&Timer_int, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 20
// { (word)&Keyb_int, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 21
// Вентиль задачи, запускающейся по прерыванию от клавиатуры
{ 0, KEYB_TASK_SELECTOR, 0, TYPE_TASK_GATE, 0 }, // 21
// Заглушки для остальных аппаратных прерываний
{ (word)&iret0, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 22
{ (word)&iret0, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 23
{ (word)&iret0, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 24
{ (word)&iret0, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 25
{ (word)&iret0, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 26
{ (word)&iret0, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 27
{ (word)&iret1, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 28
{ (word)&iret1, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 29
{ (word)&iret1, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 2A
{ (word)&iret1, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 2B
{ (word)&iret1, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 2C
{ (word)&iret1, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 2D
{ (word)&iret1, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 2E
{ (word)&iret1, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 2F
// Обработчик для программного прерывания, которое
// используется для ввода с клавиатуры
{ (word)&Int_30h_Entry, CODE_SELECTOR, 0, TYPE_INTERRUPT_GATE, 0 }, // 30
// Вентиль задачи FLIP_TASK
{ 0, FLIP_TASK_SELECTOR, 0, TYPE_TASK_GATE, 0 } // 31
};
// -------------------------------------------
// Сегменты TSS для различных задач
// -------------------------------------------
tss main_tss; // TSS главной задачи
tss task_1_tss; // TSS задачи TASK_1
tss task_2_tss; // TSS задачи TASK_2
tss keyb_task_tss; // TSS задач обслуживания
tss keyb_tss; // клавиатуры
tss flipflop_tss; // TSS задачи FLIP_TASK
// -------------------------------------------
// Стеки для задач
// -------------------------------------------
unsigned char task_1_stack[1024];
unsigned char task_2_stack[1024];
unsigned char keyb_task_stack[1024];
unsigned char keyb_stack[1024];
unsigned char flipflop_stack[1024];
word y=0; // номер текущей строки для вывода на экран
// -------------------------------------------
// Начало программы
// -------------------------------------------
extern int getcpu(void);
void main(void)
{
// Очищаем экран
textcolor(BLACK);
textbackground(LIGHTGRAY);
clrscr();
// Входим в защищённый режим процессора
Init_And_Protected_Mode_Entry();
// Выводим сообщение
vi_hello_msg();
y=3;
vi_print(0, y++, " Установлен защищённый режим в главной задаче", 0x7f);
// Загружаем регистр TR селектором главной задачи
// т.е. задачи main()
load_task_register(MAIN_TASK_SELECTOR);
// Переключаемся на задачу TASK_1
jump_to_task(TASK_1_SELECTOR);
// После возврата в главную задачу выдаём сообщение
vi_print(0, y++ ," Вернулись в главную задачу", 0x7f);
// Запускаем планировщик задач
vi_print(0, y++ ," Запущен планировщик задач", 0x70);
enable_interrupt(); // разрешаем прерывание таймера
// Ожидаем установки семафора с номером 0. После того,
// как этот семафор окажется установлен, возвращаемся
// в реальный режим.
// Семафор 0 устанавливается задачей, обрабатывающей ввод с
// клавиатуры, которая работает независимо от
// главной задаче.
vi_print(18, 24," Для возврата в реальный режим нажмите ESC", 0x70);
sem_clear(0); // сброс семафора 0
sem_wait(0); // ожидание установки семафора 0
// Возврат в реальный режим, стирание экрана и
// передача управления MS-DOS
real_mode();
textcolor(WHITE);
textbackground(BLACK);
clrscr();
}
// -----------------------------------
// Функция инициализации сегмента TSS
// -----------------------------------
void init_tss(tss *t, word cs, word ds,
unsigned char *sp, func_ptr ip)
{
t->cs = cs; // селектор сегмента кода
t->ds = ds; // поля ds, es, ss устанавливаем
t->es = ds; // на сегмент данных
t->ss = ds;
t->ip = (word)ip; // указатель команд
t->sp = (word)sp; // смещение стека
t->bp = (word)sp;
}
// -------------------------------------------------
// Функция инициализации дескриптора в таблице GDT
// -------------------------------------------------
void init_gdt_descriptor(descriptor *descr,
unsigned long base,
word limit,
unsigned char type)
{
// Младшее слово базового адреса
descr->base_lo = (word)base;
// Старший байт базового адреса
descr->base_hi = (unsigned char)(base >> 16);
// Поле доступа дескриптора
descr->type_dpl = type;
// Предел
descr->limit = limit;
// Зарезервированное поле, должно быть
// сброшено в 0 всегда (для процессоров 286)
descr->reserved = 0;
}
// -----------------------------------------------
// Инициализация всех таблиц и вход
// в защищённый режим
// -----------------------------------------------
void Init_And_Protected_Mode_Entry(void)
{
union REGS r;
// Инициализируем таблицу GDT, элементы с 1 по 5
init_gdt_descriptor(&gdt[1], MK_LIN_ADDR(_CS, 0),
0xffffL, TYPE_CODE_DESCR | SEG_PRESENT_BIT | SEG_READABLE);
init_gdt_descriptor(&gdt[2], MK_LIN_ADDR(_DS, 0),
0xffffL, TYPE_DATA_DESCR | SEG_PRESENT_BIT | SEG_WRITABLE);
init_gdt_descriptor(&gdt[3],
MK_LIN_ADDR(_DS, &task_1_tss),
(unsigned long)TSS_SIZE-1, TYPE_TSS_DESCR | SEG_PRESENT_BIT); )