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;
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
; Область памяти для инициализации 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 ; запоминаем для команды mov [protect_sel], dx ; перехода far jmp
; Подготовка к возврату в реальный режим
push ds ; готовим адрес возврата mov ax,40h ; из защищённого режима mov ds,ax mov [WORD 67h],OFFSET shutdown_return mov [WORD 69h],cs pop ds
; Запрещаем и маскируем все прерывания
cli in al, INT_MASK_PORT and al, 0ffh out INT_MASK_PORT, al
; Записываем код возврата в CMOS-память
mov al,8f out CMOS_PORT,al jmp delay1 delay1: mov al,5 out CMOS_PORT+1,al
call enable_a20 ; открываем линию A20
mov [real_ss],ss ; запоминаем регистры SS и ES mov [real_es],es
; Перепрограммируем контроллер прерываний ; для работы в защищённом режиме
mov dx,MASTER8259A mov ah,20 call set_int_ctrlr mov dx,SLAVE8259A mov ah,28 call set_int_ctrlr
; Загружаем регистры IDTR и GDTR
lidt [FWORD idtr] lgdt [QWORD gdt_ptr]
mov ax, 0001h ; переключаем процессор lmsw ax ; в защищённый режим
; jmp far flush db 0eah dw OFFSET flush p_mode_select dw ?
LABEL flush FAR
mov dx, [protect_sel] mov ss, dx mov ds, dx mov es, dx
; Обнуляем содержимое регистра LDTR
mov ax, 0 lldt ax
pop bp ret ENDP _protected_mode
; ---------------------------------------------------- ; Возврат в реальный режим. ; Прототип для вызова ; void real_mode(); ; ----------------------------------------------------
PROC _real_mode NEAR
; Сброс процессора
cli mov [real_sp], sp mov al, SHUT_DOWN out STATUS_PORT, al
rmode_wait: hlt jmp rmode_wait
LABEL shutdown_return FAR
; Вернулись в реальный режим
mov ax, DGROUP mov ds, ax
assume ds:DGROUP
mov ss,[real_ss] mov sp,[real_sp]
in al, INT_MASK_PORT and al, 0 out INT_MASK_PORT, al
call disable_a20
mov ax, DGROUP mov ds, ax mov ss, ax mov es, ax
mov ax,000dh out CMOS_PORT,al sti
ret ENDP _real_mode
; ------------------------------------------------------- ; Загрузка регистра TR. ; Прототип для вызова: ; void load_task_register(unsigned int tss_selector); ; -------------------------------------------------------
PROC _load_task_register NEAR push bp mov bp,sp ltr [bp+4] ; селектор для текущей задачи pop bp ret ENDP _load_task_register
; ------------------------------------------------------- ; Переключение на задачу. ; Прототип для вызова: ; void jump_to_task(unsigned int tss_selector); ; -------------------------------------------------------
PROC _jump_to_task NEAR push bp mov bp,sp mov ax,[bp+4] ; получаем селектор
; новой задачи mov [new_select],ax ; запоминаем его
jmp [DWORD new_task] ; переключаемся на
; новую задачу pop bp ret ENDP _jump_to_task
; ------------------------------ ; Открываем линию A20 ; ------------------------------
PROC enable_a20 NEAR push ax mov al, A20_PORT out STATUS_PORT, al mov al, A20_ON out KBD_PORT_A, al pop ax ret ENDP enable_a20
; ------------------------------ ; Закрываем линию A20 ; ------------------------------
PROC disable_a20 NEAR push ax mov al, A20_PORT out STATUS_PORT, al mov al ,A20_OFF out KBD_PORT_A, al pop ax ret ENDP disable_a20
; ----------------------------------------------------------- ; Готовим структуру для загрузки регистра IDTR ; Прототип для вызова функции: ; void load_idtr(unsigned long idt_ptr, word idt_size); ; -----------------------------------------------------------
PROC _load_idtr NEAR push bp
mov bp,sp mov ax,[bp+4] ; мл. слово адреса IDT mov dx,[bp+6] ; ст. слово адреса IDT mov bx, OFFSET idtr
; Запоминаем адрес IDTR в структуре
mov [(idtr_struc bx).idt_low], ax mov [(idtr_struc bx).idt_hi], dl
; Получаем предел IDT и запоминаем его в структуре
mov ax, [bp+8] mov [(idtr_struc bx).idt_len], ax
pop bp ret ENDP _load_idtr
; ---------------------------------- ; Установка контроллера прерываний ; ----------------------------------
PROC set_int_ctrlr NEAR
mov al, 11 out dx, al jmp SHORT $+2 mov al, ah inc dx out dx, al jmp SHORT $+2 mov al, 4 out dx, al jmp SHORT $+2 mov al, 1 out dx, al jmp SHORT $+2 mov al, 0ffh out dx, al dec dx ret ENDP set_int_ctrlr
; -------------------------- ; Выдача звукового сигнала ; --------------------------
PROC _beep NEAR
push ax bx cx
in al,KBD_PORT_B push ax mov cx,80
beep0:
push cx and al,11111100b out KBD_PORT_B,al mov cx,60
idle1:
loop idle1 or al,00000010b out KBD_PORT_B,al mov cx,60
idle2:
loop idle2 pop cx loop beep0
pop ax out KBD_PORT_B,al
pop cx bx ax ret
ENDP _beep
; ------------------------------- ; Задержка выполнения программы ; -------------------------------
PROC _pause NEAR
push cx mov cx,10
ploop0:
push cx xor cx,cx
ploop1:
loop ploop1 pop cx loop ploop0
pop cx ret
ENDP _pause
; ----------------------- ; Размаскирование прерываний ; -----------------------
PROC _enable_interrupt NEAR
in al, INT_MASK_PORT and al, 0fch out INT_MASK_PORT, al sti ret ENDP _enable_interrupt
end
5. Выводы.
Процессоры семейства Intel x86 реализуют необходимые средства для организации мультизадачных ОС с разделением адресного пространства и виртуальной памяти.
В процессе написания данного курсового проекта мной были изучена организация работы защищенного режима процессоров 80286, адресация ими свыше 1 Мб памяти, работа с прерываниями в защищенном режиме процессора, организация мультизадачных операционных систем.
6. Литература.
1. «Защищенный режим процессоров Intel 80286/80386/80486» © Александр
Фролов, Григорий Фролов Том 6, М.: Диалог-МИФИ, 1993, 234 стр.
2. «MS-DOS для программиста» © Александр Фролов, Григорий Фролов
Том 18, часть 1, М.: Диалог-МИФИ, 1995, 254 стр.
3. «MS-DOS для программиста» © Александр Фролов, Григорий Фролов
Том 19, часть 2, М.: Диалог-МИФИ, 1995, 253 стр.
4. «Язык Ассемблера для IBM PC и программирования» © Питер Абель, М.:
«Высшая школа», Москва, 1992, 444 стр.
5. «Язык программирования для персонального компьютера Си», © С.О.
Бочков, Д.М. Субботин, М.: Диалог-МИФИ, 1990, 383 стр.
6. Материалы WEB-сервера для разработчиков фирмы Intel http://developer.intel.com
Страницы: 1, 2, 3, 4