Реферат: DOS-extender для компилятора Borland C++ - текст реферата. Скачать бесплатно.
Банк рефератов, курсовых и дипломных работ. Много и бесплатно. # | Правила оформления работ | Добавить в избранное
 
 
   
Меню Меню Меню Меню Меню
   
Napishem.com Napishem.com Napishem.com

Реферат

DOS-extender для компилятора Borland C++

Банк рефератов / Программирование

Рубрики  Рубрики реферат банка

закрыть
Категория: Реферат
Язык реферата: Русский
Дата добавления:   
 
Скачать
Архив Zip, 63 kb, скачать бесплатно
Заказать
Узнать стоимость написания уникального реферата

Узнайте стоимость написания уникальной работы

DOS - extender для компилятора Borland C ++ 3.1, защищенный режим проц ессора 80286, организация многозадачн ой работы процессора 1. Введение. Операционная система MS DOS , не смотря на свое мораль ное устаревание , все еще довольно часто на ходит применение на парке старых ПК , а значит , все еще существ ует необходимост ь создания программ для нее. К сожалению , написание программ в реал ьном режиме процессоров архитектуры Intel x 86 осложнено отс утствием возможности использовать в программе оперативную память объемом свыше пресловутых 640 килобайт , а реально свыше 500-620 килобайт . Это ограничение к сожалению преследует MS DOS и аналогичные ей ОС других производителей , начиная с того момента , как горячо любимый в окол окомпьютерных кругах Билл Гейтс заявил , что 640 килобайт достаточно для всех возможных за дач ПК . Преодоление барьера 640 килобайт в новых версиях MS DOS усложнялось необходимостью совместимости с старыми программами , которые жизненно необхо димо было поддерживать . Программирование защищенн ого режима процессора и расширенной памяти требовало от прог раммистов недюжинных знаний архитектуры процессоров Intel и достаточно трудоемко го программирования. 1.1 Уровни программной поддержки защищ енного режима. Инженерная мысль не стоит на месте , особенно в такой области , как программ ирование . Задача программной поддержки за щищённого режима и поддержки работы с рас ширенной памятью получила не одно , а сразу несколько решений . Этими решениями стали так называемые уровни программной поддержки з ащищённого режима и поддержки работы с ра сши р енной памятью : · интерфейс BIOS; · интерфейс дра йвера HIMEM.SYS; · интерфейс EMS/VCPI; · интерфейс DPMI; · расширители DOS (DOS-экстендеры ). 1.1.1 Интерфей с BIOS. Интерфейсом самого низкого уро вня является интерфейс BIOS, предоставляемый пр ограммам в виде нескольких функций прерывания BIOS INT 15h. Интерфейс BIOS позволяет программе перевести процессор из реального режима в защищённый , переслать блок памяти из стандартной пам яти в расширенную или из расширенной в ст а ндартную . Этим все его возмо жности и ограничиваются . Интерфейс BIOS используется для старта мультизадачных операционных систе м защищённого режима (таких , как OS/2) или в старых программах , работающих с расширенной памятью в защищённом режиме (например , СУ Б Д ORACLE версии 5.1). 1.1.2 интерфейс драйвера HIMEM . SYS . С помощью функций , предоставля емых этим драйвером , программа может выполнят ь различные действия с блоками расширенной памяти , а также управлять адресной линией A20. Основ ное различие между способом рабо ты с расширенной памятью драйвера HIMEM.SYS и ин терфейсом прерывания BIOS INT 15h заключается в том , чт о первый выполняет выделение программе и внутренний учёт блоков расширенной памяти , а второй рассматривает всю расширенн у ю память как один непрерывный участок . Однако драйвер HIMEM.SYS не открывает для прогр амм доступ к защищённому режиму . Он полнос тью работает в реальном режиме , а для обращения к расширенной памяти использует либ о недокументированную машинную команду LOADA L L (если используется процессор 80286), либо воз можности процессора 80386, который позволяет адресоват ь расширенную память в реальном режиме (пр и соответствующей инициализации системных регист ров и таблиц ). 1.1.3 интерфейс EMS / VCPI . Используя трансляцию страниц , некоторые д райверы памяти (например , EMM386 или QEMM) могут эмулиро вать присутствие дополнительной памяти , используя расширенную память . При этом стандартный набор функций управления дополнительной памятью , реализованный в р амках прерывания INT 67h, дополнен еще несколькими функциями для рабо ты в защищённом режиме процессора . Эти нов ые функции реализуют интерфейс виртуальной уп равляющей программы VCPI (Virtual Control Programm Interface). Они позволяют уста навливать защищённ ы й и виртуальный режимы работы процессора , работать с расшир енной памятью на уровне страниц и устанав ливать специальные отладочные регистры процессор а i80386. Интерфейс VCPI облегчает использование механизма трансляции страниц , освобождая программиста от н е обходимости работать с систе мными регистрами процессора . 1.1.4 интерфейс DPMI. Интерфейс DPMI ( DOS Protected Mode Interface - интерфейс з ащищённого режима для DOS ) реализуется модулем , называющимс я сервером DPMI . Этот интерфейс д оступен для те х программ , которые работают на виртуальной машине WINDOWS или OS/2 версии 2.0 (позже мы обсудим некоторые детали , связанные с использованием интерфейса DPMI в WINDOWS). Интерфейс DPMI предоставляет полн ый набор функций для создания однозада ч ных программ , работающих в защищё нном режиме . В этом интерфейсе имеются фун кции для переключения из реального режима в защищённый и обратно , для работы с локальной таблицей дескрипторов LDT, для работы с расширенной и стандартной памятью на уровне страниц, для работы с прерываниям и (в том числе для вызова прерываний р еального режима из защищённого режима ), для работы с отладочными регистрами процессора i80386. Это наиболее развитый интерфейс из всех рассмотренных ранее . 1.1.5 расширители DOS ( DOS-экстендеры ). Последний , самый высокий урове нь программной поддержки защищённого режима - расширители DOS или DOS-экстендеры (DOS-extender). Они поставляютс я , как правило , вместе со средствами разра ботки программ (трансляторами ) в виде биб лиотек и компонуются вместе с создава емой программой в единый загрузочный модуль . DOS-экстендеры значительно облегчают использование защищённого режима и расширенной памяти в программах , предназначенных для запуска из среды MS-DOS. Программы , составленные с использованием DOS-экстендеров , внешне очень похожи на обычные программы MS-DOS, однако они получа ют управление , когда процессор уже находится в защищённом режиме . К формируемому с помощью DOS-экстендера загрузочному модулю добавл яются процедуры , необхо д имые для и нициализации защищённого режима . Эти процедуры первыми получают управление и выполняют на чальную инициализацию таблиц GDT, LDT, IDT, содержат обработ чики прерываний и исключений , систему управле ния виртуальной памятью и т.д . 1.2 Тек ущее положение дел в мире DOS - extender -ов. Еще несколько лет назад целые фирмы зарабатывали себе на существование созданием различных модификаций DOS extender -ов . Например довольно известный externder фирмы Phar Lap . После переход а большинства пользователей в среду Win 32 необходимо сть в DOS extender - ах резко сократилась и большинство таких фирм , не сумев сориентироваться в изменившихс я условиях , прекратили свое существование . Многие фирмы , разрабатывавшие компиляторы для DOS , в ключали в постав ку своих сред програм мирования DOS - extender -ы собственн ой разработки . Таким примером может служить фирма Borland (ныне подразделение фирмы Corel ) с ее Borland Pascal , Borland C ++ и расширителе м DOS RTM . В данный момент доступно несколько DOS - extender -ов по свободной лицензии , которые могут использоватьс я кем угодно для любых целей . И это понятно , денег на них сейчас не заработ аешь . Примеры таких программ : ZRDX by Sergey Belyakov Маленький и функциональный DOS - extender для Watcom C ++ и 32-х битн ых исполняе мых файлов формата OS /2 LE . Используется в коммерческих программах , таких как антивиру с AVP для DOS 32. WDOSX by Michael Tippach Самый впечатливший меня DOS - extender . Список подде рживаемых функций просто поражает . Поддерживает все распространенные среды про граммировани я : Visual C ++ 4 и позже , Borland C ++ 4 и позже , Delphi 2 и позже . При желании никто не запрещает испо льзовать Assembler . 2. Обоснование выбора сред ств. DOS-экстендеры обычно поставляются в комп лекте с трансляторами, редакторами связей , отладчиками и библиотеками стандартных функций (например , библиотеками для транслятора языка Си ). Код DOS - extender линкуе тся либо уже к готовому исполняемому файл у специальной программой (чаще ), либо линковка полностью проходит при пом ощи програ ммы-линкера , специально разработанного для данного компилятора. В настоящий момент науке известны всего один DOS - extender для Borland C ++ 3.1. Это программ а фирмы Phar Lap , не имеющая собственного названия . Фирмы , к сожалению , давно уже нет , как и ис ходных текстов этого DOS - extender -а . В него входил собственная программ а – линкер и набор специальных библиотек функций специально для Borland C ++ 3.1, которой и проводилась окон чательная сборка EXE -файла. Написание собственной среды разработки , вро де программ-линкеров и собственных т рансляторов языка Ассемблера явно выходит за переделы данного курсового проекта . Поэтому остановимся на разработке набора функций , позволяющих : реализовать защищенный режим процессора 80286, адресовать до 16 Мб памяти, обрабатывать прерывания реального режима DOS реализуем набор средств для создания параллельно выполняющихся потоков в среде DOS . После разработки необходимых средств , нап ишем программу– пример с их использованием . С обственно это получится не просто прог рамма , а некий прототип многозадачной операционной системы . Итак , согласно заданию буду пользоваться следующими средствами разработки : Borland C++ 3.1 Borland Turbo Assembler из поставки Borland C++ 3.1 3. Реализация работы прогр аммы в защи щенном режиме процессора 80286. 3.1 Адресация защищенного режима проце ссора 80286. Логический адрес в защищённом режиме ( иногда используется термин "виртуальный адрес ") состоит из двух 16-разрядных компонент - селект ора и смещения . Селектор записывается в те же сегментные регистры , что и сег ментный адрес в реальном режиме . Однако пр еобразование логического адреса в физический выполняется не простым сложением со сдвигом , а при помощи специальных таблиц преобраз ования а дресов . В первом приближении можно считать , чт о для процессора i80286 селектор является индексом в таблице , содержащей базовые 24-разрядные физические адреса сегментов . В процессе преоб разования логического адреса в физический про цессор прибавляет к базов ому 24-разрядному адресу 16-разрядное смещение , т.е . вторую ко мпоненту логического адреса (Рис . 1). Такая схема формирования физического адре са позволяет непосредственно адресовать 16 мегабайт памяти с помощью 16-разрядных компонент ло гического адреса. Т аблиц дескрипторов в системе обы чно присутствует от одной до нескольких д есятков . Но всегда существует так называемая таблица GDT (Global Descriptor Table), в которой обычно хранится описа ние сегментов самой операционной системы защи щенного режима 80286. Т аблицы LDT ( Local Descriptor Table ) создаются на каждый новый запускаемый процесс в опера ционной системе , и в них хранится описание сегментов только одной отдельной задачи. Таблица дескрипторов - это просто таблица преобразования адресов , содержащая базовы е 24-разрядные физические адреса сегментов и некоторую другую информацию . То есть каждый элемент таблицы дескрипторов (дескриптор ) содержит 24-разрядный базовый адрес сегмента и другую информацию , описывающую сегмент . Процессор 80286 имеет специальный 5-б айтный регистр защищенного режима GDTR , в котором старшие 3 байта содержат 24-разрядный физический адрес та блицы GDT, младшие два байта - длину таблицы GDT, уменьшенную на 1. Рис . 1. Схема преобразования логического адр еса в физический в защищенном режиме проц ессора 80286. Перед переходом в защищённый режим пр ограмма должна создать в оперативной памяти таблицу GDT и загрузить регистр GDTR при помощи специальной коман ды LGDT. Каждый элемент таблицы дескрипторов имеет следующий формат : Общая его длина составляет 8 байт , в которых расположены следующие поля : поле базового адреса д линой 24 бита содержит физический адрес сегмента , описывае мого данным дескриптором ; поле предела содержит размер сегмента в байтах , уменьшенный на единицу ; поле доступа описывает тип сегмента (с егмент кода , сегмент данных и др .); зарезервированное поле длиной 16 бит для процессора i80286 должно содержать нули , это поле используется процессорами i80386 и i80486 (там , в частности , хранится старший байт 32-разрядного базового адреса сегмента ). Поле доступа , занимающее в дескрипторе один байт (байт доступа ) служит для классификации дескрипторов . На рис. 2 приведены форматы поля доступа для трёх типов дескрипторов - дескрипторов сегментов кода , сегмент ов данных и системных . Рис . 2. Форматы п оля дос тупа дескриптора. Поле доступа дескриптора сегме нтов кода содержит битовое поле R, называемое битом разрешения чтения сегмента . Если этот бит установлен в 1, программа может считыв ать содержимое сегмента кода . В противном случае процессор может толь ко выполнять этот код . Биты P и A предназначены для организации виртуальной памяти . Их назначение будет опи сано в разделе , посвящённом виртуальной памят и . Сейчас отметим , что бит P называется бито м присутствия сегмента в памяти . Для тех сегментов , которые находятся в физическ ой памяти (мы будем иметь дело в основ ном с такими сегментами ) этот бит должен быть установлен в 1. Любая попытка программы обратиться к сегменту памяти , в дескрипторе которого бит P установлен в 0, приведёт к прерыванию . Бит A назыв ается битом обращения к сегменту и для всех наших программ д олжен быть установлен в 0. Поле доступа дескриптора сегмента данных имеет битовые поля W и D. Поле W называется битом разрешения записи в сегмент . Если этот бит установлен в 1, наряду с чтением в озможна и запись в данный сегме нт . В противном случае при попытке чтения выполнение программы будет прервано . Поле D задаёт направление расширения сегме нта . Обычный сегмент данных расширяется в область старших адресов (расширение вверх ). Есл и же в сегмент е расположен стек , р асширение происходит в обратном направлении - в область младших адресов (расширение вниз ). Для сегментов , в которых организуются стек и , необходимо устанавливать поле D равным 1. Рассмотрим , как таблица дескрипторов буде т выглядеть на я зыке программирования C . (В да льнейшем где это только возможно будем пр именять язык С , а Ассемблер – только там , где это необходимо .): typedef struct descriptor word limit ; // Предел (размер сегмента в байтах ) word base _ lo ; // Базовый адре с сегмента (младшее слово ) unsigned char base _ hi ; // Базовый адре с сегмента (старший байт ) unsigned char type_dpl; // Поле доступа дескриптора unsigned reserved ; // Зарезервиров анные 16 б ит descriptor; Данная структура описана в файле tos . h . Инициализацию экземпляра такой струк туры можно произвести при помощи функции , подобной функции init _ gdt _ descriptor , описанной в файле tos . c : 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; Например , запись в третий по счёту элемент GDT информации о сегменте данных с сегментным адресом _DS и пределом 0xffff будет выглядеть так : init_gdt_descriptor(&gdt[2], MK_LIN_ADDR(_DS, 0) , 0xffffL, TYPE_DATA_DESCR | SEG_PRESENT_BIT | SEG_WRITABLE); Макрос MK _ LIN _ ADDR определен в файле tos . h и служит для преобразования адрес а реального режима формата сегмент :смещение в физический адрес : #define MK_LIN_ADDR(seg,off) (((unsigned long)(seg ))<<4)+(word)(off) Специальный регистр проце ссора 286 LDTR имеет длину 16 разрядов и содержит селектор дескриптора , описывающего текущую таблицу LDT . В данном курсовом проекте я не использую регистр LDTR и не создаю таблицы LDT , в моем ва рианте достаточ но обойтись только одним кольцом защиты (0) процессора и только табл ицей GDT . 3.2 Переход в защищенный режим про цессора 80286 При переходе в защищенный режим пр ограмма совершает следующие операции : Подготовка в оперативной памя ти г лобальной таблицы дескрипторов GDT. В этой табли це создаются дескрипторы для всех сегментов , которые будут нужны программе сразу посл е того , как она переключится в защищённый режим . Для обеспечения возможности возврата из защищённого режима в реальный записыва ет адрес возврата в реальный режим в область данных BIOS по адресу 0040h:0067h, а также пиш ет в CMOS-память в ячейку 0Fh код 5. Этот код обеспечит после выполнения сброса процессора передачу управления по адресу , подготовленно му нами в области да н ных BIOS по адресу 0040h:0067h. Запрещает все маскируемые и немаскируемые прерывания . Открывает адресную линию A20 (попробуем опер ировать блоками памяти выше 1 Мб ). Запоминает в оперативной памяти содержимо е сегментных регистров , которые необходимо со хр анить для возврата в реальный режим , в частности , указатель стека реального р ежима . Программирует контроллер прерываний для р аботы в защищенном режиме. Загружает регистры IDTR и GDTR. Необходимые функции для этого реализованы в файлах tos . c и TOSSYST.ASM: Подготовка GDT осуществляется при помощи описанных выше функции init _ gdt _ descriptor () и макроса MK _ LIN _ ADDR (). Остальные действия , необходимые для перех ода в защищенный режим , описаны в функции protected _ mode () модуля TOSSYST.ASM: Обеспечение возможности возврата в реальный режим : push ds ; готовим адрес возврата mov ax,40h ; из защищённого режима mov ds,ax mov [WORD 67h],OFFSET shutdown_return mov [WORD 69h],cs pop ds Запрет прерываний : с li in al, INT_MASK_PORT and al, 0ffh out INT_MASK_PORT, al mov al,8f out CMOS_PORT,al Открытие линии A 20 производится вызовом функции enable _ a 20(), описанной в файле TOSSYST.ASM: PROC enable_a20 NEAR mov al,A20_PORT out STATUS_PORT,al mov al,A20_ON out KBD_PORT_A,al ret ENDP enable _ a 20 Запоминаем содерж имое с егментных регистров SS и ES : mov [real_ss],ss mov [real_es],es Програ ммируем при помощи функции set _ int _ ctrlr (), описанной в файле TOSSYST.ASM каскад конт роллеров прерываний ( Master и Slave ) для работы в защищенном режиме (описание работы прерыва ний в защищенно м режиме приведено ниже ): 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 3.3 Возврат в реальный режим проце ссора. Для того , чтобы вернуть процессор 80286 из защищённого режима в реальный , необходимо выполнить аппаратный сброс (отключение ) процесс ора . Это реализуется в функции real _ mode (), описанной в файле TOSSYST.ASM: 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 Функция disable _ a 20(), описанная в файле TOSSYST.ASM закрывает адресную линию 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 3.4 Обработка прерываний в защищенном режиме. Обработка прерываний и исключений в защищённом режиме по аналогии с реальным режимом базируется на таблице прерываний . Н о таблица прерываний защищённог о режима является таблицей дескрипторов , которая соде ржит так называемые вентили прерываний , венти ли исключений и вентили задач . Таблица прерываний защищённого режима наз ывается дескрипторной таблицей прерываний IDT (Interrupt Descriptor Table). Также как и таблицы GDT и LDT, таблиц а IDT содержит 8-байтовые дескрипторы . Причём это системные дескрипторы - вентили прерываний , ис ключений и задач . Поле TYPE вентиля прерывания содержит значение 6, а вентиля исключения - зн ачение 7. Формат элементов дескрипторно й таблиц ы прерываний IDT показан на рис . 3. Рис . 3. Формат элементов дескри пторной таблицы прерываний IDT. Расположение определяется содержи мым 5-байтового внутреннего регистра процессора IDTR. Формат регистра IDTR полностью аналогичен формату регистра GDTR, для его загрузки использ уется команда LIDT. Так же , как регистр GDTR содер жит 24-битовый физический адрес таблицы GDT и её предел , так и регистр IDTR содержит 24-битовы й физический ад р ес дескрипторной таблицы прерываний IDT и её предел. Регистр IDTR программа загружает перед перех одом в защищённый режим , в функции protected _ mode () модуля TOSSYST.ASM пр и помощи вызова функции set _ int _ ctrlr (), описанной в файле TOSSYST.ASM. Для обработк и особых ситуаций - ис ключений - разработчики процессора i80286 зарезервировали 31 номер прерывания . Каждому исключению соответст вует одна из функций exception _ XX () из модуля EXCEPT.C. Собственно , опи сав реакцию программы на каждое исключение можно обрабат ывать любые ошибки защище нного режима . В моем случае достаточно зав ершать программу при возникновении любого иск лючения с выдачей на экран номера возникш его исключения . Поэтому функции exception _ XX () просто вызыва ют prg_abort(), описанной там же , и передаю т ей номер возникшего исключения . Функция prg_abort() переключает процессор в реальный режим , вывод ит сообщение с данными возникшего исключения и завершает работу программы. Теперь разберемся с аппаратными прерывани ями , которые нас не интересуют в данной программе , однако это не мешает им происходить . Для этого в модуле INTPROC.C описаны две функции заглушки iret0() и iret 1(), которые собс твенно ничего не делают кроме того , что выдают на контроллеры команды конца прерыв ания . Функция iret 0() относится к пер вому контролл еру ( Master ), а вторая – ко второму ( Slave ). Неплохо было бы включить в программу поддержку программного прерывания 30 h , чтобы можно было получать данные с клавиатуры . Это реализовано в модуле KEYBOARD.ASM, в функции Int_30h_Entry(). В IDT п омещается вентиль программного прерывания , который вызывает данную функцию в момент прерывания 30 h . После запуска программа перехо дит в защищённый режим и размаскирует пре рывания от таймера и клавиатуры . Далее она вызывает в цикле прерывание int 30h (ввод символа с клавиатуры ), и выводит на экра н скан-код нажатой клавиши и состояние пер еключающих клавиш (таких , как CapsLock, Ins, и т.д .). Есл и окажется нажатой клавиша ESC, программа выходи т из цикла. Обработчик аппаратного прерывания клавиату ры - процедур а с именем Keyb_int из модуля KEYBOARD.ASM. После прихода прерывания она выдаёт кор откий звуковой сигнал (функция beep () из модуля TOSSYST.ASM), считывает и анализирует скан-код клавиши , вызвавшей прерывание . Скан-коды классифицируются на обычные и расшире нные (для 101-клав ишной клавиатуры ). В отличие от прерывания BIOS INT 16h, мы для простоты не стали реализовывать очередь , а ограничились записью полученного скан-кода в глобальную ячейку памяти key_code. При чём прерывания , возникающие при отпускании кл ав и ш , игнорируются . Запись скан-кода в ячейку key_code выполняет процедура Keyb_PutQ() из модуля KEYBOARD.ASM. После записи эта процедура устанавливает признак того , что б ыла нажата клавиша - записывает значение 0FFh в глобальную переменную key_flag. Програ ммное прерывание int 30h опрашивает состояние key_flag. Если этот флаг оказывается устан овленным , он сбрасывается , вслед за чем об работчик int 30h записывает в регистр AX скан-код наж атой клавиши , в регистр BX - состояние переключаю щих клавиш на момент на ж атия клавиши , код которой передан в регистре AX. Ну и последнее , требующееся прерывание – это аппаратное прерывание таймера . Обр аботка этого прерывания реализована в функции Timer_int() модуля TIMER.C. Эта функция служит для перек лючения процессора между задачами . Более подробно я рассмотрю ее работу в следу ющей главе курсового проекта. Структура элемента дескрипторной таблицы прерываний IDT описана в файле tos . inc : STRUC idtr_struc idt_len dw 0 idt_low dw 0 idt_hi db 0 rsrv db 0 ENDS idtr_struc 3.5 Реализация мультизада чности. Я пошел в данном курсовом проекте самым простым способом – реализации мул ьтизадачности через аппаратный таймер компьютера . Реализация более сложных алгоритмов явно тянет на дипломный проект. Как известно , таймер вырабатывает прерывание IRQ0 примерно 18,2 раза в секунду . Можно использовать данный факт для переключения между задачами , выделяя каждой квант времен и . Я не буду здесь реализовывать механизм приоритетов задач . Все выполняемые задачи име ю т равный приоритет. Для реализации разделения ресурсов ком пьютера между задачами и их взаимодействию друг с другом и средой исполнения (можн о даже ее назвать операционной системой ), я реализовал механизм семафоров . В моем случае семафор представляет соб ой ячейку памяти , отражающая текущее состояние ресурса - свободен или занят. Я иду еще на одно упрощение - не создаю здесь таблицы LDT для каждой задачи . Все-таки это не настоящая ОС , а ее так скажем , модель . Настоящие многозадачные ОС квантуют вр емя не на уровне программы , а на уровне задачи , так как каждая программа м ожет иметь несколько параллельно выполняющихся потоков . Я не буду здесь организовывать механизм потоков . Это , я думаю , простительно , так как он не реализован полностью д аже в Linux . Буду и сходить из предпосылки , ч то одна программа равна одной задаче. 3.5.1 Контекст задачи. Для хранения контекста неактивной в н астоящей момент задачи процессор i80286 использует специальную область памяти , называемую сегменто м состоя ния задачи TSS (Task State Segment). Формат TSS предста влен на рис . 4. Рис . 4. Формат сегмента состоян ия задачи TSS. Сегмент TSS адресуется процессором при помощи 16-битного регистра TR (T ask Register), соде ржащего селектор дескриптора TSS, находящегося в глобальной таблице дескрипторов GDT (рис . 5). Рис . 5. Дескриптор сегмента сос тояния задачи TSS. Многозадачная операционна я система для каждой задачи должна создавать свой TSS. Перед тем как переключиться на выполнение новой задачи , процессор сохраняет контекст старой задачи в её сегменте TSS. Сегмент состояния задачи описан в фай ле tos . h : typedef struct tss word link; // поле обратной связи word sp0; // указатель стека кольца 0 word ss0; word sp1; // указатель стека кольца 1 word ss1; word sp2; // указатель стека кольца 1 word ss2; word ip; // регистры процессора word flags; word ax; word cx; wor d dx; word bx; word sp; word bp; word si; word di; word es; word cs; word ss; word ds; word ldtr; tss; 3.5.2 Переключение задач. В качестве способа переключения между задачами выберем команду JMP . Неудобство в этом случае представляет то , что если , к примеру , задача 1 вызвала задачу 2, то верну ться к задаче 2 можно только вызвав снова команду JMP и передав ей TSS задачи 1. Реализация альтернативного метода через команду CALL позволяет создавать механизм влож енных в ызовов задач , но выглядит гораз до более трудоемким и требует организации вентилей вызова задач. Функция переключения задач называется jump_to_task() и реализована в модуле TOSSYST.ASM: 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 Переключение задач происходит в функции Timer _ int () из модуля TIMER.C. Эта функция вызывается по прер ыван ию таймера . Выбор какая задача получит про цессор в данный момент решает диспетчер з адач , организованный как функция dispatcher (), описанная в модуле TIMER.C. Диспетчер работает по самому п ростому алгоритму – по кругу переключает процессор между задачам и. 3.5.3 Разделение ресурсов. Разделение ресурсов для задач организо вано в файле SEMAPHOR.C. Сам семафор представляет собой целое 2-х байтное число ( int ). В принципе можно было обойтись и одним битом , но это требует несколько бо лее сложного кода. Так как операционная система у мен я получается ну очень крошечная , я думаю будет достаточно предположить , что максималь ное количество семафоров в системе будет равно 5. Поэтому в файле SEMAPHOR.C задан статический массив из 5 семафоров : word semaphore[5]; Работа задач с семафорами организуется при помощи 3-х функций : sem_clear() – процедура сброса семафора, sem_set() – процедура установки семафора, sem_wait() – процедура ожидания семафора. 3.5.4 Задачи. Исполняющиеся задачи организованы как просто функции , в модуле TASKS.C. Задача task1() выполняется единократно , после ч его передает управление операционной системе. Задачи task 2() и flipflop _ task () работают в бесконечных циклах , рисуя на экране двигающи еся линии , тем самым обозначая свою работу . Задача flipflop _ task () работает с меньшим периодом и только тогда , когда установлен семафор 1. Задача keyb _ task () вводит символы с клавиатуры и отображает скан-коды нажатых клавиш , а также состоян ие переключающих клавиш на экране . Если нажимается клавиша ESC , задача устанавливает семафор н омер 0. Работающая параллельно главная задача о жидает установку этого семафора . Как только семафор 0 окажется установлен , главная задача завершает свою работу и программа возвращ ает процессор в реальный режим , затем передаёт управление MS - DOS . 4. Полные исходные тексты программы. 4.1 Файл TOS.INC. Определение констант и структур для модулей , составленных на языке ассемблера. C MOS_PORT equ 70h PORT_6845 equ 63h COLOR_PORT equ 3d4h MONO_PORT equ 3b4h STATUS_PORT equ 64h SHUT_DOWN equ 0feh INT_MASK_PORT equ 21h VIRTUAL_MODE equ 0001 A20_PORT equ 0d1h A20_ON equ 0dfh A20_OFF equ 0ddh EOI equ 20h MASTER8259A equ 20h SLAVE8259A equ 0a0h KBD_PORT_A equ 60h KBD_PORT_B equ 61h L_SHIFT equ 0000000000000001b NL_SHIFT equ 1111111111111110b R_SHIFT equ 0000000000000010b NR_SHIFT equ 1111111111111101b L_CTRL equ 0000000000000100b NL_CTRL equ 1111111111111011b R_CTRL equ 0000 000000001000b NR_CTRL equ 1111111111110111b L_ALT equ 0000000000010000b NL_ALT equ 1111111111101111b R_ALT equ 0000000000100000b NR_ALT equ 1111111111011111b CAPS_LOCK equ 0000000001000000b SCR_LOCK equ 0000000010000000b NUM_LOCK equ 0000000100000000b IN SERT equ 0000001000000000b STRUC idtr_struc idt_len dw 0 idt_low dw 0 idt_hi db 0 rsrv db 0 ENDS idtr_struc 4.2 Файл TOS . H . Определение констант и структур для модулей , составленных на языке Си. #define word unsigned int // Селекторы , определённые в GDT #define CODE_SELECTOR 0x08 // сегмент кода #define DATA_SELECTOR 0x10 // сегмент данных #define TASK_1_SELECTOR 0x18 // задача TASK_1 #define TASK_2_SELECTOR 0x20 // задача TASK_2 #define MAIN_TASK_SELECTOR 0x28 // глав ная задача #define VID_MEM_SELECTOR 0x30 // сегмент видеопамяти #define IDT_SELECTOR 0x38 // талица IDT #define KEYBIN_TASK_SELECTOR 0x40 // задача ввода с клавиатуры #define KEYB_TASK_SELECTOR 0x48 // задача обработки // клавиа турного прерывания #define FLIP_TASK_SELECTOR 0x50 // задача FLIP_TASK // Байт доступа typedef struct unsigned accessed : 1; unsigned read_write : 1; unsigned conf_exp : 1; unsigned code : 1; unsigned xsystem : 1; unsigned dpl : 2; unsigned present : 1; ACCESS; // Структура дескриптора typedef struct descriptor word limit; // Предел (размер сегмента в байтах ) word base_lo; // Базовый адрес сегмента (младшее сло во ) unsigned char base_hi; // Базовый адрес сегмента (старший б айт ) unsigned char type_dpl; // Поле доступа дескриптора unsigned reserved; // Зарезервированные 16 бит descriptor; // Структура вентиля вызова , задачи , прерывания, // исключ ения typedef struct gate word offset; word selector; unsigned char count; unsigned char type_dpl; word reserved; gate; // Структура сегмента состояния задачи TSS typedef struct tss word link; // поле обратной связи word sp0; // указатель стека кольца 0 word ss0; word sp1; // указатель стека кольца 1 word ss1; word sp2; // указатель стека кольца 1 word ss2; word ip; // регистры процессора word flags; word ax; word cx; word dx; word bx; word sp; word bp; word si; word di; word es; word cs; word ss; word ds; word ldtr; tss; // Размеры сегментов и структур #define TSS_SIZE (sizeof(tss)) #define DESCRIPTOR_SIZE (sizeof(descriptor)) #define GATE_SIZE (sizeof(gate)) #define IDT_SIZE (sizeof(idt)) // Физические адреса видеопамяти для цветного // и монохромного видеоадаптеров #define COLOR_VID_MEM 0xb8000L #def ine MONO_VID_MEM 0xb0000L // Видеоржеимы #define MONO_MODE 0x07 // м онохромный #define BW_80_MODE 0x02 // монохромный , 80 символов #define COLOR_80_MODE 0x03 // цветной , 80 символов // Значения для поля доступа #define TYPE_CODE_DESCR 0x18 #define TYPE_DATA_DESCR 0x10 #define TYPE_TSS_DESCR 0x01 #define TYPE_CALL_GATE 0x04 #define TYPE_TASK_GATE 0x85 #define TYPE_INTERRUPT_GATE 0x86 #define TYPE_TRAP_GATE 0x87 #define SEG_WRITABLE 0x02 #define SEG_READABLE 0x02 #define SEG_PRESENT_BIT 0x80 // Константы для обработки а ппаратных // прерыв аний #define EOI 0x20 #define MASTER8259A 0x20 #define SLAVE8259A 0xa0 // Макро для формирования фи зического // адреса из компонент сегменоного адреса // и смещения #define MK_LIN_ADDR(seg,off) (((unsigned long)(seg))<<4)+(word)(off) // Тип указателя на функцию типа void без параметров typedef void (func_ptr)(void); 4.3 Файл TOS . H . Основной файл программы. #include #include #include #include #include "tos.h" // -------------------------------- // Определения вызываемых функций // -------------------------------- // Инициализация защищенного режима и вхо д в него void Init_And_Protected_Mode_Entry(vo id); void protected_mode(unsigned long gdt_ptr, unsigned int gdt_size, word cseg, word dseg); word load_task_register(word tss_selector); void real_mode(void); void jump_to_task(word tss_selector); void load_idtr(unsigned long idt_ptr, word idt_size); void Keyb_int(void); void Timer_int(void); void Int_30h_Entry(void); extern word kb_getch(void); void enable_interrupt(void); void task1(void); void task2(void); void flipflop_task(void); void keyb_task(void); void init_tss(tss *t, word cs, word ds, un signed char *sp, func_ptr ip); void init_gdt_descriptor(descriptor *descr, unsigned long base, word limit, unsigned char type); 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); // p rg_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(vo id); // 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_abo rt(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 iret0(void); void iret1(void); // -------------------------------------- // Глобальная таблица дескрипторов GDT // -------------------------------------- descriptor gdt[11]; // -------------------------------------- // Дескрипторная таблица прерываний IDT // -------------------------------------- gate idt[] = // Обработчики исключений (word)&exception_0, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 , // 0 (word)&exception_1, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 , // 1 (word)&exception_2, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 , // 2 (word)&exception_3, CODE_SELECTOR, 0, TYPE_TRAP_GATE, 0 , // 3 (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, TYP E_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_SELE CTOR, 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_SE LECTOR, 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)&e xception_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_INTER RUPT_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 = (unsigne d 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); init_gdt_descriptor(&gdt[4], MK_LIN_ADDR(_DS, &task_2_tss), (unsigned long)TSS_SIZE-1, TYPE_TSS_DESCR | SEG_PRESENT_BIT); ini t_gdt_descriptor(&gdt[5], MK_LIN_ADDR(_DS, &main_tss), (unsigned long)TSS_SIZE-1, TYPE_TSS_DESCR | SEG_PRESENT_BIT); // Инициализируем TSS для з адач TASK_1, TASK_2 init_tss(&task_1_tss, CODE_SELECTOR, DATA_SELECTOR, task_1_stack+ sizeof(task_1_stac k), task1); init_tss(&task_2_tss, CODE_SELECTOR, DATA_SELECTOR, task_2_stack+ sizeof(task_2_stack), task2); // Инициализируем элемент 6 таблицы GDT - // дескриптор для сегмента видеопамяти // Определяем видеорежим r.h.ah = 15; int86(0x10, &r, &r) ; // Инициализация для мон охромного режима if (r.h.al == MONO_MODE) init_gdt_descriptor(&gdt[6], MONO_VID_MEM, 3999, TYPE_DATA_DESCR | SEG_PRESENT_BIT | SEG_WRITABLE); // Инициализация для цве тного режима else if (r.h.al == BW_80_MODE || r.h.al == COLOR_80_MODE) init_gdt_descriptor(&gdt[6], COLOR_VID_MEM, 3999, TYPE_DATA_DESCR | SEG_PRESENT_BIT | SEG_WRITABLE); else printf("\ nИзвините , этот видеорежим недопустим ."); exit(-1); // Инициализация э лементов 7 и 8 таблицы GDT init_gdt_descriptor(&gdt[7], MK_LIN_ADDR(_DS, &idt), (unsigned long)IDT_SIZE-1, TYPE_DATA_DESCR | SEG_PRESENT_BIT | SEG_WRITABLE); init_gdt_descriptor(&gdt[8], MK_LIN_ADDR(_DS, &keyb_task_tss), (unsigned long)TSS_SIZE-1, TYPE_TSS_DESCR | SEG_PRESENT_BIT); // Инициализация TSS для за дачи KEYB_TASK init_tss(&keyb_task_tss, CODE_SELECTOR, DATA_SELECTOR, keyb_task_stack + sizeof(keyb_task_stack), keyb_task); // Инициализация элемента 9 таблицы GDT init_gdt_descriptor(&gdt[9], MK_LIN_ADDR(_DS, &keyb_tss), (unsigned long)TSS_SIZE-1, TYPE_TSS_DESCR | SEG_PRESENT_BIT); // Инициализация TSS для за дачи KEYB обработки ввода с клавиатуры init_tss(&keyb_tss, CODE_SELECTOR, DATA_SELECTOR, keyb_stack + sizeof(keyb_stack), Keyb_int); // Инициализация элемента 10 таблицы GDT init_gdt_descriptor(&gdt[10], MK_LIN_ADDR(_DS, &flipflop_tss), (unsigned long)TSS_SIZE-1, TYPE_TSS_DESCR | SEG_PRESENT_BIT); // Инициализация TSS для за дачи FLIP_TASK init_tss (&flipflop_tss, CODE_SELECTOR, DATA_SELECTOR, flipflop_stack + sizeof(flipflop_stack), flipflop_task); // Загрузка регистра IDTR load_idtr(MK_LIN_ADDR(_DS, &idt), IDT_SIZE); // Вход в защищённый режим protected_mode(MK_LIN_ADDR(_DS, &gdt), sizeof(gd t), CODE_SELECTOR, DATA_SELECTOR); 4.4 Файл TASKS . C . Содержит функции задач. #include #include #include #include #include #include "tos.h" #include "screen.h" word dispatcher(void); // Номер текущей строки для вывода на экран extern unsigned int y; // Задача TASK_1 void task1(void) while(1) vi_print(0,y++, " Запущена задача TASK_1, " " возврат управления гла вной задаче ", 0x70); jump_to_task(MAIN_TASK_ SELECTOR); // После повторного запу ска этой задачи // снова входим в цикл. // Задача TASK_2 long delay_cnt1 = 0l; word flipflop1 = 0; void task2(void) char Buf[B_SIZE + 1]; // Буфер вывода задачи 2 static TLabel Label1; static TLabel Label2; memset(Buf, ' ', B_SIZE); Buf[B_SIZE] = 0; Label1.Pos = 0; Label1.Dir = 1; Buf[Label1.Pos] = '/'; Label2.Pos = B_SIZE; Label2.Dir = 0; Buf[Label2.Pos] = '\\'; vi_print(30, 15, "Работает задача 2:", 0x7f); while (1) // Периодически выводи м на экран д вижки, // каждый раз переключая // семафор номер 1. Этот семафор однозначно // соответствует выведенной на экран стро ке. asm sti if (delay_cnt1 > 150000l) asm cli StepLabel(&Label1, &Label2, Buf); if (flipflop1) vi_print(5, 16, Buf, 0x1f); sem_clear(1); else vi_print(5, 16, Buf, 0x1f); sem_set(1); flipflop1 ^= 1; delay_cnt1 = 0l; asm sti delay_cnt1++; word flipflop = 0; long delay_cnt = 0l; // Эта задача также периодич ески выводит на эк ран // с меньшим периодом . Кроме того , эта задача // работает только тогда , когда установлен // семафо р номер 1. void flipflop_task(void) char Buf[B_SIZE + 1]; // Буфер вывода задачи 2 static TLabel Label1; static TLabel Label2; memset(Buf, ' ', B_S IZE); Buf[B_SIZE] = 0; Label1.Pos = 0; Label1.Dir = 1; Buf[Label1.Pos] = '/'; Label2.Pos = B_SIZE; Label2.Dir = 0; Buf[Label2.Pos] = '\\'; vi_print(30, 12, "Работает задача 0:", 0x7f); while(1) asm sti if (delay_cnt > 20000l ) sem_wait(1); // ожидаем установки семафор а asm cli StepLabel(&Label1, &Label2, Buf); vi_print(5, 13, Buf, 0x1f); flipflop ^= 1; delay_cnt = 0l; asm sti delay_cnt++; word keyb_code; extern word keyb_status; // Эта задача вводит символы с клавиатуры // и отображает скан-коды нажатых клавиш // и состояние переключающих клавиш на экране. // Если нажимается клавиша ESC, задача // устанавливает семафор номер 0. // Работающая параллельно главная задача // ожидает установку этого семафора . Как то лько // семафор 0 окажется установлен , главная за дача // завершает свою работу и программа в озвращает // процессор в реальный режим , затем п ередаёт // управление MS-DOS. void keyb_task(void) vi_print(32, 20, " Key code: .... ", 0x20); vi_print(32, 21, " Key status: .... ", 0x20); while(1) keyb_code = kb_getch(); vi_put_word(45, 20, keyb_code, 0x4f); vi_put_word(45, 21, keyb_status, 0x4f); if ((keyb_code & 0x00ff) == 1) sem_set(0); 4.5 Файл SEMAPHOR.C. Содержит процед уры для р аботы с семафорами. #include #include #include #include #include "tos.h" // Массив из пяти семафоров word semaphore[5]; // Процедура сброса семафора. // Параметр sem - номер сбрасываемого семафора voi d sem_clear(int sem) asm cli semaphore[sem] = 0; asm sti // Процедура установки семафора // Параметр sem - номер устанавливаемого семафора void sem_set(int sem) asm cli semaphore[sem] = 1; asm sti // Ожидание установки семафора // Параметр sem - номер ожидаемого семафора 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 exc eption_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 #in clude #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: i n 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_sta tus] 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 @@kb 11 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 jm p 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(un signed 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(VI D_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_st ruc <,,,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 ; запоминаем для команды 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 de lay1: 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 flu sh 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_wai t 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 [(i dtr_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 x 86 реализуют нео бходимые средства для организации мультизадач ных ОС с разделением адресного простр анства и виртуальной памяти. В процессе написания данного курсового проекта мной были изучена организация рабо ты защищенного режима процессоров 80286, адресация ими свыше 1 Мб памяти , работа с прерывани ями в защищенном режиме процессора , орга низация мультизадачных операционных систем.
1Архитектура и строительство
2Астрономия, авиация, космонавтика
 
