обзоре, посвященном новому поколению микропроцессоров х86, счел необходимым отметить отсутствие этой ошибки в Pentium Pro. Теперь, спустя почти два года, обнаружилось, что этот микропроцессор содержит другую арифметическую ошибку. И не только Pentium Pro, но и Pentium II, который на момент написания этой заметки еще не был представлен в России. Так что в некотором смысле процессора еще нет, но ошибка в нем уже есть.

Посмотрим на хронику событий. Первая информация об этом появилась в Internet, вероятно, 11 апреля (http://www.x86.org/secrets/Dan/0411.html). На одном из ПК в ходе преобразования из числа с плавающей запятой в целое в результате ошибки выдался дамп оперативной памяти (http://www.math.ufl.edu/~cws/3114/ariane-siam. html). Выяснение обстоятельств привело к созданию программы на языке ФОРТРАН, которую написал проф. В. Кахан из калифорнийского университета Беркли. Было установлено, что ошибка возникает при попытке преобразования очень больших отрицательных чисел с плавающей запятой (в окрестности чисел -295 и -2111, с общим числом различных приводящих к ошибке мантисс 231 + 247) в целое. Ясно, что подобное преобразование само по себе "ненормально": такие числа нельзя корректно преобразовать не только к 16-разрядному, но и к 32-разрядному целому, ибо для представления таких чисел в виде целых просто не хватает разрядов.

Поэтому выполняющая подобное преобразование команда FIST должна была бы "создать" максимально допустимое отрицательное число и взвести бит IE (Invalid Operand Exception) в слове состояния устройства с плавающей запятой. Однако, как уже сказано, для целого ряда операндов процессор почему-то "забывает" взвести бит IE. В качестве аналогии можно привести пример извлечения квадратного корня из отрицательного числа: ясно, что это незаконная операция, но при попытке ее выполнить программист должен получить уведомление о том, что сделать этого нельзя.

В Internet доступен целый ряд тестов, которые позволяют убедиться в наличии данной ошибки. Листинги ФОРТРАН-программ проф. Кахана имеются в http://www.cs.berkeley.edu/~wkahan/tests/ fustest#.lst, где # равно 2 или 4. Недостаток этой программы состоит в использовании нестандартной поразрядной реализации логического оператора AND, что "портит" переносимость программы. Имеется более корректная в этом смысле С-версия и ассемблерный вариант (http://www.x86.org/ftp/source/fistbug/fistbug.asm). Тому же, кто хочет убедиться в наличии ошибки, проще всего воспользоваться exe-файлом, расположенным по адресу http://www.x86.org/ftp/source/fistbug/fistbug.exe.

Было установлено, что ошибка есть только в Pentium Pro и Pentium II. Естественно, она вызвала живое обсуждение на телеконференциях Usenet, в частности на comp.sys.intel. Корпорация Intel наличие ошибки признала. Мнения по поводу способов ее исправления, как всегда, самые полярные; некоторые даже призывают к полной замене всех микропроцессоров. С моей точки зрения (в этом я согласен с большинством экспертов), последствия этого изъяна менее неприятны, чем ошибки с делением - прежде всего потому, что операция вычисления целой части от таких больших отрицательных чисел встречается довольно редко. Intel обсуждает с производителями ПО способы постановки программных "заплат".

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

Проблему нельзя и недооценивать. Хорошей иллюстрацией может служить история с французской ракетой Ariane 5, летом прошлого года взорвавшейся на первой минуте после старта (http://www.math.ufl.edu/~cws/3114/ariane-siam.html). Тщательный анализ показал, что первопричиной была ошибка в тексте программы на языке Ада. В процессе выполнения программы было произведено преобразование данных из 64-разрядного числа с плавающей запятой в 16-разрядное целое со знаком. Число с плавающей запятой оказалось больше, чем можно представить 16-разрядным целым, и возникла ситуация исключения (exception). Коды на Аде не предусматривали контроля операндов в этом месте программы...