2015-10-09 3 views
4

Что должен делать обработчик прерываний операционной системы для прерываний, связанных с ошибками кодирования?Что делать в обработчике прерываний для деления на ноль?

Например, я попытался разделить на 0 для проверки моего прерывания, и обработчик прерываний получил вызов. Однако, поскольку команда div не была успешно выполнена, EIP не обновляется до следующей инструкции после нее и после возвращения из обработчика прерываний с iret, он снова возвращается к ошибочной команде div.

mov ax, 3 
    mov dl, 0 
    div dl ; go back here again and again 

Каков правильный способ обработки этого прерывания? Несколько способов я думал:

  • dl Изменения к чему-то еще, кроме 0. Однако, я не уверен, что если dl может держать, если что-то случится, и программа обработки прерывания предполагается восстановить регистры после выхода, и Я не думаю, что корректно исправлять ошибку, предоставляя неверные вычисления, хорошо.

  • Получить следующую инструкцию после div. Однако я не думал о каком-либо простом и надежном способе получения следующей инструкции.

  • Измените верхнюю часть стека, которая в настоящее время содержит обратный адрес, на адрес другого кода. Итак, мы больше не возвращаемся к инструкции div.

+0

Проверьте, существует ли делитель 0 перед делением и помечены как ошибка перед его выполнением? Но если вы действительно хотите это сделать, вы могли бы декодировать инструкцию (по обратному адресу) в вашем Div с помощью обработчика нулевого прерывания, а затем вычислить длину текущей команды (той, которая была сбой), а затем обновить обратный адрес добавив длину инструкции.Это может привести к перезапуску при следующей инструкции (проще сказать, чем сделать). Ваша последняя идея часто используется и более разумна (возврат к общему обработчику ошибок). –

+0

@Michael Petch Я пишу обработчик прерываний на уровне ОС, поэтому я не могу предположить, что программа пользовательского пространства сделает это. Я думаю, что я соглашусь на перенаправление потока исполнения на какой-то другой код, поскольку мы не можем попытаться «исправить» вычисление или продолжить выполнение следующей инструкции с размером мусора и сделать все неправильно. Вероятно, именно поэтому, пытаясь разделить на 0 в программе C, он дает «исключение с плавающей запятой» (скомпилировано с 'gcc') и останавливает программу. –

+1

Если вы пишете ОС, а затем на DIV на ноль, я бы поместил обработчик ошибок ОС в стек в качестве обратного адреса и вернусь к нему, чтобы завершить программу пользователя и сообщить им о причине (деление на ноль). Если программы пространства пользователя хотят переопределить это, то ваша ОС может предоставить некоторый тип системного вызова для пользовательской программы для регистрации обработчика ошибок. Если обработчик зарегистрирован программой пользовательского пространства, то этот обработчик помещается в стек перед выполнением IRET. Специфика будет зависеть от того, как вы разработали свою ОС. –

ответ

6

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

В операционных системах POSIX это исключительное поведение покрывается сигналом SIGFPE. Если вы писали ОС и хотели следовать POSIX, то ваш обработчик прерываний должен отправить этот сигнал процессу. Если у процесса есть обработчик для этого сигнала, тогда переходите к нему и разрешите процессу обрабатывать это (например, так может работать блок try/catch на языке высокого уровня ... теперь вы знаете, почему исключения медленны !). Если нет обработчика сигнала, тогда процесс должен быть убит (и повторно введите свой планировщик, чтобы выяснить, что делать дальше ... и надеемся, что это был PID 1!).

Конечно, это ваша ОС, и нет причин, по которым вы должны следовать POSIX, если вы этого не хотите! Если у вас есть еще какой-то другой способ обработки ошибки в пользовательской программе, вы можете реализовать это вместо этого.

+0

Я собирался сказать: делайте то, что делает Linux, но POSIX, конечно, еще лучше :-) –

+0

О, и это также упоминается ANSI C (хотя я не думаю, что это необходимо для деления на ноль), поэтому он определенно должен использоваться в ОС. –

4

В общем, за ошибки кодирования есть только 2 варианта:

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

b) Разрешить процессу (который даже не мог выполнить нормальное выполнение), чтобы попытаться восстановить его (что труднее выполнить и проверить, чем обычное выполнение). Примером этого могут служить сигналы.