3Безопасность жизнедеятельности
4Биология
 
5Военная кафедра, гражданская оборона
 
6География, экономическая география
7Геология и геодезия
8Государственное регулирование и налоги
 
9Естествознание
 
10Журналистика
 
11Законодательство и право
12Адвокатура
13Административное право
14Арбитражное процессуальное право
15Банковское право
16Государство и право
17Гражданское право и процесс
18Жилищное право
19Законодательство зарубежных стран
20Земельное право
21Конституционное право
22Конституционное право зарубежных стран
23Международное право
24Муниципальное право
25Налоговое право
26Римское право
27Семейное право
28Таможенное право
29Трудовое право
30Уголовное право и процесс
31Финансовое право
32Хозяйственное право
33Экологическое право
34Юриспруденция
 
35Иностранные языки
36Информатика, информационные технологии
37Базы данных
38Компьютерные сети
39Программирование
40Искусство и культура
41Краеведение
42Культурология
43Музыка
44История
45Биографии
46Историческая личность
47Литература
 
48Маркетинг и реклама
49Математика
50Медицина и здоровье
51Менеджмент
52Антикризисное управление
53Делопроизводство и документооборот
54Логистика
 
55Педагогика
56Политология
57Правоохранительные органы
58Криминалистика и криминология
59Прочее
60Психология
61Юридическая психология
 
