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

Глава 7. Заглушки.

        Заглушками называются процедуры, которые не допускают дальнейшее выполнение программы. При этом они либо явно зацикливают процессор (простая заглушка), либо производят возврат в режим реальных адресов и прекращение программы. На стадии разработки и отладки операционной системы защищённого режима заглушки являются нормальной частью программы.
        При обработке простой заглушки процессор, естественно, "виснет", зато есть гарантия, что он остался в нужной точке программы, а не выполняет не предусмотренные действия. Пример такой заглушки - команда JMP с адресом перехода на саму себя, реализованный в примере 4 в предыдущей главе.
        Однако, для нас всегда важно знать, откуда был переход на заглушку и причину этого перехода, поэтому в этой главе мы рассмотрим использование заглушек вместо обработчиков исключений, которые будут сообщать об исключении, переводить процессор в R-Mode и прекращать программу.

        При вызове обработчика исключения процессор помещает в стек информацию, благодаря которой можно узнать причину возникшего исключения. Указателем на стек является пара регистров SS:SP, но т.к. мы рассматриваем программирование 32-разрядных процессоров, то во всех указателях будем использовать 32-разрядное смещение; для стека это будет SS:ESP. На рис. 7-1 представлен формат стека обработчика исключения после передачи ему управления:


Рисунок 7-1. Использование стека при передаче
управления обработчику прерывания.

        Не все исключения снабжаются кодом ошибки, поэтому для каждого обработчика нужно учитывать его наличие (см. в Приложениях "Исключения и прерывания защищённого режима").

        Для вывода информации об исключениях в примере к этой главе введены следующие процедуры:
  •  
  • put_zs - вывод ZS-строки (ZS = Zero-String - строка, заканчивающаяся нулём)
  •  
  • put_db_num, put_dw_num и put_dd_num - вывод db-, dw- и dd-числа соответственно.

            Эти процедуры производят вывод на экран в координаты X,Y, переданные в регистре DX и с атрибутом цвета, определённым в переменной text_color. Для преобразования координат в адрес используется процедура "get_adr".
           Далее, во всех наших примерах эти процедуры сохранятся и для текстового режима на них будет построена система вывода.
           Процедура putzs, определённая в предыдущих примерах, остаётся. Она является универсальной, т.к. для вывода использует адрес видеопамяти в паре регистров ES:DI и может использоваться как в R-Mode, так и в P-Mode.

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

            Принцип работы заглушек для всех исключений у нас одинаков - вывести на экран надписи и значения, переданные в стеке, поэтому все эти действия будет выполнять одна процедура "stopper".
            Stopper имеет два входных параметра:
  •  
  • номер исключения в регистре AL
  •  
  • значение флага CF в EFLAGS - если CF = 1, значит в стеке есть кода ошибки.

            Все обработчики исключений теперь будут заменены на следующие последовательности команд:
  •  
  • Для исключений без кода ошибки (например, исключение деления на 00h):
    	mov	al,00h		; Номер исключения.
    	clc			; Кода ошибки нет.
    	jmp	stopper
    
  •  
  • Для исключений с кодом кода ошибки (например, исключение общей защиты 0Dh):
    	mov	al,0dh		; Номер исключения.
    	stc			; Код ошибки есть.
    	jmp	stopper
    

            Для возврата в режим реальных адресов теперь используется переход на метку "Return_to_R_Mode".

            Далее следует текст заглушки "stopper":


    stopper: ; AL = номер исключения ; CF = 1/0 - код ошибки есть / нет mov text_color,1ah mov cl,al ; Сохраняем в CL номер исключения mov al,0 ; AL = признак наличия кода ошибки ; (1/0 - есть / нет). jnc stop_1 mov al,1 stop_1: xor ebx,ebx mov bx,ss ; EBX = BX = селектор стека lar edx,ebx ; EDX = старшая половина дескриптора ; сегмента стека. shr edx,22 test dl,1 ; Проверяем бит D (размерность сегмента ; 16 или 32 бит). jnz stop_3 ; стек - 16-разрядный cmp al,1 ; Код ошибки есть? jne stop_2 pop ax ; Error code mov dx,0747h call put_dw_num stop_2: pop ax ; IP mov dx,0647h call put_dw_num pop ax ; CS mov dx,0547h call put_dw_num pop ax ; FLAGS mov dx,0447h call put_dw_num jmp stop_5 stop_3: ; стек - 32-разрядный cmp al,1 ; Код ошибки есть? jne stop_4 pop eax ; Error Code mov dx,0747h call put_dd_num stop_4: pop eax ; EIP mov dx,0647h call put_dd_num pop eax ; CS mov dx,0547h call put_dd_num pop eax ; EFLAGS mov dx,0447h call put_dd_num stop_5: mov text_color,1fh mov dx,0347h mov al,cl call put_db_num ; Выводим номер исключения, переданный в ; процедуру в регистре AL. mov text_color,1bh lea bx,exept_mess_1 mov dx,033bh call put_zs ; "Exeption:" mov dx,043bh call put_zs ; "EFLAGS:" mov dx,053bh call put_zs ; "CS:" mov dx,063bh call put_zs ; "EIP:" mov dx,073bh call put_zs ; "Error Code:" jmp Return_to_R_Mode ; Выход в R-mode

            Для демонстрации работы заглушек используется команда UD2, предназначенная для генерации исключения недопустимой команды.

            Исходник примера можно скачать здесь: examp_5.asm, pmode_5.lib и examp_5.com в архиве examp_5.zip (9177 байт).

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

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

    Hosted by uCoz