§ Заглушки

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