Assembler - язык неограниченных возможностей


Обработка прерываний и исключений


До сих пор все наши программы работали в защищенном режиме с полностью отключенными прерываниями — ими нельзя было управлять с клавиатуры, они не могли работать с дисками и вообще не делали ничего, кроме чтения или записи в те или иные области памяти. Разумеется, ни одна программа не может сделать ничего серьезного в таком режиме — нам рано или поздно придется обрабатывать прерывания.

В реальном режиме адрес обработчика прерывания считывался процессором из таблицы, находящейся по адресу 0 в памяти. В защищенном режиме эта таблица, называемая IDT — таблицей дескрипторов прерываний, может находиться где угодно. Достаточно того, чтобы ее адрес и размер были загружены в регистр IDTR. Содержимое этой таблицы — не просто адреса обработчиков, как это было в реальном режиме, а дескрипторы трех типов: шлюз прерывания, шлюз ловушки и шлюз задачи (форматы этих дескрипторов рассматривались в предыдущей главе).

Шлюзы прерываний и ловушек указывают точку входа обработчика, а также его разрядность и уровень привилегий. При передаче управления обработчику процессор помещает в стек флаги и адрес возврата, так же как и в реальном режиме, но для некоторых исключений после этого в стек помещается дополнительный код ошибки, так что не все обработчики можно завершать простой командой IRETD (или IRET для 16-битного варианта). Единственное различие между шлюзом прерывания и ловушки состоит в том, что при передаче управления через шлюз прерывания автоматически запрещаются дальнейшие прерывания, пока обработчик не выполнит IRETD. Этот механизм считается предпочтительным для обработчиков аппаратных прерываний, в то время как шлюз ловушки, который не запрещает прерывания на время исполнения обработчика, предпочтителен для обработки программных прерываний (которые фактически и являются исключениями типа ловушки). Кроме того, в защищенном режиме при вызове обработчика прерывания сбрасывается флаг трассировки ТF.

Сначала рассмотрим пример программы, обрабатывающей только аппаратное прерывание клавиатуры при помощи шлюза прерываний. Для этого надо составить IDT, загрузить ее адрес командой LIDT и не забыть загрузить то, что содержится в регистре IDTR в реальном режиме, — адрес 0 и размер 4 * 256, соответствующие таблице векторов прерываний реального режима.

; pm2.asm ; Программа, демонстрирующая обработку аппаратных прерываний в защищенном ; режиме, переключается в 32-битный защищенный режим и позволяет набирать ; текст при помощи клавиш от 1 до +. Нажатие Backspace стирает предыдущий ; символ, нажатие Esc - выход из программы. ; ; Компиляция TASM: ; tasm /m /D_TASM_ pm2.asm ; (или, для версий 3.x, достаточно tasm /m pm2.asm) ; tlink /x /3 pm2.obj ; Компиляция WASM: ; wasm /D pm2.asm ; wlink file pm2.obj form DOS ; ; Варианты того, как разные ассемблеры записывают смещение из 32-битного ; сегмента в 16-битную переменную: ifdef _TASM_ so equ small offset ; TASM 4.x else so equ offset ; WASM endif ; для MASM, по-видимому, придется добавлять лишний код, который преобразует ; смещения, используемые в IDT




Начало  Назад  Вперед