62Радиоэлектроника
63Религия
 
64Сельское хозяйство и землепользование
65Социология
66Страхование
 
67Технологии
68Материаловедение
69Машиностроение
70Металлургия
71Транспорт
72Туризм
 
73Физика
74Физкультура и спорт
75Философия
 
76Химия
 
77Экология, охрана природы
78Экономика и финансы
79Анализ хозяйственной деятельности
80Банковское дело и кредитование
81Биржевое дело
82Бухгалтерский учет и аудит
83История экономических учений
84Международные отношения
85Предпринимательство, бизнес, микроэкономика
86Финансы
87Ценные бумаги и фондовый рынок
88Экономика предприятия
89Экономико-математическое моделирование
90Экономическая теория

 Анекдоты - это почти как рефераты, только короткие и смешные Следующий
Мудрость - это когда задница успокоилась и уже ничего не ищет!
Anekdot.ru

Узнайте стоимость курсовой, диплома, реферата на заказ.

Обратите внимание, реферат по программированию "DOS-extender для компилятора Borland C++", также как и все другие рефераты, курсовые, дипломные и другие работы вы можете скачать бесплатно.

Смотрите также:


Банк рефератов - РефератБанк.ру
© РефератБанк, 2002 - 2016
Рейтинг@Mail.ru