ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

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

     

    Інформатика, програмування

    Міністерство освіти Республіки Білорусь Білоруський Державний

    Університет Інформатики і радіоелектроніки

    Кафедра ЕОМ

    Пояснювальна записка до курсового проекту по курсу

    "СПO ЕОМ", на тему:

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

    Виконав: студент групи 500501

    Балахонов Е.В.

    Мінськ 2000

    Зміст.

    1. Вступ. 2
    1.1 Рівні програмної підтримки захищеного режиму. 2

    1.1.1 Інтерфейс BIOS. 2

    1.1.2 інтерфейс драйвера HIMEM.SYS. 2

    1.1.3 інтерфейс EMS/VCPI. 3

    1.1.4 інтерфейс DPMI. 3

    1.1.5 розширювачі DOS (DOS-екстендера). 3
    1.2 Поточний стан справ у світі DOS-extender-ів. 4
    2. Обгрунтування вибору засобів. 4
    3. Реалізація роботи програми в захищеному режимі процесора 80286. 5
    3.1 Адресація захищеного режиму процесора 80286. 5
    3.2 Перехід в захищений режим процесора 80286 8
    3.3 Повернення до реального режиму процесора. 10
    3.4 Обробка переривань в захищеному режимі. 11
    3.5 Реалізація мультизадачності. 13

    3.5.1 Контекст завдання. 14

    3.5.2 Перемикання завдань. 15

    3.5.3 Поділ ресурсів. 16

    3.5.4 Завдання. 16
    4. Повні вихідні тексти програми. 17
    4.1 Файл TOS.INC. Визначення констант і структур для модулів, складених на мові асемблера. 17
    4.2 Файл TOS.H. Визначення констант і структур для модулів, складених на мові Сі. 18
    4.3 Файл TOS.H. Основний файл програми. 19
    4.4 Файл TASKS.C. Має функції завдань. 24
    4.5 Файл SEMAPHOR.C. Містить процедури для роботи з семафора. 26
    4.6 Файл TIMER.C. Процедури для роботи з таймером і диспетчер завдань. 27
    4.7 Файл EXCEPT.C. Обробка винятків. 28
    4.8 Файл INTPROC.C. Заглушки для апаратних переривань. 29
    4.9 Файл KEYB.C. Введення символу з клавіатури. 30
    4.10 Файл KEYBOARD.ASM. Процедури для роботи з клавіатурою. 30
    4.11 Файли SCREEN.H і SCREEN.C - модуль для роботи з відеоадаптером. 34

    4.11.1 SCREEN.H 34

    4.11.2 SCREEN.C 34
    4.12 Файл TOSSYST.ASM. Процедури для ініціалізації, переходу в захищений режим і повернення в реальний режим, для завантаження регістру TR і перемикання завдань. 36
    5. Висновки. 41
    6. Література. 41

    1. Введення.

    Операційна система MS DOS, не дивлячись на своє моральне старіння,все ще досить часто знаходить застосування на парку старих ПК, а значить, всеще існує необхідність створення програм для неї.

    На жаль, написання програм в реальному режимі процесорівархітектури Intel x86 ускладнене відсутністю можливості використовувати впрограмі оперативну пам'ять обсягом понад горезвісних 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не відкриває для програм доступ до захищеного режиму. Він повністюпрацює в реальному режимі, а для звернення до розширеної пам'яті використовуєабо недокументовані машинну команду LOADALL (якщо використовуєтьсяпроцесор 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. Після переходу більшостікористувачів у середу Win32 необхідність у DOS extender-ах різкоскоротилася і більшість таких фірм, не зумівши зорієнтуватися вумовах, що змінилися, припинили своє існування.

    Багато фірм, які розробляли компілятори для DOS, включали в постачаннясвоїх середовищ програмування DOS-extender-и власної розробки. Такимприкладом може служити фірма Borland (нині підрозділ фірми Corel) з її
    Borland Pascal, Borland C + + і розширювачем DOS RTM.

    У даний момент доступні декілька DOS-extender-ів з вільноїліцензії, які можуть використовуватися ким завгодно для будь-яких цілей. І цезрозуміло, грошей на них зараз не заробиш.

    Приклади таких програм:

    - ZRDX by Sergey Belyakov (http://www.zrdx.da.ru) < p> Маленький і функціональний DOS-extender для Watcom C + + і 32-х бітових виконуваних файлів формату OS/2 LE. Використовується в комерційних програмах, таких як антивірус AVP для DOS32.

    - WDOSX by Michael Tippach (http://www.wuschel.demon.co.uk)

    Найбільш вразили мене 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;

    // зарезервоване поле, має бути < br>// скинуто в 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)) ss = ds; t-> ip = (word) ip;// покажчик команд t-> sp = (word) sp;// зсув стека t-> bp = (word) sp;
    )

    // ---------------------------------------- ---------< br>//Функція ініціалізації дескриптора в таблиці 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;

    // зарезервоване поле, має бути < br>// скинуто в 0 завжди (для процесорів 286) descr-> reserved = 0;
    )

    // ---------------------------------------- -------< br>//Ініціалізація всіх таблиць і вхід
    //В захищений режим
    //-----------------------------------------------

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

    init_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_stack), task1);

    init_tss (& task_2_tss, CODE_SELECTOR, DATA_SELECTOR, task_2_stack + sizeof (task_2_stack), task2);

    // Ініціалізіруем елемент 6 таблиці GDT -
    // дескриптор для сегменту відеопам'яті

    // Визначаємо відеорежим rhah = 15; int86 (0x10, & r, & r);

    // Ініціалізація для монохромного режиму if (rhal == MONO_MODE) init_gdt_descriptor (& gdt [6], MONO_VID_MEM,

    3999, TYPE_DATA_DESCR | SEG_PRESENT_BIT | SEG_WRITABLE);
    // Ініціалізація для кольорового режиму else if (rhal == BW_80_MODE | | rhal == 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); < p>// Ініціалізація елемента 9 таблиці GDT init_gdt_descriptor (& gdt [9],

    MK_LIN_ADDR (_DS, & keyb_tss),

    (unsigned long) TSS_SIZE-1, < p> 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 (gdt),

    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_1void task1 (void)
    (While (1)
    (vi_print (0, y + +, "Запущена завдання TASK_1,"

    "повернення управління головної задачі", 0x70); jump_to_task (MAIN_TASK_SELECTOR);

    // Після повторного запуску цього завдання
    // знову входимо в цикл.
    )
    )

    // Завдання TASK_2long 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_SIZE);
    Buf [B_SIZE] = 0;

    Label1.Pos = 0;
    Label1.Dir = 1;
    Buf [Label1.Pos] ='/';

    Label2.Pos = B_SIZE; < br> 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 - номер скидається семафораvoid 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"

    // ---------------------------------- ---------< br>//Модуль обслуговування таймера
    //------------------------------------------- < p> # 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;

    // ------------------------- -----------------< br>//Оброблювач апаратного переривання таймера
    //------------------------------------------

    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
    )

    // --------------------------------------< br >//Диспетчер завдань
    //--------------------------------------

    // Масив селектор, що вказують на 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 )


    4.7 Файл EXCEPT.C. Обробка винятків.


    # include
    # include
    # include
    # include
    # include "tos.h"

    void prg_abort (int err);

    // Номер поточного рядка для виводу на екран

    extern unsigned int y;

    // Обробники винятків

    void exception_0 (void) (prg_abort (0);)void exception_1 (void) (prg_abort (1);)void exception_2 (void) (prg_abort (2);)void exception_3 (void) (prg_abort (3);)void exception_4 (void) (prg_abort (4);)void exception_5 (void) (prg_abort (5);)void exception_6 (void) (prg_abort (6);)void exception_7 (void) (prg_abort (7);)void exception_8 (void) (prg_abort (8);)void exception_9 (void) (prg_abort (9);)void exception_A (void) (prg_abort (0xA);)void exception_B (void) (prg_abort (0xB);)void exception_C (void) (prg_abort (0xC);)void exception_D (void) (prg_abort (0xD);)void exception_E (void) (prg_abort (0xE);)void exception_F (void) (prg_abort (0xF);)void exception_10 (void) (prg_abort (0x10);)void exception_11 (void) (prg_abort (0x11);)void exception_12 (void) (prg_abort (0x12);)void exception_13 (void) (prg_abort (0x13);)void exception_14 (void) (prg_abort (0x14);)void exception_15 (void) (prg_abort (0x15);)void exception_16 (void) (prg_abort (0x16);)void exception_17 (void) (prg_abort (0x17);)void exception_18 (void) (prg_abort (0x18);)void exception_19 (void) (prg_abort (0x19);)void exception_1A (void) (prg_abort (0x1A);)void exception_1B (void) (prg_abort (0x1B);)void exception_1C (void) (prg_abort (0x1C);)void exception_1D (void) (prg_abort (0x1D);)void exception_1E (void) (prg_abort (0x1E);)void exception_1F (void) (prg_abort (0x1F);)

    // ----------------------------- -
    //Аварійний вихід з програми
    //------------------------------

    void prg_abort (int err)
    (Vi_print (1, y + +, "ERROR! ---> Сталося виключення", 0xc);

    real_mode ();// Повертаємося до реального режиму

    // В реальному режимі виводимо повідомлення про виключення

    gotoxy (1, + + y); cprintf ( "Виключення% X, натисніть будь-яку клавішу", err); getch ();

    textcolor ( WHITE); textbackground (BLACK); clrscr (); exit (0);
    )


    4.8 Файл INTPROC.C. Заглушки для апаратних переривань.


    # include
    # include
    # include
    # include
    # include "tos.h"

    // Заглушки для необроблюваних
    //Апаратних переривань.

    void iret0 (void)
    (//Перший контролер переривань asm (push ax mov al, EOI out MASTER8259A, al pop ax pop bp iret
    )
    )

    // ---------------------------------------- -------------------< br>//Другий контролер переривань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

    P286include "tos.inc"

    ; ------------------------------------ ------< br>; Модуль обслуговування клавіатури
    ; ------------------------------------------

    PUBLIC _Keyb_int, _Int_30h_Entry, _key_code, _keyb_status
    EXTRN _beep: PROC
    DATASEG

    _key_flag db 0

    _key_code dw 0 ext_scan db 0

    _keyb_status dw 0

    CODESEG

    PROC _Keyb_int NEAR cli

    call _beep

    push ax mov al, [ext_scan] cmp al, 0 jz normal_scan1 cmp al, 0e1h jz pause_key

    in al, 60h

    cmp al, 2ah jz intkeyb_exit_1 cmp al, 0aah jz intkeyb_exit_1

    mov ah, [ext_scan] call Keyb_PutQ

    mov al, 0 mov [ext_scan], al jmp intkeyb_exit

    pause_key:

    in al, 60h cmp al, 0c5h jz pause_key1 cmp al, 45h jz pause_key1

    jmp intkeyb_exit

    pause_key1: mov ah, [ext_scan] call Keyb_PutQ

    mov al, 0 mov [ext_scan], al jmp intkeyb_exit

    normal_scan1: in al, 60h cmp al, 0feh jz intkeyb_exit cmp al, 0e1h jz ext_key cmp al, 0e0h jnz normal_scan

    ext_key: mov [ext_scan], al jmp intkeyb_exit

    intkeyb_exit_1: mov al, 0 mov [ext_scan], al jmp intkeyb_exit

    normal_scan: mov ah, 0 call Keyb_PutQ

    intkeyb_exit: in al, 61h mov ah, al or al, 80h out 61h, al xchg ah, al out 61h, al mov al, EOI out MASTER8259A, al

    pop ax sti iret jmp _Keyb_int
    ENDP _Keyb_int


    PROC Keyb_PutQ NEAR

    push ax

    cmp ax, 002ah; L_SHIFT down jnz @ @ kb1 mov ax, [_keyb_status] or ax, L_SHIFT mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb1: cmp ax, 00aah; L_SHIFT up jnz @ @ kb2 mov ax, [_keyb_status] and ax, NL_SHIFT mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb2: cmp ax, 0036h; R_SHIFT down jnz @ @ kb3 mov ax, [_keyb_status] or ax, R_SHIFT mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb3: cmp ax, 00b6h; R_SHIFT up jnz @ @ kb4 mov ax, [_keyb_status] and ax, NR_SHIFT mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb4: cmp ax, 001dh; L_CTRL down jnz @ @ kb5 mov ax, [_keyb_status] or ax, L_CTRL mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb5: cmp ax, 009dh; L_CTRL up jnz @ @ kb6 mov ax, [_keyb_status] and ax, NL_CTRL mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb6: cmp ax, 0e01dh; R_CTRL down jnz @ @ kb7 mov ax, [_keyb_status] or ax, R_CTRL mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb7: cmp ax, 0e09dh; R_CTRL up jnz @ @ kb8 mov ax, [_keyb_status] and ax, NR_CTRL mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb8: cmp ax, 0038h; L_ALT down jnz @ @ kb9 mov ax, [_keyb_status] or ax, L_ALT mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb9: cmp ax, 00b8h; L_ALT up jnz @ @ kb10 mov ax, [_keyb_status] and ax, NL_ALT mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb10: cmp ax, 0e038h; R_ALT down jnz @ @ kb11 mov ax, [_keyb_status] or ax, R_ALT mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb11: cmp ax, 0e0b8h; R_ALT up jnz @ @ kb12 mov ax, [_keyb_status] and ax, NR_ALT mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb12: cmp ax, 003ah; CAPS_LOCK up jnz @ @ kb13 mov ax, [_keyb_status] xor ax, CAPS_LOCK mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb13: cmp ax, 00bah; CAPS_LOCK down jnz @ @ kb14 jmp keyb_putq_exit
    @ @ kb14: cmp ax, 0046h; SCR_LOCK up jnz @ @ kb15 mov ax, [_keyb_status] xor ax, SCR_LOCK mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb15: cmp ax, 00c6h; SCR_LOCK down jnz @ @ kb16 jmp keyb_putq_exit
    @ @ kb16: cmp ax, 0045h; NUM_LOCK up jnz @ @ kb17 mov ax, [_keyb_status] xor ax, NUM_LOCK mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb17: cmp ax, 00c5h; NUM_LOCK down jnz @ @ kb18 jmp keyb_putq_exit
    @ @ kb18: cmp ax, 0e052h; INSERT up jnz @ @ kb19 mov ax, [_keyb_status] xor ax, INSERT mov [_keyb_status], ax jmp keyb_putq_exit
    @ @ kb19: cmp ax, 0e0d2h; INSERT down jnz @ @ kb20 jmp keyb_putq_exit
    @ @ kb20:

    test ax, 0080h jnz keyb_putq_exit

    mov [_key_code], ax

    mov al, 0ffh mov [_key_flag], alkeyb_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] ='/';< br>)
    )
    // Якщо рухаємося направо else
    (
    // Якщо не дійшли до крайньої правої позиції if (Label1-> Pos (

    Label1-> Pos ++;

    Buf [Label1-> Pos] ='/';< br>) 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] ='/';< br>)
    )
    // Якщо рухаємося направо else
    (
    // Якщо не дійшли до крайньої правої позиції if (Label2 - > Pos (

    Label2-> Pos ++;

    Buf [Label2-> Pos] ='/';< br>) 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

    ; ----------------------------------- --------------------------------< br>; Процедура для перемикання в захищений режим.
    ; Прототип для виклику:
    ; 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 +10 d]; отримуємо селектор сегменту коду mov dx, [bp +12 d]; отримуємо селектор сегменту даних 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 delay1delay1: 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 flushp_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

    ; ---------------------------------------- ------------< br>; Повернення до реального режиму.
    ; Прототип для виклику
    ; 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 < p> 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

    ; ---------------------------------------- ---------------< br>; Завантаження регістра 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

    ; ---------------------------------------- ---------------< br>; Переключення на завдання.
    ; Прототип для виклику:
    ; 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

    ; ------------------------------< br>; Відкриваємо лінію 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

    ; ------------------------------< br>; Закриваємо лінію 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

    ; ---------------------------------------- -------------------< br>; Готуємо структуру для завантаження регістра 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

    ; ----------------------------------< br>; Встановлення контролера переривань
    ; ----------------------------------


    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

    ; --------------------------< br>; Видача звукового сигналу
    ; --------------------------

    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 < p>idle1:

    loop idle1 or al, 00000010b out KBD_PORT_B, al mov cx, 60

    idle2:

    loop idle2 pop cx loop beep0 < p> pop ax out KBD_PORT_B, al

    pop cx bx ax ret

    ENDP _beep

    ; ------------- ------------------< br>; Затримка виконання програми
    ; -------------------------------

    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

    ; -----------------------< br>; Размаскірованіе переривань
    ; -----------------------

    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 для програміста» ©

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status