И вот Крис Ламон, наконец, расставил точки над i.
Он "просто" взял, и дизассемблировал код Excel 2007, отыскал отладчиком фрагмент, в котором возникала ошибка, дизасемблировал соответствующую подпрограмму, разобрался в ней, проделал ту же работу с Excel 2000 и Excel 2003, сравнил результаты, и окончательно расставил всё по своим местам.
"Отчёт о проделанной работе" Ламона - весьма объемный документ (25 страниц), поэтому весь пересказывать не стану, кто хочет - прочтёт.
Итак, самые главные два факта:
1. это действительно была ошибка отображения, точнее, ошибка в преобразовании числа с плавающей точкой в формате IEE 754 в Unicode-строку, выполняющаяся только перед отображением содержимого ячейки
2. эта ошибка действительно устранена
По сути - всё.
Но "отчёт Ламона" куда более интересен. Потому что даёт представление о реалиях действительно больших программ, созданных для массового использования.
Оказывается, с очень высокой степенью вероятности не всегда верно работающая подпрограмма написана на ассемблере.
"Не всегда" здесь означает, что из всего диапазона всех возможных значений числа с плавающей точкой в формате IEE 754 всего 12 значений приводили к ошибочному результату конверсии в строку. А именно, те, шестнадцатиричное представление которых описывается шаблоном:
0x40EFFFюF FFFFFFFы, где ю - D или F, а ы - A, B, C, D, E, F
"Написана на ассемблере с очень большой степенью вероятности" - это соображение подтверждается следующими фактами: во-первых, по наблюдениям Ламона, в коде подпрограммы отсутствуют специфические для компилированного кода конструкции (в первую очередь, - сегмент стека в стиле C/C++); во-вторых, - в коде встречаются машинные команды, которые генераторами кодов компиляторов не используются (shld, scasw, cwde). Ну и есть ещё "в-третьих" - для каждой видимой на экране ячейки электронной таблицы эта подпрограмма вызывается каждый раз, когда происходит одно из множества событий - от изменения значения в ячейке до изменения стекового порядка окон других приложений на экране (ведь перерисовывать окно приложения после того, как оно стало видимым, надо). Иными словами, - хоть компьютеры у нас быстрые, но в больших программах есть такие незаметные фрагменты, в которых без ручного ассемблерного кодирования не обойтись, что бы там не говорили апологеты освобождения от низкоуровневого кодирования - если окно электронной таблицы будет перерисовываться секундами, никому такая таблица не понадобится.
До Excel 2007 эту подпрогамму "боялись трогать" - она использовала 16-битовые регистры. Боялись трогать потому, что задача конверсии числа с плавающей точкой в строку кажется простой только тем, кто её никогда не решал.
В Excel 2007 подпрограмма стала полностью 32-битовой. При портировании её (а дизассемблированный код Excel 2002 и Excel 2007 убедительно показывает, что это было именно портирование) не был учтён столь тонкий нюанс с обнаружением обнуления счётчика (размещённого в регистре AX) одного из циклов, что тестирование просто его не выявило.
В
"заплатке" для устранения ошибки потребовалось всего две дополнительные ассемблерные команды.
Кроме неправильного отображения, ошибка гарантированно не сказывалась ни на чём.
Желающим поковыряться во внутренностях Excel 2007 и детально разобраться с причинами -
полный "отчёт Ламона".
Як RPA-платформа допомогла SkyUр автоматизувати оплату рахунків