Главная страница
Навигация по странице:

  • Шлюз вызова

  • Таблица дескрипторов прерываний

  • Дескрипторы IDT

  • Переключение в защищенный режим

  • Переключение в реальный режим

  • Lab2. Защищенный режим микропроцессоров Intel x86. Лабораторная работа защищенный режим микропроцессоров intel x86 Основные сведения


    Скачать 0.54 Mb.
    НазваниеЛабораторная работа защищенный режим микропроцессоров intel x86 Основные сведения
    Дата17.11.2022
    Размер0.54 Mb.
    Формат файлаpdf
    Имя файлаLab2. Защищенный режим микропроцессоров Intel x86.pdf
    ТипЛабораторная работа
    #795112
    страница2 из 4
    1   2   3   4
    Системные дескрипторы
    В дополнение к дескрипторам сегментов кода и данных имеются дескрипторы для системных сегментов и шлюзов, используемые для управления задачами, особыми ситуациями и прерываниями.
    В байте прав доступа такого дескриптора 3-битовое поле
    TYPE объединено с битом A, образуя 4-битовое поле TYPE, определяющее тип системного дескриптора (табл. 2.2).
    Формат всех системных дескрипторов 32-битного процессора х86 представлен на рис 2.6. В процессоре 80286 старшее слово не используется и всегда равно нулю; в остальном системные дескрипторы 80286 отличаются от 32- битных дескрипторов только значениями битов поля TYPE
    (биты 8...11).
    Шлюз вызова
    Шлюзы вызовов используются для передачи управления между различными уровнями привилегированности. Их использование необходимо только в системах, где имеется более одного уровня привилегированности.
    Шлюз вызова имеет две основные функции:

    1. Определение точки входа в процедуру.
    2. Задание уровня привилегированности, требуемого для входа в процедуру.
    Таблица 2.2
    Типы системных дескрипторов
    ┌────────┬───────────────────────────────────────────────┐
    │ TYPE │
    Тип объекта

    ├────────┼───────────────────────────────────────────────┤
    │ 0000b │ Зарезервирован

    │ 0001b │ Доступный TSS процессора 80286

    │ 0011b │ Таблица LDT

    │ 0010b │ Занятый TSS процессора 80286

    │ 0100b │ Шлюз вызова

    │ 0101b │ Шлюз задачи

    │ 0110b │ Шлюз прерывания процессора 80286

    │ 0111b │ Шлюз ловушки процессора 80286

    │ 1000b │ Зарезервирован

    │ 1001b │ Доступный TSS процессора 80386

    │ 1010b │ Зарезервирован

    │ 1011b │ Занятый TSS процессора 80386

    │ 1100b │ Шлюз вызова процессора 80386

    │ 1101b │ Зарезервирован

    │ 1110b │ Шлюз прерывания процессора 80386

    │ 1111b │ Шлюз ловушки процессора 80386

    └────────┴────────────────────────────────────────────────┘
    Дескрипторы шлюзов вызова используются командами
    CALL и JMP аналогичным способом, что и дескрипторы кодовых сегментов. Они могут находиться в GDT или в LDT, но не в таблице дескрипторов прерываний (IDT).
    Поля селектора и смещения в шлюзе образуют указатель на точку входа в процедуру. Шлюз вызова гарантирует, что любые передачи управления другим сегментам будут происходить в правильные точки входа процедуры. Операнд команды передачи управления не является селектором сегмента и смещением в сегменте точки входа желаемой процедуры.
    Вместо этого селектор сегмента указывает на шлюзовой селектор, а смещение не используется.
    Уровнями привилегированности, проверяемыми при передаче управления через шлюз вызова, являются:
    1. CPL (текущий уровень привилегированности).
    2. RPL (уровень привилегированности источника запроса) селектора сегмента, который был использован для задания шлюза вызова.

    Шлюз вызова
    31 15 14-12 13 3
    0
    ┌──────────────────────────┬─┬───┬─┬─┬─┬─┬─┬─┬─┬─┬─┬───────┐

    │ │ D │ │ │ │ │ │ │ │ │ │Счетчик│
    │ Смещение 31..16 │P│ P │0│1│1│0│0│0│0│0│0│двойных│+4

    │ │ L │ │ │ │ │ │ │ │ │ │слов │
    ├──────────────────────────┼─┴───┴─┴─┴─┴─┴─┴─┴─┴─┴─┴───────┤
    │ Селектор сегмента
    │ Смещение 15..00 │+0
    └──────────────────────────┴───────────────────────────────┘
    Шлюз задачи
    31 15 14-12 13 7
    0
    ┌───────────────────────────┬─┬───┬─┬─┬─┬─┬─┬──────────────┐

    │ │ D │ │ │ │ │ │


    Резервировано │P│ PL│0│0│1│0│1│ Резервировано│ +4
    ├───────────────────────────┼─┴───┴─┴─┴─┴─┴─┴──────────────┤
    │ Селектор сегмента TSS │ Резервировано
    │ +0
    └───────────────────────────┴──────────────────────────────┘
    Шлюз прерывания
    31 15 14-12 13 4
    0
    ┌───────────────────────────┬─┬───┬─┬─┬─┬─┬─┬─┬─┬─┬────────┐

    │ │ D │ │ │ │ │ │ │ │ │ │
    │ Смещение 31..16
    │P│ Pl │0│1│1│1│0│0│0│0│Резерв │ +4
    ├───────────────────────────┼─┴───┴─┴─┴─┴─┴─┴─┴─┴─┴────────┤
    │ Селектор сегмента │ Смещение 15..00 │ +0
    └───────────────────────────┴──────────────────────────────┘
    Шлюз ловушки
    31 15 14-12 13 4 0
    ┌───────────────────────────┬─┬───┬─┬─┬─┬─┬─┬─┬─┬─┬────────┐

    │ │ D │ │ │ │ │ │ │ │ │ │
    │ Смещение 31..16
    │P│ PL│0│1│1│1│1│0│0│0│Резерв │ +4
    ├───────────────────────────┼─┴───┴─┴─┴─┴─┴─┴─┴─┴─┴────────┤
    │ Селектор сегмента │ Смещение 15..00
    │ +0
    └───────────────────────────┴──────────────────────────────┘
    Дескриптор TSS
    31 24 23 20 19-16 15 14-13 7 0
    ┌─────────────┬─┬─┬─┬─┬──────┬─┬───┬─┬─┬─┬─┬─┬─────────────┐

    │ │ │ │ │Грани-│ │ D │ │ │ │ │ │

    │База 31..24 │G│ │ │ │ ца │P│ P │0│1│0│B│1│ База 23..16 │

    │ │ │ │ │19..16│ │ L │ │ │ │ │ │

    ├─────────────┴─┴─┴─┴─┴──────┼─┴───┴─┴─┴─┴─┴─┴─────────────┤

    База 15..00
    │ Граница 15..00

    └────────────────────────────┴─────────────────────────────┘
    Дескриптор таблицы LDT
    31 24 23 20 19-16 15 14-13 7 0
    ┌─────────────┬─┬─┬─┬─┬──────┬─┬───┬─┬─┬─┬─┬─┬─────────────┐

    │ │ │ │ │Грани-│ │ D │ │ │ │ │ │

    │ База 31..24│0│0│0│0│ ца │P│ P │0│0│0│1│0│ База 23..16 │

    │ │ │ │ │19..16│ │ L │ │ │ │ │ │

    ├─────────────┴─┴─┴─┴─┴──────┼─┴───┴─┴─┴─┴─┴─┴─────────────┤

    База 15..00
    │ Граница 15..00

    └────────────────────────────┴─────────────────────────────┘
    Рис. 2.6. Системные дескрипторы

    4. DPL дескриптора сегмента кодового сегмента назначения перехода.
    Поле DPL дескриптора шлюза определяет, из каких уровней привилегированности может использоваться данный шлюз.
    Шлюзы могут использоваться для передачи управления как на более привилегированные уровни, так и на тот же уровень привилегированности (хотя в последнем случае их использование не оправдано). Для передачи управления на более привилегированные уровни шлюзы могут использоваться только командами CALL. Команда JMP может использовать шлюз только для передачи управления кодовому сегменту с тем же уровнем привилегированности или конформному кодовому сегменту с тем же или более высоким уровнем привилегированности.
    Для команды CALL при обращении к неконформному сегменту должны удовлетворяться следующие два правила привилегированности (в противном случае генерируется особая ситуация общей защиты):
    1) MAX(CPL,RPL) <= DPL шлюза;
    2) DPL кодового сегмента назначения < CPL.
    Таблица дескрипторов прерываний
    Таблица дескрипторов прерываний (IDT) ассоциирует каждый вектор прерывания или особой ситуации с дескриптором процедуры или задачи, которая обслуживает соответствующее событие. Подобно таблицам GDT и LDT, IDT представляет собой массив 8-байтовых дескрипторов. В отличие т глобальной дескрипторной таблицы, первый элемент таблицы
    IDT содержит действительный дескриптор.
    Для формирования индекса в IDT процессор умножает вектор на масштабный коэффициент 8, т.е. число байтов дескриптора. Поскольку существует всего 256 векторов, IDT не может содержать более 256 дескрипторов.
    IDT может находиться в любой области физической памяти. Процессор находит IDT при помощи регистра IDTR
    (pис. 2.7). Этот регистр содержит как 32-разрядный базовый
    адрес, так и 16-разрядную границу IDT. Команды LIDT и SIDT выполняют загрузку и сохранение содержимого регистра IDTR.
    Если вектор ссылается на дескриптор вне заданной границы, процессор входит в режим отключения. В этом режиме процессор прекращает выполнение команд до приема немаскируемого прерывания или поступления сигнала RESET.
    Процессор генерирует специальный цикл шины, указывающий на то, что он вошел в режим отключения.
    Регистр IDTR
    47 16 15 0
    ┌────────────────────────────────────┬────────────────────────┐

    Базовый адрес IDT

    Граница IDT │
    └─────────────────┬──────────────────┴─────────────┬──────────┘

    ┌────────────────────────┘

    V

    ┌───┐ ┌────────────────────────┐
    ├────>│ + ├─────>│ Шлюз для │

    └───┘ ├─── прерывания #N ────┤

    ├────────────────────────┤

    |
    |

    ├────────────────────────┤

    │ Шлюз для


    ├─── прерывания #2 ────┤

    ├────────────────────────┤

    │ Шлюз для

    └───────────────>├─── прерывания #1 ────┤
    └────────────────────────┘
    Рис. 2.7. Регистр IDTR определяет положение IDT в памяти
    Дескрипторы IDT
    Таблица дескрипторов прерываний может содержать любые из трех видов системных дескрипторов (рис. 2.6): шлюзы задачи, шлюзы прерывания и шлюзы ловушки.
    Если вектор прерывания индексирует шлюз прерывания или шлюз ловушки, то вызов обработчика происходит аналогично вызову при помощи CALL шлюза вызова. Если же вектор индексирует шлюз задачи, это приводит к переключению задачи аналогично вызову при помощи CALL шлюза задачи.
    При возникновении особой ситуации или прерывания процессор сохраняет текущее состояние в стеке (рис. 2.8).

    При возникновении некоторых особых ситуаций в защищенном режиме процессором помещается на вершину стека (после вызова процедуры прерывания) код ошибки (рис.
    2.8а).
    15 3 2 1 0
    ┌───────────────────┬─┬─┬─┐

    │T│ │E│
    │ Индекс селектора │I│I│X│

    │ │ │T│
    └───────────────────┴─┴─┴─┘
    Рис. 2.8а. Формат кода ошибки
    Процессор устанавливает бит EXT, если особая ситуация вызвана событием, внешним по отношению к программе.
    Процессор устанавливает I-бит (IDT-bit), если индексная часть кода ошибки ссылается к дескриптору шлюза в IDT.
    Если бит IDT не установлен, то бит TI указывает на то, ссылается ли код ошибки к GDT (бит TI очищен), или же к LDT
    (бит TI установлен). Остальные 14 битов - это старшие биты селектора сегмента. В некоторых случаях код ошибки является пустым (т.е. все биты его младшего слова очищены).
    В 32-битном процессоре х86 код ошибки помещается в стек в виде двойного слова, старшая половина которого резервируется.
    Полная информация о используемых прерываниях и особых ситуациях приведена в приложении 2.
    Шлюз ловушки. Процессор осуществляет межсегментную передачу управления, используя селектор и смещение, содержащиеся в шлюзе ловушки. Селектор не может адресовать никакой другой сегмент, кроме сегмента кода. При достижении команды IRET из стека восстанавливается старое состояние и выполнение прерванной задачи возобновляется.
    Шлюз прерывания. Различие между шлюзом прерывания и шлюзом ловушки состоит в их воздействии на флаг IF.
    Прерывание, использующее шлюз прерывания, очищает флаг IF, предотвращая тем самым влияние на текущий обработчик прочих возможных аппаратных прерываний. Последующая команда IRET восстанавливает флаг IF в состояние, которое он имел в сохраненном в стеке регистре EFLAGS. Прерывание,
    использующее шлюз ловушки, не изменяет флаг IF.
    Прерывания, использующие шлюзы прерывания или ловушки, вызывают очистку флага TF после того, как его текущее значение сохранено в стеке как часть регистра EFLAGS. Этим процессор предотвращает воздействие трассировки команд на реакцию прерывания.
    Последующая команда
    IRET восстанавливает флаг TF из сохраненного регистра EFLAGS.
    Шлюз задачи. Шлюз задачи в IDT косвенно ссылается на задачу. Селектор сегмента в шлюзе задачи адресует дескриптор
    TSS в GDT. Когда прерывание или особая ситуация вызывает шлюз задачи в IDT, происходит переключение задач. Обработка прерывания в отдельной задаче имеет следующие преимущества:
    1. Автоматически выполняется полное сохранение всего контекста прерванной задачи.
    2. Обработчик прерывания может быть изолирован от прочих задач за счет выделяемого ему отдельного адресного пространства.
    Переключение задачи, вызванное прерыванием, работает аналогично другим переключениям задач. Задача прерывания возвращается к прерванной задаче, выполняя команду IRET.
    Правило привилегированности, управляющее процедурами прерывания, аналогично правилу, действующему при вызове процедуры: процессор не разрешает прерыванию передавать управление менее привилегированному сегменту кода. Попытка нарушить это правило приводит к возникновению особой ситуации общей защиты. В связи с непредсказуемостью прерываний и особых ситуаций требуется гарантировать соблюдение правил защиты по привилегиям. Это достигается одним из 2 способов:
    1. Обработчики помещаются в кодовый сегмент с уровнем привилегированности 0. Такие обработчики будут выполняться всегда, независимо от CPL программы;
    2. Обработчики помещаются в подчиненных сегментах кода.

    Уровень
    Уровень привилегированности привилегированности не изменяется, не изменяется, без кода ошибки с кодом ошибки
    ├───────────────────┤ Старый ├──────────────────┤ Старый

    │<── ESP │
    │<── ESP
    ├───────────────────┤
    ├──────────────────┤
    │ Старый EFLAGS │
    │ Старый EFLAGS │
    ├─────────┬─────────┤
    ├────────┬─────────┤

    │Старый CS│

    │Старый CS│
    ├─────────┴─────────┤ Новый ├────────┴─────────┤
    │ Старый EIP │<── ESP │ Старый EIP │
    ├───────────────────┤
    ├──────────────────┤ Новый
    │ Код ошибки │<── ESP
    └──────────────────┘
    Уровень
    Уровень привилегированности привилегированности изменяется, изменяется, без кода ошибки с кодом ошибки
    ┌───────────────────┐ ESP из ┌───────────────────┐
    ESP из
    │ Не используется │<── TSS │ Не используется │<── TSS
    ├─────────┬─────────┤
    ├─────────┬─────────┤

    │Старый SS│

    │Старый SS│
    ├─────────┴─────────┤
    ├─────────┴─────────┤
    │ Старый ESP │
    │ Старый ESP │
    ├───────────────────┤
    ├───────────────────┤
    │ Старый EFLAGS │
    │ Старый EFLAGS │
    ├─────────┬─────────┤
    ├─────────┬─────────┤

    │Старый CS│

    │Старый CS│
    ├─────────┴─────────┤ Новый ├─────────┴─────────┤
    │ Старый EIP │<── ESP │ Старый EIP │
    └───────────────────┘
    ├───────────────────┤
    Новый
    │ Код ошибки │<── ESP
    └───────────────────┘
    Рис. 2.8. Сохранение состояния в стеке
    Переключение в защищенный режим
    При включении питания устанавливается реальный режим работы процессора. Для того, чтобы переключить процессор в защищенный режим, в общем случае необходимо выполнить следующие действия:
    - подготовить в оперативной памяти глобальную дескрипторную таблицу GDT. В ней должны быть созданы дескрипторы для сегментов, которые будут нужны при работе программы. Создаются как минимум два дескриптора - сегмента кода и данных;

    - если предполагается возврат в реальный режим, то необходимо знать полный адрес, c которого будет продолжено выполнение после выхода из защищенного режима (в форме сегмент: смещение). Также необходимо запомнить содержимое сегментных регистров;
    - если программа в защищенном режиме будет работать с прерываниями, то необходимо создать таблицу дескрипторов прерываний IDT, в которой описать шлюзы обработчиков прерываний и особых ситуаций;
    - запретить все прерывания;
    - открыть адресную линию A20. В реальном режиме эта линия, управляемая процессором клавиатуры 8042, может быть закрыта (всегда значение 0), и расширенная память за пределами первого мегабайта становится недоступной. Чтобы программа в защищенном режиме могла обращаться к расширенной памяти необходимо открыть прохождение сигнала через линию A20. Для этого необходимо записать в порт A 8042
    (порт 60h) байт 0DFh, что послужит командой для открывания
    A20. Для закрывания A20 нужно записать в тот же порт байт
    0DDh (в современных компьютерах не нужно);
    - загрузить регистр GDTR;
    - если создана таблица IDT, то загрузить регистр IDTR;
    - переключиться в защищенный режим, установив бит 0 в регистре CR0;
    - выполнить команду межсегментного перехода для очистки очереди команд и загрузки регистра CS селектором кодового сегмента.
    После выполнения перечисленных пунктов программа может приступать к работе в защищенном режиме.
    Переключение в реальный режим
    Для того чтобы переключиться из защищенного режима в реальный программа должна выполнить следующие действия:
    - передать управление сегменту с пределом 64 Кбайт. Это загрузит регистр CS границей, требуемой для реального режима;
    - загрузить в сегментные регистры SS, DS, ES, FS и GS селектор дескриптора, содержащего подходящие для реального режима значения: предел = 0FFFFh, бит G = 0 (байтная
    гранулярность), бит E = 0 (расширение вверх), бит W = 1
    (записываемый), бит P = 1 (присутствующий);
    - запретить все прерывания;
    - сбросить бит 0 в регистре CR0. После этого выполнение продолжается в реальном режиме;
    - выполнить команду межсегментного перехода на программу реального режима для очистки очереди команд и загрузки регистра CS сегментным адресом;
    - загрузить в регистр LIDT базу и предел таблицы прерываний реального режима;
    - разрешить прерывания;
    - загрузить сегментные регистры значениями, необходимыми для работы в реальном режиме;
    - далее программа может продолжать работу в реальном режиме.
    В процессоре 80286 не было предусмотрено программное переключение в реальный режим и при написании программ пользовались следующей особенностью систем PC AT: если записать в ячейку 0Fh CMOS-памяти значение 05h, а затем выполнить сброс процессора или перевод его в состояние отключения, то процессор перейдет в реальный режим и управление будет передано по адресу, содержащемуся в ячейке
    0040:0067h. При этом будет восстановлено состояние контроллеров прерываний.
    Сброс процессора можно инициировать путем вывода байта 0FEh в порт 64h (процессор клавиатуры 8042). Таким способом, например, выходит в реальный режим программа Multi.asm, приведенная в лабораторной работе 3.
    Проиллюстрируем все вышесказанное на примере программы, выполняющей переход в защищенный режим, простейшие действия с экраном и возврат в реальный режим.
    Рассмотрим работу программы:
    - формируем в памяти таблицы GDT и IDT. GDT содержит дескриптор, описывающий саму таблицу GDT; дескриптор, описывающий сегмент программы как сегмент кода; дескриптор, описывающий сегмент программы как сегмент данных; дескрипторы, описывающие таблицу IDT в реальном и в защищенном режимах; дескриптор, описывающий сегмент
    текстового видеобуфера. Таблица IDT содержит 16 шлюзов ловушек, ссылающихся на обработчики исключительных ситуаций, 22 пустых дескриптора и 1 шлюз прерывания, который ссылается на процедуру вывода строки на экран. Такая структура таблицы IDT приведена в качестве примера использования прерываний;
    - запрещаем прерывания;
    - открываем адресную линию A20;
    - формируем в памяти адреса для косвенных межсегментных переходов, которые нужно будет выполнить, сразу после переключения режимов работы процессора, для загрузки CS новым содержимым и очистки очереди команд;
    - загружаем регистры GDTR и IDTR;
    - переключаемся в защищенный режим, устанавливая бит
    0 регистра CR0;
    - выполняем косвенный межсегментный переход по адресу, сформированному в памяти (Protect_Jump). В результате в регистр CS заносится селектор дескриптора кодового сегмента
    (CS_CODE), и управление передается на метку Protect;
    - заносим в сегментные регистры DS, ES и SS селектор дескриптора сегмента данных;
    - вызываем рабочую процедуру, выполняющую очистку экрана и вывод сообщения, причем сообщение выводится при помощи вызова через шлюз прерывания функции вывода строки (присутствующей в том же сегменте);
    - запрещаем прерывания;
    - переключаемся в реальный режим, очищая бит 0 регистра CR0;
    - выполняем косвенный межсегментный переход по адресу, сформированному в памяти (Real_Jump). В результате в регистр CS заносится сегментный адрес программы, и управление передается на метку Real;
    - загружаем регистр IDTR значением, необходимым для адресации таблицы прерываний реального режима (База =
    0000:0000, граница = 3FFh);
    - восстанавливаем сегментные регистры;
    - закрываем адресную линию A20;
    - разрешаем прерывания;

    - передаем управление в DOS.
    ;Программа транслируется в COM-файл:
    ; TASM demo.asm
    ; Tlink demo.obj /t
    ; Demo.asm
    .386p
    ; Разрешение трансляции
    ; всех инструкций 80386
    Gdt_Descriptor
    STRUC; Шаблон дескpиптоpа GDT
    Seg_Limit dw 0
    ; Длина сегмента
    Base_Lo_Word dw 0; Младшие 16 бит базового
    ; адреса
    Base_Hi_Byte db 0 ; Биты 16..23 базового адреса
    Acces_Rights db 0; Байт прав доступа db 0
    Base_Top_Byte db 0; Биты 24..31 базового
    ; адреса
    Gdt_Descriptor
    ENDS
    Idt_Descriptor
    STRUC ; Шаблон дескриптора IDT
    Int_Offset dw 0
    ; Точка входа в процедуру
    ; обработки прерывания
    Int_Selector dw 0 ; Селектор сегмента в GDT db 0
    ;
    Access db 0
    ; Права доступа dw 0
    ;
    Idt_Descriptor
    ENDS
    Code_Seg_Access Equ 10011011b; Байт прав доступа
    ; дескриптора сегмента кода
    Data_Seg_Access Equ 10010011b; Байт прав доступа
    ; дескриптора сегмента данных
    Disable_Bit20
    Equ 11011101b; Код команды 8042
    ; для закрывания линии A20
    Enable_Bit20
    Equ 11011111b; Код команды 8042
    ; для открывания линии A20
    Port_A
    Equ 060h ; Порт A 8042
    Status_port Equ 064h ; Порт состояния 8042
    Cmos_Port
    Equ 070h ; Адрес порта CMOS-памяти

    ; Макро для записи базового адреса сегмента
    ; в дескриптор
    FILLDESCR MACRO Seg_Addr,Offset_Addr,Descr xor edx,edx
    ; EDX := 0 xor ecx,ecx
    ; ECX := 0 mov dx,Seg_Addr; Сегментная часть mov cx,offset Offset_Addr; Смещение call Form_32Bit_Address; CX:DX :=
    ; линейный адрес
    ; Занесение базового адреса в дескриптор mov
    &Descr.Base_Lo_Word,dx; mov
    &Descr.Base_Hi_Byte,cl mov
    &Descr.Base_Top_Byte,ch
    ENDM
    CSEG SEGMENT Para USE16 public 'code'
    ASSUME cs:Cseg,ds:Cseg
    ORG
    100h
    Start: jmp
    Main
    ; Глобальная дескрипторная таблица GDT
    EVEN
    Gdt label word
    ; Дескриптор, описывающий саму таблицу GDT
    Gdt_Desc
    EQU $-gdt; Селектор дескриптора
    Gdt1 Gdt_Descriptor
    ; Дескриптор, описывающий сегмент Cseg как кодовый
    Cs_Code
    EQU $-gdt; Селектор дескриптора
    Gdt2 Gdt_Descriptor
    ;** Дескриптор, описывающий Cseg как сегмент данных
    ; с пределом 0FFFEh. Он будет использоваться также
    ; в роли стекового
    Cs_Data
    EQU $-gdt; Селектор дескриптора
    Gdt3 Gdt_Descriptor
    ; Дескриптор, описывающий таблицу IDT
    Idt_Pointer Gdt_Descriptor

    ; Дескриптор, описывающий таблицу IDT реального
    ; режима
    Idt_Real
    Gdt_Descriptor<3FFh,,,data_seg_access>
    ; Дескриптор, описывающий сегмент видеопамяти
    Video_Desc EQU $-gdt; Селектор дескриптора
    GdtB800 Gdt_Descriptor<1000h,8000h,0bh,\ data_seg_access>
    Gdt_Leng
    EQU $-gdt
    ; Длина таблицы GDT
    ;Таблица дескрипторов прерываний IDT.
    EVEN
    Idt label word ex0 Idt_Descriptor ex1 Idt_Descriptor ex2 Idt_Descriptor ex3 Idt_Descriptor ex4 Idt_Descriptor ex5 Idt_Descriptor ex6 Idt_Descriptor ex7 Idt_Descriptor ex8
    Idt_Descriptor ex9 Idt_Descriptor ex10 Idt_Descriptor ex11 Idt_Descriptor ex12 Idt_Descriptor ex13 Idt_Descriptor
    ex14 Idt_Descriptor ex15 Idt_Descriptor ex16 Idt_Descriptor
    Idt_Descriptor 22 dup(<>)
    Int39 Idt_Descriptor 10000110b,0>
    Idt_Leng
    EQU $-Idt; Длина таблицы IDT
    Mess db 'Protected Mode$'
    Len dw 14d
    Gate_Failure db "Error open A20$"
    Main: FillDescr cs,Gdt,Gdt1; Формирование
    ; 32-разрядного адреса из CS:GDT и запись его
    ; в дескриптор с номером Gdt_Desc
    FillDescr cs,0,gdt2; Дескриптор Cs_Code
    ; указывает на CSEG как на кодовый сегмент.
    FillDescr cs,0,gdt3; Дескриптор Cs_Data
    ; указывает на CSEG как на сегмент данных
    FillDescr cs,Idt,Idt_Pointer; Дескриптор
    ; Idt_Pointer указывает на IDT. cli
    ; Запрет прерываний mov al,8fh; Запрет немаскируемых out cmos_port,al; прерываний jmp short $+2 mov al,5 out cmos_port+1,al mov ah,Enable_Bit20; Открываем call Gate_A20
    ; адресную линию A20 or al,al
    ; Если произошла jz A20_Opened; ошибка, то выдать mov dx,offset Gate_Failure ; сообщение mov ah,9
    ; на экран, int 21h sti ; разрешить прерывания int
    20h; вернуться в DOS
    A20_Opened:
    lea di,Real_CS; Сохранение сегмента mov word ptr cs:[di],cs ; кода для
    ; перехода в реальный режим lgdt Gdt1 ; Загрузка GDTR lidt Idt_Pointer ; Загрузка IDTR mov eax,cr0; Переходим в защищенный or eax,1
    ; режим, устанавливая mov cr0,eax ; бит 0 в регистре CR0 db 0EAh
    ; Дальний переход dw offset Protect; с непосредственным dw Cs_Code
    ; операндом
    ; Работа в защищенном режиме
    Protect: mov ax,Cs_Data mov ss,ax
    ; Регистры DS, ES и SS mov ds,ax
    ; содержат селектор mov es,ax
    ; сегмента Cs_Data call My_Proc; Вызов рабочей процедуры cli mov eax,cr0 ; Переходим в реальный and eax,0FFFEh ; режим, сбрасывая бит 0 mov cr0,eax ; регистра CR0 db 0EAh
    ; Дальний переход с dw offset Real ; непосредственным
    Real_CS dw ?
    ; операндом
    ; Работа в реальном режиме.
    Real: lidt Idt_Real ; Загружаем регистр IDTR
    ; для работы в реальном
    ; режиме mov dx,cs
    ; Восстанавливаем mov ds,dx
    ; сегментные mov ss,dx
    ; регистры mov ah,Disable_Bit20; Закрытие адресной call Gate_A20
    ; линии A20 sti
    ; Разрешение прерываний int
    20h ; Выход в DOS ex0_proc: iret
    ; Обработчики особых ex1_proc: iret
    ; ситуаций ex2_proc: iret
    ; Здесь установлены
    ex3_proc: iret
    ; заглушки вместо ex4_proc: iret
    ; обработчиков ex5_proc: iret ex6_proc: iret ex7_proc: iret ex8_proc: iret ex9_proc: iret ex10_proc: iret ex11_proc: iret ex12_proc: iret ex13_proc: iret ex14_proc: iret ex15_proc: iret ex16_proc: iret
    ;**************************************************
    ;Управление прохождением сигнала A20
    ;ВХОД: (AH)=0DDH установить A20 всегда равным нулю
    ; (AH)=0DFh открыть адресный разряд A20
    ;ВЫХОД: (AL)=0 8042 принял команду
    ;
    (AH)=2 сбой
    ;*************************************************
    Gate_A20 PROC cli
    ; Запрет прерываний call Empty_8042 jnz Gate_1 mov al,0d1h ; Выдаем команду 8042 для out Status_Port,al; записи в выходной порт call Empty_8042 jnz Gate_1 mov al,ah ; Записываем в порт A 8042 out Port_A,al
    ; код команды call Empty_8042
    Gate_1: ret
    Gate_A20 ENDP
    ;*************************************************
    ;Ждать пока буфер 8042 не опустеет
    ;Вход: нет
    ;Выход:(AL)=0 буфер пуст
    ; (AL)=2 не пуст
    ;**************************************************

    Empty_8042 PROC push cx xor cx,cx ; CX = 0 (256 повторений)
    Empty_1: in al,Status_Port ; Порт 8042 and al,00000010b ; Бит 2 очищен ? loopnz Empty_1 pop cx ret
    Empty_8042 ENDP
    ;**************************************************
    ; Формирование 32-разрядного адреса
    ; Вход: CX:DX - адрес в формате <сегмент: смещение>
    ; Выход: CX:DX - 32-разрядный линейный адрес
    Form_32Bit_Address PROC shl edx,4 add edx,ecx mov ecx,edx shr ecx,16 ret
    Form_32Bit_Address ENDP
    ;**************************************************
    ; Процедура вывода строки на экран, работает
    ; в качестве обработчика прерывания.
    ; Вход : DS:BX - адрес сообщения
    ;
    DL - строка экрана
    ;
    DH - колонка экрана
    ;**************************************************
    Int10_Proc Proc Near ; Обработчик прерывания pusha
    ; INT 39d xor cx,cx
    ; Очистка CX mov cl,dh
    ; CL = колонка sal cl,1
    ; CL = CL*2 xor dh,dh
    ; DX = строка imul dx,160d; Умножаем на число байт в строке add dx,cx; Прибавляем смещение в строке
    ; Результат: DX = смещение в видеопамяти push Video_Desc pop es ; ES = сегмент видеопамяти mov di,dx; DI = смещение в этом сегменте m: mov ax,[bx]; AL = очередной символ строки
    cmp al,'$' ; Конец строки ? jz Ex ; Да - выход mov cx,es:[di] ; Получить атрибут в CH mov ah,ch ; AX = символ с атрибутом stosw ; Записать символ в видеопамять inc bx ; Перейти к следующему символу jmp short m ex: popa iret
    ; Возврат из прерывания
    Int10_Proc Endp
    ;**************************************************
    ;Процедура выполняющая какие-либо действия
    ; в защищенном режиме
    ;*************************************************
    MY_PROC PROC pusha push es push Video_Desc; В регистр ES заносим pop es; селектор сегмента видеопамяти mov dh,0fh ; Очищаем экран call Paint_Screen mov ax,Cs_Data mov ds,ax ; DS - сегмент данных lea bx,Mess ; Адрес сообщения mov dx,200Bh ; Координаты вывода int 39d ; Вывод строки на экран pop es popa ret
    MY_PROC ENDP
    ;**************************************************
    ; Процедура очищает экран и устанавливает цвета
    ; в соответствии с заданным атрибутом.
    ; Вход : ES - селектор дескриптора текстового
    ; видеобуфера, DH - атрибут.
    ;**************************************************
    PAINT_SCREEN PROC push cx si di es mov cx,80*25; Размер видеопамяти (слов) xor si,si ; SI и DI установим на xor di,di
    ; начало видеопамяти

    Paint1: lodsw; Увеличиваем смещение
    ; в видеопамяти mov ah,dh; Байт атрибута символа mov al,20h; Код символа "ПРОБЕЛ" stosw; Записываем символ с атрибутом
    ; в видеопамять loop Paint1; Повторить для каждого
    ; символа на экране pop es di si cx
    RET
    PAINT_SCREEN ENDP
    Cseg_Leng Equ $; Длина сегмента Cseg
    Cseg Ends
    End
    Start
    1   2   3   4


    написать администратору сайта