Re[17]: Откуда такая неизбывная приверженность к константам?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 25.10.24 11:14
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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

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

Что вы решили назвать тут флагом состояния?

Вот, например, самая первая операция, которую рассматривают — сложение. Пусть у нас байтовые параметры. Сложив 0x01 и 0xFF, мы получаем 0x00. Но в знаковой интерпретации это нормально, а в беззнаковой это переполнение. Мы должны детектировать это переполнение? Если да, как выглядит этот "флаг состояния"?

Архитектура типа RISC-V намеренно лишена аналога Flags в x86. Даже не как в ARM, где у большинства команд этой группы можно управлять, есть там флаги или нет. Не знаю, насколько правильно в самом глобальном смысле это решение само по себе. Но если оно сделано, то явная проверка требуется не только на деление. Сложение, вычитание, умножение — они все требуют проверок на валидность результата, не был ли он усечён (после чего об его корректности вообще нет смысла говорить, лучше считать тупо мусором). В чём особенность тут одного деления по сравнению с остальными?

Пусть у нас теперь есть Flags в варианте, например, как в x86. Все операции ставят флаги. Мы можем добавлять JO или INTO после команды. Мы можем добавлять JC. Вопрос: почему нет парной к ней INTC?

(Да, я буду регулярно сравнивать с x86. Это "а у вас негров линчуют", я заранее согласен.)

Есть один вариант решения: флагов нет, ставьте явные проверки по диапазонам и конкретным значениям, где нужно. Есть другой: флаги есть, можно реагировать на них. Тут уже вопрос, кто и что как ставит. Я бы не против, если б SDIV ставила OF (как бы они ни звались) в случаях деления на 0 или MIN/-1. Но вводить ещё и фолт для одного-единственного случая — точно явный и неуместный перекос. Когда это сделали в S/360, там было понятно — откровенно пионерная архитектура. Когда это сделали в 8086 через 14 лет — зачем это было? Неужели не было уже понятно по опыту развития, что в этом нет смысла?

Кстати, я ни в одной архитектуре кроме POWER не видел "накопительного" флага переполнения, и то там есть такой только для знакового. А обычные надо проверять после каждой операции.

ЕМ>Если же механизм исключений имеется, но решено отказаться от возбуждения исключения, то это непонятно вообще.


Механизм появляется вместе с более высокими уровнями реализации (в RISC-V). Но его принудительная ориентация на обработку в супервизоре избыточна.

N>>Если команда не делает исключения, то надо вернуть какое-то осмысленное значение в качестве частного. Варианты — ближайшее к бесконечности с нужной стороны (лучше всего), просто ближайшее к бесконечности, ноль, что-то иное.


ЕМ>Значение, ближайшее к бесконечности, можно считать осмысленным только для деления с плавающей точкой. Для деления с фиксированной оно, наоборот, абсурдно.


И опять же. Сложили 0x01 и 0xFF в беззнаковом контексте, получили 0 вместо 0x100. Не заметили, пошли дальше, нарвались на что-то и приветъ. Будем трапаться на таком или нет? Я согласен только на универсальный подход, потому что в упор не вижу, чем деление тут должно быть таким особенным.

N>>Если бы деление на ноль вызывало исключение, то для внедрителей языков была бы дополнительная забота взаимодействия со сложным механизмом (traps) вместо простого (одна проверочная команда там, где это нужно).

ЕМ>И какова вероятность того, что в языке, реализованном для архитектуры, мало-мальски сложной (имеющей тот же диспетчер памяти), вообще не будут поддерживаться механизмы исключений?

Да вообще-то на таком уровне ровно 100%. В C нет никаких исключений. Если где-то вы видите, например, обработчик SIGFPE (в который по POSIX мапится деление на 0, если трапается), то в нём всё равно нельзя без платформенно-специфичных средств вернуться на ту же команду. Максимум это через siglongjmp() вернуться на какую-то заранее придуманную контрольную точку. Если речь про Windows, то SEH это тоже не элемент языка, а расширение для конкретной платформы.

ЕМ>Если уж они решили одновременно и упростить, и унифицировать, и оставить возможность масштабирования, то единственно правильное решение — это устанавливать флаг состояния. При наличии механизма исключений можно было бы добавить возбуждение исключения, как и для переполнения при умножении.


Да, такое определено в IEEE754. Там накопительные флаги и возможность управления ими. А теперь покажите мне такое в x86 или SystemZ (где деление на 0 трапается) такие накопительные флаги?

N>>А какая связь? Сам по себе механизм защиты памяти уже системный и требует настройки.

ЕМ>Связь такая, что у программы должна быть возможность получать информацию о нештатных ситуациях при ее выполнении. Когда процессор эту информацию имеет, но не отдает, либо отдает в неадекватном виде, это требует экстраординарных оснований. Такие основания есть?

Отлично, жду ваших оснований для отсутствия накопительных флагов переполнения в x86.

ЕМ>И что конструктивного я мог бы сказать по поводу отсутствия в языках даже самых простых в реализации средств контроля исполнения? Я действительно не знаю, почему в индустрии преобладает стремление внедрять свистоперделки, порой достаточно дорогие в реализации, но упорно избегать внедрения дешевых и эффективных средств.


В языках-то оно есть. Возьмите какую-нибудь Ada и там всё будет под полным контролем.

N>>всё, что вы хотите, это чтобы Чен явно сказал "это была наша ошибка"? И если бы он сказал, вы бы вообще не подняли тему?

ЕМ>Да, именно так. Он высказался в стиле "у нас все было правильно, просто никто не ожидал".

Не вижу в его словах такого акцента.

N>>Тогда это как минимум оффтопик для данного подфорума.

ЕМ>Это был лишь очередной пример проблемы, к которой привел произвольный выбор фиксированной константы.

Лучше бы вспомнили историю ATA геометрий — она красочнее. В общем же случае я думаю, что каждое расширение какого-то реального параметра в 2-3 раза приводит к наступанию на очередной предел.

EM> И ведь того, что выбор константы в 2 Гб тоже был неудачным, они тоже не признают.


Он был 99.99% удачен. Остальных давно ждал 64-битный режим. На это я уже отвечал.

N>>Ни у кого нет бесконечного количества ресурсов на разработку и учёт всего.


ЕМ>Да ладно бы такая ошибка была в сколько-нибудь объемном коде, с неочевидными зависимостями, которые трудно проследить в уме. Но в достаточно компактном коде загрузчика, который заполняет массив фиксированного размера, отсутствие адекватных действий при переполнении должно было насторожить.


Тогда на всём экономили.
Вон загрузчик MS-DOS где-то аж до версии 5 должен был получать io.sys первым в корневом каталоге, иначе беда. А всё потому, что решили, что нефиг в FAT даже на винче выдать десяток секторов на более умный промежуточный читатель FS. В котором из FAT это стало обязательным? Чуть ли не в 32м.

Про саму проблему трёх областей видимости (20, 32 и 64 бита адреса) уже и не вспоминаю, там и сейчас есть где плясать часами на костях.

N>>вы ввели тут уже сильно позже исходного сообщения какую-то необходимость извиняться

ЕМ>Не извиняться, а признавать свои ошибки.

Этому вообще весь блог посвящён в целом. "Old new thing" — о древностях, замшелостях и откуда они такие растут. Каждая из них это какая-то ошибка, отсталость, влияние древнего ограничения или просто недосмотр.

Это не требуется прописывать каждый раз.
The God is real, unless declared integer.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.