§ Заглушки
Заглушками называются процедуры, которые не допускают дальнейшее выполнение программы. При этом они либо явно зацикливают процессор (простая заглушка), либо производят возврат в режим реальных адресов и прекращение программы. На стадии разработки и отладки операционной системы защищённого режима заглушки являются нормальной частью программы.При обработке простой заглушки процессор, естественно, "виснет", зато есть гарантия, что он остался в нужной точке программы, а не выполняет не предусмотренные действия. Пример такой заглушки - команда 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-числа соответственно.
Далее, во всех наших примерах эти процедуры сохранятся и для текстового режима на них будет построена система вывода.
Процедура putzs, определённая в предыдущих примерах, остаётся. Она является универсальной, т.к. для вывода использует адрес видеопамяти в паре регистров ES:DI и может использоваться как в R-Mode, так и в P-Mode.
Исходный текст этих процедур здесь не приводится, т.к. целью данной главы является определение заглушек, а не вывод на экран. В конце главы есть ссылка на архив с исходником, где вы сможете посмотреть реализацию этих процедур.
Принцип работы заглушек для всех исключений у нас одинаков - вывести на экран надписи и значения, переданные в стеке, поэтому все эти действия будет выполнять одна процедура "stopper".
Stopper имеет два входных параметра:
- номер исключения в регистре AL
- значение флага CF в EFLAGS - если CF = 1, значит в стеке есть кода ошибки.
Для исключений без кода ошибки (например, исключение деления на 00h):
1mov al, 00h ; Номер исключения. 2clc ; Кода ошибки нет. 3jmp stopperДля исключений с кодом кода ошибки (например, исключение общей защиты 0Dh):
1mov al, 0dh ; Номер исключения. 2stc ; Код ошибки есть. 3jmp stopperДля возврата в режим реальных адресов теперь используется переход на метку "Return_to_R_Mode". Далее следует текст заглушки "stopper": исходный текст программы пропущен. Для демонстрации работы заглушек используется команда UD2, предназначенная для генерации исключения недопустимой команды.
Процедуры смотреть здесь.