Подробное исследование работы клавиатуры ПК и обслуживающих ее прерываний, страница 3

При возникновении прерывания, независимо от того, инициировано оно извне — аппаратно, или изнутри — программой, ЦПУ прежде всего сохраняет текущее состояние регистра флагов в стеке. После этого очищаются флаг прерываний (IF) и флаг трассировки (ТР). Очистка флага IF (Interrupt-enable Flag) делает то же, что и инструкция CLI (Clear Interrupt-enable Flag — очистка IP, запрет прерываний) — запрещает прерывания (все, кроме немаскируемых прерываний, напр., INT 02H), обеспечивая непрерывную работу ЦПУ в течение всего времени выполнения процедурой INT критичного задания. Обработчик прерываний должен разрешить прерывания сразу, как только это станет возможно, используя команду STI (Set Interrupt-enable Flag — установка IF, разрешение прерываний). Тем самым будет разрешено выполнение других критичных по времени прерываний. Примером критичного по времени прерывания может служить ввод символа через порт связи и его буферизация. Однако инструкция STI может быть опущена, если код обработчика очень короткий. Очистка флага TF (Trap Flag) необходима для обеспечения правильной работы программ-трассировщиков. Если флаг трассировки не сбросить, то и сам обработчик будет прерываться после каждой выполненной инструкции, что приведет к банальному зависанию.

Далее ЦПУ сохраняет в стеке текущее значение регистра сегмента кода (CS). Затем в CS заносится значение сегмента адреса обработчика прерывания, взятое из таблицы векторов прерываний. Таблица векторов прерываний находится в нижней части памяти — в самом ее начале (стартовый адрес 0000:0000). Индексация (выборка нужного адреса) в таблице производится путем умножения номера прерывания на 4 и добавления 2 (для сегментного адреса). Двойка добавляется из-за обратного порядка записи адресов, принятого в процессорах Intel — вначале размещается смещение, а затем сегмент.

Такое "перевертывание" является следствием принципа "более значимая информация хранится в более старших адресах". (На самом деле никакого перевертывания здесь нет. Просто более старшие информационные разряды чисел записывается в более старших байтах памяти. Так адрес FFFC:08A5 реально в байтах памяти запишется, как А5 08 FC FF, аналогично тому, как слово 25В7 записывается в памяти в виде В7 25.)

После этого в стеке сохраняется скорректированное значение указателя инструкций (или счетчика команд — IP — Instruction Pointer), указывающее на следующую за прерванной выполняемую команду. Далее в IP заносится смещение обработчика прерываний из таблицы векторов прерываний. Индексация смещения в таблице производится путем умножения номера прерывания на 4.

В результате этого процесса управление передается процедуре, указываемой новой парой адресов CS:IP, т.е. программе обработки прерывания. (На самом деле производится просто far-вызов программы-обработчика по адресу из таблицы векторов прерываний — CALL FAR (INT*4), где INT.— номер прерывания.) Как указывалось, одно из первых действий, которое выполняет обработчик, это разрешение прерываний командой STI. Затем все регистры, которые обработчик может модифицировать, сохраняются в стеке. Далее выполняется непосредственно обработка прерывания. По ее завершении значения регистров восстанавливаются. Если обработчик вызывается аппаратным прерыванием, он информирует Программируемый Контроллер Прерываний (PIC) об окончании обслуживания прерывания посылкой команды (EOI).

И, наконец, обработчик выполняет инструкцию IRET. IRET возвращает управление прерванному процессу, выполняя действия, противоположные тем, которые выполняются инструкцией INT. Первым из стека заполняется регистр IP. Следующее слово выталкивается в регистр сегмента кода — это адрес сегмента, в котором расположена следующая выполняемая инструкция. Последнее слово выталкивается в регистр флагов.