Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm: Общие вопросы > Целочисленное деление на 0


Автор: FCM 31.10.2009, 16:45
В каком регистре CPU фиксируется деление целого на ноль того же типа?

Автор: AndNot 1.11.2009, 00:56
Ни в каком. При делении на ноль процессор генерирует исключение. Перехватывай INT 0. На 8086 в него передается адрес следующей за делением команды, а в 286-м и выше - адрес команды деления на ноль.

Автор: Mikl_ 2.11.2009, 06:02
FCM
В операциях деления предпола­гается, что частное значительно меньше, чем делимое. Деление на 1, например, может также вызвать переполнение, так как частное равно дели­телю, поэтому рекомендуется следующее пра­вило: если делитель – байт, то его значение должно быть меньше чем старший байт делителя (содер­жимое регистра ah); если делитель – двойное слово, то его значение долж­но быть меньше чем старшее двойное слово делителя (содержимое реги­стра edx). Деление на 0  сработает при div/idiv ah, div/idiv dx, div/idiv edx при любом содержимом ah/dx/edx smile 

Автор: FCM 11.11.2009, 09:30
Т.е. получается, что исключение целочисленого деления на ноль генерируется CPU в рез-те операций, которые в ассемблированном виде имеют вид  " div/idiv ah, div/idiv dx, div/idiv edx при любом содержимом ah/dx/edx" и ни в каком флаге CPU это событие не отражается?

(С другой стороны целочисленный overflow фиксируется CPU, но самостоятельно CPU такое исключение не генерит.)

Автор: Mikl_ 11.11.2009, 12:58
FCM
Вы ответили моим ответом на свой вопрос -- какой ответ вы еще ждете? smile 

Автор: FCM 11.11.2009, 16:29
Цитата(Mikl_ @  11.11.2009,  12:58 Найти цитируемый пост)
Вы ответили моим ответом на свой вопрос -- какой ответ вы еще ждете?

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

PS/
есть одна древняя притча, мораль которой такова: "Даже в самой очевидной ситуации есть хотя бы один незнакомый аспект". А уж к программированию это относится стократно. 

Автор: AndNot 16.11.2009, 15:13
Цитата(FCM @  11.11.2009,  09:30 Найти цитируемый пост)
Т.е. получается, что исключение целочисленого деления на ноль генерируется CPU в рез-те операций, которые в ассемблированном виде имеют вид  " div/idiv ah, div/idiv dx, div/idiv edx при любом содержимом ah/dx/edx" и ни в каком флаге CPU это событие не отражается?

В корне неверно. При чем тут "div ah" и прочие? Тебе это привели только для примера возникновения переполнения. Пойми одну простую вещь. Делимое всегда в два раза больше делителя, а результат всегда должен быть равен, по размеру, делителю. Поэтому возможны случаи возникновения переполнения результата. Для примера раздели 600 на 2. Если использовать команду деления на БАЙТ, то возникнет переполнение (300 не уместится в регистр AL). Если же делить на СЛОВО, то переполнения не будет, поскольку 300 легко умещается в регистр AX.

Цитата(FCM @  11.11.2009,  09:30 Найти цитируемый пост)
и ни в каком флаге CPU это событие не отражается?
Выставляется флаг OVERFLOW, в регистре флагов. Но тебе он вряд ли поможет, поскольку будет доступен только в обработчике исключения, а тот по умолчанию выведет сообщение о делении на ноль и подвесит программу.

Цитата(FCM @  11.11.2009,  09:30 Найти цитируемый пост)
С другой стороны целочисленный overflow фиксируется CPU, но самостоятельно CPU такое исключение не генерит
Это совершенно разные ситуации, поэтому и обрабатываются по разному.

Автор: FCM 16.11.2009, 19:30
Цитата(AndNot @  1.11.2009,  00:56 Найти цитируемый пост)
Ни в каком.


Цитата(AndNot @  16.11.2009,  15:13 Найти цитируемый пост)
Выставляется флаг OVERFLOW, в регистре флагов.


Так как же на самом деле?

Цитата(AndNot @  16.11.2009,  15:13 Найти цитируемый пост)
Выставляется флаг OVERFLOW, в регистре флагов. Но тебе он вряд ли поможет, поскольку будет доступен только в обработчике исключения, а тот по умолчанию выведет сообщение о делении на ноль и подвесит программу.


