Увеличение объема при отсутствии выгоды
Теоретическая гибкость
Неоднородная вселенная
Мнимое благо 32-разрядности
Компиляторы C++ и их производители
Длинное и короткое целое

ПКспособные работать с 32-разрядными приложениями, появились почти десять лет назад, когда Intel выпустила первый процессор марки 80386. В настоящее время появились ОС OS/2, Windows NT и Windows 95, специально разработанные для 32-разрядных программ. Хотя производители решили, что это открывает им массу новых перспектив, на самом деле не все так просто. 32-разрядное программирование породило проблему так называемого "раздувшегося" программного обеспечения, когда многие небольшие и быстрые приложения становятся более медленными и объемными.

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

И у 16-разрядных, у 32-разрядных приложений есть свои достоинства. И те и другие находят свою область применения.

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

Основные типы данных, используемые в 32-разрядном программировании, занимают по 32 бита. Это означает, например, что за один раз можно обработать целое число, находящееся в промежутке от -2 млрд. до 2 млрд. или сразу четыре символа.

Микропроцессор может манипулировать 32-разрядными значениями с помощью одной инструкции, зачастую выполняемой всего за один такт. Если оснастить кэш-памятью достаточного объема компьютер класса Pentium/100 МГц, машина сможет выполнить около 100 млн. операций сложения за секунду.

При использовании 32-разрядной адресации размер одного сегмента памяти составляет 4 Гбайт, в отличие от 64 Кбайт при 16-разрядной адресации.

По словам Алана Далла, менеджера по новым технологиям компании Powersoft, последняя предпочитает "плоскую" модель памяти, предоставляемую 32-разрядными операционными системами, поскольку таким образом увеличивается объем непосредственно адресуемой оперативной памяти. В 16-разрядной DOS приложения могут адресовать сегменты размером 64 Кбайт, получая тем самым доступ максимум к 500 Кбайт оперативной памяти. Плоская модель 32-разрядной ОС Windows NT позволяет адресовать сразу 500 Мбайт в одном сегменте.

Так почему бы, учтя все вышеописанные преимущества, не делать все приложения 32-разрядными?

Увеличение объема при отсутствии выгоды

В области компьютерных технологий, как и везде, за все приходится расплачиваться. Цена использования 32-разрядных инструкций - резкий рост объема приложения по сравнению с 16-разрядными. В большинстве случаев 16 бит достаточно для хранения всех типов данных, используемых в приложении. При преобразовании таких приложений в 32-разрядную форму они (или некоторые их части) просто увеличиваются в объеме и начинают медленнее работать.

Компания Symantec предоставляет 16-ти и 32-разрядную версии своих инструментов для разработки, которые были созданы при помощи 16- и 32-разрядных компиляторов на основе одного и того же исходного текста.

"Объем 32-разрядной версии больше", - говорит Мэнсур Сафаи, главный менеджер Symantec по средствам разработки.

Возьмем приложение для планирования, которое каждую неделю увеличивает на 7 значение числа месяца. 16-разрядная инструкция, прибавляющая 7, занимает 3 байта - 1 байт уходит на команду "ADD" и 2 - на константу 7. Такая же 32-разрядная инструкция занимает 5 байт - снова всего 1 байт на команду сложения, но на константу - уже 4.

В архитектуре Intel время выполнения 32- и 16-разрядных инструкций не зависит от длины типа данных. Операция сложения с целым, например, производится за одинаковое число тактов процессора, какое бы количество бит ни занимала константа. Тем не менее размер программы очень сильно влияет на общую скорость ее работы. Микропроцессор обрабатывает данные почти в 10 раз быстрее, чем они передаются к нему по шине из оперативной памяти. Чем меньше программа, тем больше вероятность того, что ее инструкции и данные находятся в кэш-памяти процессора или в промежуточной кэш-памяти.

Аналогичной палкой о двух концах является и 32-разрядная адресация. Возьмем, например, программу размером 100 Кбайт, в которой используется 32-разрядная адресация. Размер каждого адреса в ней увеличивается вдвое, хотя выгоды от увеличения размера сегмента в данном случае никакой. Таким образом множество программ (для которых вовсе не требуются 32-разрядные инструкции) с удвоенными размерами всех данных и адресов увеличиваются в объеме и, соответственно, начинают работать более медленно. 32-разрядные инструкции целесообразно использовать, когда объем приложения превышает 1 Мбайт. Одним из способов проверить, так ли это на самом деле, является генерация и 16-, и 32-разрядных исполняемых файлов для сравнения их размеров и скорости работы.

Теоретическая гибкость

