Здравствуйте, уважаемые подписчики.



Этот выпуск, можно сказать, юбилейный. Ровно месяц назад я открыл свою расссылку. И вот, всего лишь спустя месяц у меня уже 3600 подписчиков, что не может не радовать!!! :) Спасибо за участие и все такое.

Выпуск №6

В этом выпуске мы поговорим на следующие темы. Извините, что не будет исходников, но о них мы тоже сегодня поговорим. А так же мы продолжим разговор про защищенный режим процессора, вы узнаете, что такое шлюзы. А так же вкратце поговорим про виртуальный режим процессора 8086.

Возвращаясь к прошлым выпускам...


В 4-м выпуске, когда я расписывал вам, как писать boot sector, я допусил одну достаточно серьезную ошибку, которую признаю и благодарю Bug Maker'а, за то, что обратил на это мое внимаение. В процедуре load_sector я, первым делом, делю номер сектора на количество секоров на дорожке. Для деления используя беззнаковую команду div, предварительно расширяя ax в dx:ax знаковой командой cwd. Правда если учесть что максимальное количество секторов на гибком диске не превышает 2880, то старший, знаковый, бит ax всегда нулевой. Но, тем не менее, ошибка потенциальная. Этот фрагмент кода стоит писать так:

load_sector:
        push    ax
        push    cx

        mov     cl, 18
        div     cl

        mov     cx, dx
        inc     cx

Исправившись, я вообще убрал команду cwd, и теперь делю на байт cl. Все это, к тому же, сэкономило мне два байта. :)

Но это еще не все.. при написании boot sector'а я говорил, что это совсем не окончательная версия. Так оно и получается. Из бутсектора мы уберем код загрузки kernel. Этим будет заниматься программа setup. Следовательно, boot sector'у осанется только считать setup и запусить его... Даже если сделать более корректную обработку ошибок чтения, у нас остается около 250 байт на всякие развлечения... :)

А setup должен будет уметь достаточно многое. В него будет встроена поддержка файловой системы, поддержка выполняемых форматов файлов. Мы собираемся делать микроядро, и setup'у придется загружать помимо ядра еще несколько дополнительных программ, которые понадобятся нам для нормального старта системы.

Но об этом позже. А теперь продолжаем разбираться с защищенным режимом.

Шлюзы


В прошлом выпуске, когда я говорил о дескрипторах и дескрипторных таблицах я ни слова не упомянул о дескрипторной таблице прерываний (Interrupt description table или IDT). Эта таблица так же состоит из дескрипторов, но в отличии от LDT и GDT в этой таблице могут размечаться только шлюзы. В защищенном режиме все прерывания происходят через IDT. Традиционная таблица векторов прерываний здесь не используется.

Формат дескрипторов шлюзов отличается от дескриптора сегмента.
Для начала рассмотрим шлюз вызова.
7 6 5 4
Смещение 31-16 Права доступа Количество слов стека
3 2 1 0
Селектор Смещение 15-0

В поле прав доступа задается уровень привилегий, который должен быть ниже CPL текущего процесса, бит присутствия и соответствующий тип в остальных полях.
Селектор и смещение задают адрес вызываемой функции, при этом селектор должен присутствовать либо в GDT либо в активной LDT.
Параметр "Количество слов стека" служит для передачи аргументов в вызываемую функцию, при этом соответствующее количество слов копируется из стека текущего уровня привилегий в стек уровня привилегий вызываемой функции. Это поле использует только младшие 5 бит четвертого байта. Остальные биты должны быть нулевыми.
Обращаться к такому шлюзу, если дескриптор не расположен в IDT, можно только командой call far, при этом указываемое в команде смещение игнорируется. А селектор должен указывать на дескриптор шлюза вызова.

Шлюз прерывания и шлюз ловушки имеют одинаковый формат, отличаются между собой типами в байте прав доступа. В отличии от шлюза вызова эти шлюзы не содержат в себе Количества слов стека, поскольку прерывания бывают аппаратными и передача в них параметров через стек - бессмысленна. Эти шлюзы используются обычно только в IDT.

Шлюз задачи содержит в себе значительно меньше информации.
Во втором и третьем байте дескриптора записывается селектор TSS (Сегмента состояния задачи). Поле прав доступа заполняется аналогично другим шлюзам, но с соответствующим типом. Остальные поля дескриптора не используются.
При вызове такого шлюза происходит переключение контекста задачи. При этом вызывающая задача блокируется и не может быть вызвана до тех пор, пока вызванная задача не вернет ей управление командой iret.

Про правила доступа к шлюзам я говорил в прошлом выпуске, и в этот раз я закончу на этом. в следующем выпуске расскажу про прерывания более подробно.

Виртуальный режим процессора 8086.


Для возможности запуска из защищенного режима программ, предназначенных для реального, существует так называемый "Виртуальный режим процессора 8086". При этом полноценно работают механизмы преобразования адресов защищенного режима. А так же многозадачные системы, которые могут одновременно выполнять как защищенные задачи, так и виртуальные. При этом адресация в виртуальной задаче осуществляется традиционным для 8086 методом - сегмент/смещение.

Обращение к прерываниям осуществляется через IDT, но таблица прерываний реального режима может быть обработана из функций, шлюзы которых размещаются в IDT.
Обращение виртуальной задачи к портам так же может быть отслежено через прерывания защищенного режима. При обращении к запрещенным портам происходит исключение.
При желании может быть обеспечена абсолютно прозрачная работа нескольких виртуальных задач в одной мультизадачной среде. Но мы этой возможностью не будем пользоваться, и в своей работе будем рассчитывать на программы исключительно защищенного режима.

На этом я сегодня заканчиваю. До следующих выпусков. Пишите.

Отправлено 2001-08-10 для 3692 подписчиков.
ведущий рассылки Dron