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