Архитектура микропроцессоров Intel позволяет программисту использовать 16-разрядные данные и адреса в 32-разрядных программах и, наоборот - 32-разрядные данные и адреса при работе с 16-разрядными инструкциями. В нашем примере с прибавлением числовой константы 7 та же операция могла бы занять 4 байта, а не 5, если бы программист указал, что размер значения - 16 бит. Компилятор или ассемблер, которыми пользовался разработчик, сгенерировали бы при этом еще один байт, информирующий процессор об изменении статуса (16 или 32 разряда) для одной инструкции.

Это позволяет программам, работающим в основном с 16-разрядными значениями, использовать преимущества 32-разрядных инструкций только тогда, когда это необходимо. И наоборот, при написании 32-разрядных приложений можно было бы применять 16-разрядную адресацию при отсутствии потребности в большом адресном пространстве. Языки Си и Си++ позволяют разработчикам указывать размеры типов данных. Некоторые компиляторы используют такую декларацию типов для оптимизации исполняемого кода посредством применения инструкций различного размера.

В ЕХЕ- и других исполняемых файлах инструкции хранятся в связанных группах, называемых сегментами. Значение разрядности команд хранится в заголовке сегмента. Микропроцессор может переключаться между 16- и 32-разрядными режимами, переходя от сегмента к сегменту.

К сожалению, современные операционные системы склонны игнорировать данную возможность, делая ее таким образом скорее теоретической, чем практической. Windows 3.x и Windows 95, например, требуют наличия специального уровня, определяющего разрядность адресации. Процесс определения достаточно медлителен для того, чтобы утратить все преимущества, предоставляемые дифференциацией типов сегментов для хранения данных программы. Данный способ полезен в основном при использовании 16-разрядных динамических библиотек с новыми 32-разрядными приложениями.

Неоднородная вселенная

Большинство организаций, особенно крупных, обладают парком персональных компьютеров, работающих под управлением различных ОС. Несмотря на то что 16-разрядная Windows 3.1 по-прежнему является наиболее популярной из настольных систем, она постепенно заменяется на 32-разрядные Windows 95 и Windows NT. OS/2 и Windows NT Server, также являющиеся 32-разрядными, в основном устанавливаются на серверы приложений, а также используются в некоторых программах высшего класса для конечного пользователя. Однако старая добрая 16-разрядная DOS, занимающая немного места на диске, по-прежнему является неотъемлемой частью почти всех настольных систем.

Точная скорость, с которой происходит процесс перехода предприятий на 32-разрядные платформы, все еще остается предметом для дискуссии.

Многие компании избрали путь полного игнорирования Windows 95 и ожидания выхода NT 4.0. Другие переходят на Windows 95, но медленно. Есть и третья группа - фирмы, решившие работать с Windows 3.1 до тех пор, пока это возможно.

Чем все это может обернуться для вас, если вы - разработчик приложений, рассчитанных на использование в предприятиях? Наибольшую важность здесь представляет собой необходимость осознания того, что "разрядность" ОС в данном случае строго не определена.

Приложениям, использующим трехмерное моделирование, например DOOM, необходима вся мощь 32-разрядных инструкций. Но DOOM - игра, работающая в DOS. По словам Гено Коши, руководителя разработки компиляторов Watcom компании Powersoft, DOOM работает в 32-разрядном режиме с помощью модуля расширения DOS, который переключается на 16-разрядный режим всякий раз, когда необходимо выполнить операцию, связанную с поддерживаемым DOS аппаратным обеспечением (например чтение с жесткого диска). Игра была написана с использованием компилятора Watcom для DOS. В Windows 95 применяется аналогичная смешанная технология.

Большинство приложений для Windows 3.x - 16-разрядные, но, используя интерфейс разработчика Win32s компании Microsoft, вы можете работать в этой операционной системе и с 32-разрядными программами. Даже Windows NT, "чисто" 32-разрядная ОС, способна запускать 16-разрядные приложения для DOS.

По существу выходит, что у вас всегда есть выбор создания 16- или 32-разрядных приложений, независимо от платформы. К счастью, большинство инструментов для разработки способны компилировать один и тот же исходный текст и в 16-, и в 32-разрядный исполняемый файл. Во многих случаях программисту достаточно выбрать разрядность из меню и нажать на клавишу "Build" для генерации приложения.

"При пользовании инструментами Watcom вы просто выбираете нужный вам компилятор и запускаете его, - говорит Коши. - Компиляторы Watcom будут поддерживать и 16- и 32-разрядные инструкции, пока это будет нужно потребителю". Borland и Symantec избрали аналогичные стратегии. (Microsoft же сводит к минимуму поддержку разработки 16-разрядного ПО: для его создания вам придется воспользоваться Visual C++ версии 1.52.)

Используя различные инструменты, программисты могут создавать и 16-, и 32-разрядные исполняемые файлы за считанные секунды. Для очень больших систем на это уйдет лишь несколько минут. Тестирование покажет, что в большинстве случаев версия вашего приложения, имеющая меньший объем, будет работать быстрее.

