Прерывания в защищённом режиме:

Глава 6. Установка IDT в программе.

        Как уже говорилось в разделе "защищённый режим", воспользоваться прерываниями BIOS и DOS программа, работающая в P-Mode, не может. Это связано с тем, что вектора от 00h до 1Fh заняты исключениями либо зарезервированы для них, следовательно, прерывания, отображённые на эти вектора, предоставляют доступ не к ресурсам BIOS-а, а к обработчикам прерывания. Например, команда INT 10h в режиме реальных адресов обеспечивает доступ к сервису управления видеоадаптером, а в защищённом режиме - к обработчику исключения плавающей точки x87 FPU.

        Итак, для того, чтобы определить прерывания в защищённом режиме, нужно выполнить следующие действия:
1. Перенаправить аппаратные прерывания (IRQ)
2. Создать дескрипторы для всех используемых векторов (исключений, аппаратных и программных прерываний).
3. Подготовить образ IDTR и загрузить его в регистр IDTR.
4. Разрешить прерывания

        Действие 1 были рассмотрены в предыдущей главе, действие 3 - см. в исходнике - оно совмещено с построением GDT; в этой главе будет обсуждаться только 2-е.

        Некоторые процедуры, из-за своей громоздкости, здесь будут приведены не полностью - будет показан только принцип их построения. В конце главы вы сможете найти ссылку на архив (7Кб) с файлами исходника, библиотеки и самой программы.
        Теперь для каждого примера будет своя библиотека, т.к. макросы, определяющие обработчики прерываний, можно будет менять и дополнять в пределах изучаемой темы и отдельная библиотека для каждого примера позволит избежать путаницы и лишней работы по редактированию макросов.

        Создаём дескрипторы для всех используемых векторов прерываний.

        Для всех исключений и прерываний создадим дескрипторы шлюзов прерываний и ловушек; шлюзы задач будут рассматриваться отдельно в разделе "Мультизадачность".
        Шлюзы прерываний и ловушек содержат точку входа (сегмент:смещение) и права доступа обработчика. В следующем ниже примере функцию самих обработчиков будут выполнять заглушки, определённые соответствующими макросами; функциональная реализация обработчиков исключений и аппаратных прерываний будет описана в дальнейших главах.

        Для установки дескрипторов прерываний давайте определим три следующих функции. Базовая функция set_IDT_descriptor устанавливает дескриптор с правами доступа в CX. Шлюзы прерывания и ловушки отличаются всего лишь одним битом в байте прав доступа (бит D в дескрипторе шлюза ловушки равен 0, т.к. стек, используемый обработчиком ловушек в нашем примере - 16-разрядный).


init_set_IDT_descriptor macro set_IDT_descriptor proc near ; Установка IDT-дескриптора. ; DS:BX = дескриптор в IDT ; DX = селектор сегмента кода обработчика ; EAX = смещение в сегменте кода ; CX = access_rights (права доступа) push eax push ecx push cx mov cx,dx shl ecx,16 mov cx,ax ; ECX = dw Селектор & dw offset_low mov [ bx ],ecx pop ax mov [ bx + 4 ],eax ; EAX = dw offset_hi & db access_rights & db 0 add bx,8 pop ecx pop eax ret endp endm
init_set_int_IDT_descriptor macro set_int_IDT_descriptor proc near ; Установка IDT-дескриптора прерывания. ; DS:BX = дескриптор в IDT ; DX = селектор сегмента кода обработчика ; EAX = смещение в сегменте кода push cx mov cx,8600h ; Права доступа шлюза прерывания call set_IDT_descriptor pop cx ret endp endm
init_set_trap_IDT_descriptor macro set_trap_IDT_descriptor proc near ; Установка IDT-дескриптора ловушки. ; DS:BX = дескриптор в IDT ; DX = селектор сегмента кода обработчика ; EAX = смещение в сегменте кода push cx mov cx,8700h ; Права доступа шлюза ловушки с D=0 call set_IDT_descriptor pop cx ret endp endm

        Обработчики прерываний определены следующим образом (здесь приводится неполный макрос, полностью - см. в конце главы, в архиве):



init_handlers macro ; Обработчики исключений ex_00_entry_point: exeption_00_handler ex_01_entry_point: exeption_01_handler ... ex_1f_entry_point: exeption_1f_handler ; Обработчики аппаратных прерываний IRQ_0_entry_point: IRQ_0_handler IRQ_1_entry_point: IRQ_1_handler ... IRQ_f_entry_point: IRQ_f_handler ; Обработчики программных прерываний Int_30_entry_point: Int_30_handler Int_31_entry_point: Int_31_handler endm

        Сами макросы exeption_xx_handler, IRQ_x_handler и Int_3x_handler определяются следующим образом:


exeption_00_handler macro ex_00_start: jmp ex_00_start endm
exeption_01_handler macro ex_01_start: jmp ex_01_start endm
и т.д.

IRQ_1_handler macro IRQ_1_start: jmp IRQ_1_start endm
IRQ_2_handler macro IRQ_2_start: jmp IRQ_2_start endm

        и т.д.


Int_30_handler macro iret endm
Int_31_handler macro iret endm

        Такое определение макросов позволяет легко менять обработчики - просто заменить соответствующий макрос, не меняя при этом исходника.

        Теперь определение IDT. Оно производится функцией setup_IDT, имеющей вид:


init_setup_IDT macro setup_IDT proc near lea bx,IDT mov dx,Code_selector ; Обработчики все исключений и ; прерываний в данном примере ; находятся в одном сегменте кода. lea eax,ex_00_entry_point call set_int_IDT_descriptor lea eax,ex_01_entry_point call set_trap_IDT_descriptor ; Ловушка lea eax,ex_02_entry_point call set_int_IDT_descriptor lea eax,ex_03_entry_point call set_trap_IDT_descriptor ; Ловушка lea eax,ex_04_entry_point call set_trap_IDT_descriptor ; Ловушка lea eax,ex_05_entry_point call set_int_IDT_descriptor ... lea eax,ex_1f_entry_point call set_int_IDT_descriptor lea eax,IRQ_0_entry_point call set_int_IDT_descriptor lea eax,IRQ_1_entry_point call set_int_IDT_descriptor ... lea eax,IRQ_f_entry_point call set_int_IDT_descriptor lea eax,Int_30_entry_point call set_int_IDT_descriptor lea eax,Int_31_entry_point call set_int_IDT_descriptor ret endp endm

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

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

        В этом примере определена IDT из 32h (т.е. 50) дескрипторов. Для примера - этого вполне хватает, для других программ - может не хватить, но главное, чтобы вы знали о возможности увеличить/уменьшить IDT простой заменой значения макроса idt_descr_n.
        Для программных прерываний в примере определено всего 2 дескриптора - просто чтобы было понятно, как их определять. На самом деле, операционная система защищённого режима не нуждается в программных прерываниях - её сервис удобней предоставлять в виде вызовов соответствующих процедур или задач, к тому же, в защищённом режиме прерывание обрабатывается довольно-таки долго, по сравнению с дальним вызовом.

        Сам пример рабочей программы и библиотеки вы можете скачать здесь: pmode_4.lib, examp_4.asm и examp_4.com в архиве examp_4.zip (7230 байт).

Следующая глава Оглавление Вопросы? Замечания? Пишите: sasm@narod.ru

  Copyright © Александр Семенко.
TopList

Hosted by uCoz