DOS-extender для компилятора Borland C++ 3.1, защищенный режим процессора 80286, организация многозадачной работы процессора

Страница 9

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 <stdio.h>

#include <dos.h>

#include <conio.h>

#include <stdlib.h>

#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;

offset = (y*160) + (x*2);

vid_ptr = MK_FP(VID_MEM_SELECTOR, offset);

*vid_ptr++=c; *vid_ptr=attr;

}

// Вывод строки s на экран, координаты - (x,y),

// атрибут выводимой строки - attr

void vi_print(unsigned int x,

unsigned int y, char *s, char attr)

{

while (*s)

vi_putch(x++, y, *s++, attr);

}

// Вывод стоки сообщения о запуске программы

void vi_hello_msg(void)

{

vi_print(0, 0,

" Threads for DOS, "

" Version 0.1/i286, Copyright (c) 2000 Eugeny Balahonov ", 0x30);

}

// Вывод бегущей строки

void StepLabel(TLabel* Label1, TLabel* Label2, char* Buf)

{

// Стираем символы меток

Buf[Label1->Pos] = ' ';

Buf[Label2->Pos] = ' ';

// Если двигаемся налево

if (Label1->Dir == 0)

{

// Если не дошли до крайней левой позиции

if (Label1->Pos > 0)

{

Label1->Pos--;

Buf[Label1->Pos] = '\\';

}

else

{

Label1->Dir = 1;

Buf[Label1->Pos] = '/';

}

}

// Если двигаемся направо

else

{

// Если не дошли до крайней правой позиции

if (Label1->Pos < B_SIZE)

{

Label1->Pos++;

Buf[Label1->Pos] = '/';

}

else

{

Label1->Dir = 0;

Buf[Label1->Pos] = '\\';

}

}

// Если двигаемся налево

if (Label2->Dir == 0)

{

// Если не дошли до крайней левой позиции

if (Label2->Pos > 0)

{

Label2->Pos--;

Buf[Label2->Pos] = '\\';

}

else

{

Label2->Dir = 1;

Buf[Label2->Pos] = '/';

}

}

// Если двигаемся направо

else

{

// Если не дошли до крайней правой позиции

if (Label2->Pos < B_SIZE)

{

Label2->Pos++;

Buf[Label2->Pos] = '/';

}

else

{

Label2->Dir = 0;

Buf[Label2->Pos] = '\\';

}

}

}

4.12 Файл TOSSYST.ASM. Процедуры для инициализации, перехода в защищённый режим и возврата в реальный режим, для загрузки регистра TR и переключения задач.

IDEAL

MODEL SMALL

RADIX 16

P286

DATASEG

include "tos.inc"

PUBLIC _beep

; Область памяти для инициализации IDTR

idtr idtr_struc <,,,0>

; Область памяти для инициализации GDTR

gdt_ptr dw (8*15)-1 ; размер GDT, 15 элементов

gdt_ptr2 dw ?

gdt_ptr4 dw ?

; Область памяти для записи селектора задачи,

; на которую будет происходить переключение

new_task dw 00h

new_select dw 00h

; Область памяти для хранения регистров,

; используется для возврата в реальный режим

real_ss dw ?

real_sp dw ?

real_es dw ?

protect_sel dw ?

init_tss dw ?

CODESEG

PUBLIC _real_mode,_protected_mode,_jump_to_task

PUBLIC _load_task_register, _load_idtr, _enable_interrupt

; -------------------------------------------------------------------

; Процедура для переключения в защищённый режим.

; Прототип для вызова:

; void protected_mode(unsigned long gdt_ptr, unsigned int gdt_size,

; unsigned int cseg, unsigned int dseg)

; -------------------------------------------------------------------

PROC _protected_mode NEAR

push bp

mov bp,sp

; Параметр gdt_ptr

mov ax,[bp+4] ; мл. слово адреса GDT

mov dx,[bp+6] ; ст. слово адреса GDT

mov [gdt_ptr4], dx ; запоминаем адрес GDT

mov [gdt_ptr2], ax

; Параметр gdt_size

mov ax,[bp+8] ; получаем размер GDT

mov [gdt_ptr], ax ; и запоминаем его

; Параметры cseg и dseg

mov ax,[bp+10d] ; получаем селектор сегмента кода

mov dx,[bp+12d] ; получаем селектор сегмента данных

mov [cs:p_mode_select], ax ; запоминаем для команды