Меня как раз все это интересует со  стороны С++ и со стороны исключений (SEH, C++)

Автор: 111u3 17.11.2009, 05:22
FCM, если обратится к интеловским манам то можно найти следующее; Overflow is indicated with the #DE (divide error) 
exception rather than with the CF flag. т.е. тебе остается ловить это исключение.

Автор: AndNot 17.11.2009, 12:26
Цитата(FCM @  16.11.2009,  19:30 Найти цитируемый пост)
Так как же на самом деле?
На самом деле сам факт всплытия обработчика исключения 0 свидетельствует о некорректной операции деления и проверять флаги уже нет нужды. Что и делают стандартные обработчики - просто прикрывают программу (или вешают комп). Можно конечно в обработчике проанализировать опкод и если возможно, то выполнить деление повторно, расширив разрядность операндов. Но это рискованно - еще одна ошибка и получим другое исключение - двойной отказ, а это уже серьезно, поскольку малейшая ошибка уже приведет к отключению процессора.
Цитата(FCM @  16.11.2009,  19:30 Найти цитируемый пост)
Меня как раз все это интересует со  стороны С++ и со стороны исключений (SEH, C++)
Ну так с этого и надо начинать. Флаги тебе здесь не помогут, поскольку SEH универсален и всплывает при любом исключении, а не только при делении на ноль. Тут тебе скорее нужно маны по винде изучать, а не хард. Могу только предположить, что самым простым вариантом будет анализ опкода, что вызвал исключение.

Автор: 111u3 17.11.2009, 15:07
AndNot, ну допустим если быть точным двойной отказ получить в этом случае крайне трудно - так он появляется только если во время одного исключения словили другое(вернее из другого класса) это я точно говорю (это так прописано в манах и работает на практике) ну а SEH и настроить можно равно как и другие инструменты для подобных ситуаций.

Автор: AndNot 18.11.2009, 05:53
Цитата(111u3 @  17.11.2009,  15:07 Найти цитируемый пост)
это я точно говорю
А я разве не об этом говорил? smile 
Цитата(111u3 @  17.11.2009,  15:07 Найти цитируемый пост)
ну допустим если быть точным двойной отказ получить в этом случае крайне трудно
Это легче чем кажется. Чем сложнее код, тем больше вероятности наличия в нем скрытых ошибок ;) За примерами далеко ходить не надо - в соседней теме дал простейший код, но даже не заметил опечатки с условным переходом. И это обычное дело, когда явную ошибку в упор не видишь и проявится она необязательно сразу. Поэтому грамотно разрулить ситуацию в самом обработчике исключения довольно сложно (а значит рискованно) и применяют альтернативные методы, в частности обработчик только фиксирует ситуацию, а обрабатывается она уже вне обработчика (что автоматом исключает вероятность двойного отказа). Это не только безопаснее, но и более выгодно с точки зрения альтернативных путей решения ситуации. Например таким макаром в простом паскале легко обходятся деления на ноль (ну не совсем легко, приходится использовать асм, либо инлайн вставки). Но все эти альтернативные обработчики (и в паскале и SEH) сами по себе не являются обработчиками исключительных ситуаций, это скорее постобработчики, всего лишь фичи языка и ОС.

Автор: Mikl_ 18.11.2009, 06:44
FCM, а вот так нельзя? Допустим делитель в ebx
Код
test ebx,ebx
jz err_div0
div ebx
 smile 

Автор: 111u3 18.11.2009, 08:38
AndNot, не совсем верно - получить 2 исключение ни во время обработки 1, а сразу после него перед заходом в обработчик и то для каждого конкретного случая есть свои оссобенности. Я вон поток #GP ловил один за другим и не разу двойного не было. а вот когда во время исключения #GP я #PG хватанул тогда проц и перезагрузился причем без захода в обработчики #GP и #PG(на двойном исключении у меня тогда ничего не стояло). + никто не заставляет автора поста лезть в обработчики idt - его ос туда не пустит(по крайней мере за так). А SEH пишут когда данное событие не должно происходить но происходит по причине "отсутствия настроения у ос рано утром". И еще не все обработчики допускают обработку во вне. 

респект Mikl_ - зачем гемороится с исключениями когда можно ловить 0 до деления.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)