Глава 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 © Александр Семенко. |