Некоторые инструменты для разработки, например PowerBuilder компании Powersoft, генерируют "байтовый код", независимый от разрядности основной архитектуры. "Байтовый код" обрабатывается небольшим интерпретатором, написанным специально для каждой из платформ.

Как говорит Далл из Powersoft, - "Мы нейтральны относительно разрядности".

Системы, генерирующие "байтовый код", освобождают разработчика от необходимости заботиться о разрядности инструкций, но за это, опять же, приходится платить. Интерпретируемый "байтовый код" не может работать с той же скоростью, что и компилированная программа на Си++. Технология "байтового кода" используется также в языках Visual Basic и Java.

Мнимое благо 32-разрядности

Преобразование 16-разрядных программ в 32-разрядные зачастую принесет лишь разочарование. Приложения, изначально написанные для 16-разрядных сред, будет несложно перекомпилировать в 32-разрядные, но вероятность того, что после этого получится более объемная и медленная программа, довольно велика. Крупные же программы часто приходится основательно переписывать, для того чтобы они смогли выиграть от использования 32-разрядных инструкций. Многие меньшие по объему программы в 16-разрядном исполнении будут обладать большей производительностью.

Несмотря на то что навязчивая реклама некоторых производителей пытается убедить вас в том, что 32-разрядное ПО быстро придет на смену "устаревшему" 16-разрядному, на самом деле 32-разрядные приложения - лишь еще одна потенциальная возможность, которую надо использовать с умом.

В некоторых случаях они будут работать намного лучше, чем старое ПО. Несомненно также, что благодаря 32-разрядным инструкциям появятся приложения, которые просто невозможно было бы сделать в 16-разрядном исполнении. Но, если вы не будете осторожны, ваши маленькие и быстрые программы могут превратиться в медлительных "динозавров".

Если разработчики в процессе создания станут учитывать то, что их детище будет работать и в 16-, и в 32-разрядных средах, можно будет с выгодой пользоваться преимуществами обоих типов систем.


Компиляторы C++ и их производители

Borland C++ 5.0,
Borland International,
http://www.borland.com

Microsoft C++ 1.52, Microsoft Visual C++ 4.0,
Microsoft Corp.,
http://www.microsoft.com/devonly

Symantec C++ 7.2,
Symantec Corp.,
http://www.symantec.com

Watcom C/C++ 10.6,
Powersoft Corp.,
http://www.symantec.com


Длинное и короткое целое

Язык программирования Си разработан для множества компьютеров. Основным его преимуществом была и осталась мобильность, которая и породила нижеописываемую проблему для программистов. При перекомпиляции 16-разрядных приложений, написанных на Си или Си++ для 32-разрядной среды, все данные типа int удваиваются в размере. В результате при преобразовании из 16- в 32-разрядную форму возникают проблемы, связанные с переопределением типов.

Программисты на Си и Си++ могут использовать тип данных int (целое), а также short int (короткое целое) или long int (длинное целое), в зависимости от конкретной задачи.

Однако, в стандартном Си тип int не обладает конкретной длиной. Вместо этого принято, что тип long int имеет длину, большую или равную длине типа int, а int, в свою очередь, - длину, большую или равную длине short int. В обычном случае тип int имеет длину слова, соответствующего конкретному процессору.

Изначально на персональных компьютерах размер слова составлял 16 бит. В большинстве компиляторов Си этот размер используется и для типа short int, и для типа int. Тип long int занимал 32 бита и требовал специальной обработки. Большинство программистов на ПК не применяли тип short int, поскольку он являлся эквивалентом int.

С появлением 32-разрядных операционных систем 32-разрядные компиляторы для ПК стали интерпретировать short int как 16-разрядный тип, преобразовывая данные типа int и long int в 32-разрядные значения.

В итоге при перекомпиляции 16-разрядной программы, написанной на Си или Си++, в 32-разрядную форму, все данные типа int удваиваются в размере даже в том случае, если программист позаботился о том, чтобы значения этого типа занимали 16 бит. Итак, получается, что новая программа приобретает все наихудшее, что есть в обоих типах разрядности: для данных, размер которых строго ограничен 16-разрядным словом, используется 32-разрядное пространство. Таким образом, при перекомпиляции для 32-разрядной системы приложение увеличивается в объеме безо всякой пользы.

Если вы руководите разработкой программ на Си или Си++ в 16-разрядной среде, убедитесь, что все ваши программисты знают об этой проблеме. Не так уж сложно заставить их использовать типы short и long, чтобы получить оптимальный исполняемый файл и для 16-ти, и для 32-разрядной сред. Применения типа данных int в таких случаях следует избегать.