12 лет назад 5 октября 2006 в 12:26 77

В нынешнем году все прогрессивное человечество будет праздновать полувековой юбилей: ровно пятьдесят лет прошло с того момента, как Джон Бэкус и его команда в IBM начали разработку первого в мире языка программирования высокого уровня Fortran… А может, и не будет праздновать. Может, только кратко вспомнит, что в ноябре 1954 года появился язык, предназначенный для удобного описания математических формул с их последующим вычислением при помощи ЭВМ; что этот язык не только благополучно дожил до наших дней, пережив десяток реинкарнаций, но и породил целую кучу новых языков, их “диалектов” и модификаций. Хотя, возможно, не вспомнят даже этого.

Жалко. Ведь не появись в процессе эволюции современные объектно-ориентированные языки, где бы была сегодня вся эта IT-индустрия? Ну кому бы понадобились все эти Pentium 4 Extreme Edition или AMD Athlon 64, если бы не было инструментария разработки для них – соответствующего программного обеспечения? Как ни крути, а первична всегда информация, следовательно, и алгоритмы ее обработки, а уж только потом аппаратное обеспечение, которое позволяет за приемлемый квант времени эти алгоритмы выполнить. Кто-то может возразить, что в индустрии компьютерных игр дело обстоит не совсем так: сперва появляется очередная более мощная графическая карта, а уж самим фактом своего существования она провоцирует появление игр с более изощренной графикой. Не соглашусь.

С момента появления самых первых игр (а они появились ненамного позже первых ЭВМ) вся индустрия аппаратного обеспечения, предназначенного для визуализации обработанной информации, нацелена только на одно – на наиболее достоверное отображение реального мира, а до этого пока ох как далеко. Какая-нибудь GeForce FX 5900 Ultra, наверное, дает возможность отображать на экране очень реалистичное 3D пространство, но, положа руку на сердце, любая дешевая видеокамера (даже веб-камера), подключенная к простенькому телевизору, по качеству изображения положит на обе лопатки самую крутую компьютерную игру, запущенную на машине с самой навороченной видеокартой.

А ведь языки программирования, способные выполнить задачу моделирования пространства, практически ничем не отличимого от того, что мы видим по телевизору, уже имеются, но вот аппаратная часть пока сильно отстает.

Как бы там ни было, а несправедливо, уделив столько времени истории развития “железа”, обойти молчанием (или отделаться скупыми несколькими строками) историю развития языков программирования, тем более накануне юбилея. А история эта ничуть не менее интересная, да к тому же к ней причастны не только инженеры, но и представители других, в том числе и гуманитарных, профессий. Дэвид Кнут в своем “Искусстве программирования” писал: “Процесс составления программ для цифровой вычислительной машины особенно привлекателен тем, что он не только дает экономические и научные результаты, но и доставляет эстетические переживания, во многом близкие переживаниям, испытываемым при сочинении стихов или музыки”. Справедливость этих слов нет надобности доказывать тому, кто написал хотя бы одну работающую программу, состоящую более чем из пары десятков операторов. А уж если кому довелось сваять компьютерную игру, хотя бы самую простую…

Писать историю языков программирования гораздо проще, чем историю естественных языков. Никто не знает автора, допустим, русского языка, а вот авторство, скажем, языка Pascal установить несложно. С другой стороны, подобно русскому (и любому другому человеческому языку), современные языки программирования являются результатом процесса постепенной эволюции. Современный русский язык – это неизвестно какая “версия” древнерусского с вкраплениями большого количества слов из других языков. Само построение фраз современного русского явно отличается от того русского, на котором говорил, скажем, Михайло Ломоносов, а уж от языка автора “Слова о полку Игоревом” нынешний “новояз” отличается как небо и земля (ага, читать “Слово…” в оригинале, на старославянском – увлекательное занятие – прим. ред.). С современными языками программирования приблизительно такая же история.

Приступив к изучению истории языков программирования, я открыл немало любопытного для себя. Например, не без удивления, проследив генеалогию гипертекстового процессора персональных домашних страниц, более известного как PHP (мало уже найдется крупных веб-сайтов, в которых не применялся бы этот язык), я обнаружил следующее.
Сегодня имеется версия PHP 4.3.4 от 3 ноября 2003 года, а всего их было 13. Появился PHP (PHP/FI) в 1995 году, когда независимый программист Расмус Лердорф написал скрипт для подсчета и регистрации посетителей своего веб-сайта. В процессе написания стандартный Perl не совсем его устроил, он кое-что в нем подправил, дав развитие новому языку.

Еще сравнительно недавно в кругах “настоящих программистов” считалось хорошим тоном поругивать Perl, мол, это не настоящий язык программирования, а какой-то “язык страничных сценариев”. Однако появился Perl 18 декабря 1987 года в результате обобщения “настоящего” языка программирования “Си” Кернигана и Ричи – C (K&R), а также еще трех известных только узким специалистам языков: Sed, Sh и NAWK. Последний был прямым наследником языка AWK, а тот, в свою очередь, появился в 1978 году путем скрещивания языка Snobol (четвертой версии) и классического “Си” 1971 года. Первая версия языка Snobol появилась в 1962 году, а что касается языка “Си” (C), то он появился как улучшенная версия языка “Би” (B), а тот “пророс” из BCPL, который, в свою очередь, “наследовал” языку CPL, выросшему из Algol 60 – прямого потомка Alogol 58 и внука языка IAL. Язык IAL был боковой ветвью развития языка Fortran I, а тот, в свою очередь, непосредственным и единственным отпрыском нашего юбиляра – самого первого языка Fortran, народившегося на свет в ноябре 1954 года.

Вот какая запутанная генеалогия только у одного языка PHP. Но мы попробуем проследить генезис современных языков программирования с самого начала.
Теоретически, любой человек, знакомый с компьютером, может разработать новый язык программирования. Однако описать синтаксис языка и его основные конструкции – это только часть дела. Следующий шаг – создать компилятор, который будет транслировать текст программы на данном языке в объектный код – набор команд центрального процессора. И тут возникают самые разнообразные и неожиданные сложности. Появление 64-битных процессоров (Intel Itanium и, в еще большей степени, AMD Athlon 64) проявило одну проблему. Вся штука в том, что, начиная с 1985 года, когда Intel выпустила процессор 80386, и вплоть до появления Intel Itanium и AMD Athlon 64, регистры центрального процессора были 32-битными, то есть почти 10 лет все программное обеспечение было 32-битным.

Что, собственно, означает термин 32-битное ПО? Если разобрать любую готовую (откомпилированную и слинкованную) программу, то можно увидеть, что она представляет собой гигантский массив, который состоит из команд в основном трех видов:
1) команды вызова процедур ОС и BIOS (программные прерывания); 2) команды манипуляции над числами; 3) команды анализа состояния регистров и так называемого перехода в зависимости от состояния этих регистров. Процедуры ОС и BIOS, в сущности, это тоже программы, имеющие точно такую же структуру, поэтому первой группой команд можно пренебречь.

Команды второй и третьей групп имеют дело с регистрами центрального процессора, и до сих пор все эти команды “предполагали”, что размерность регистров – 32 бита. Появление 64-битной операционной системы – это лишь частичное решение проблемы, поскольку запущенная в этой ОС старая 32-битная программа все равно будет предполагать наличие 32-битных регистров центрального процессора, и, лишь вызывая процедуры ОС и BIOS, она будет опосредованно использовать всю мощь новых процессоров (за счет этого и получается заметный прирост производительности). Однако по-настоящему полноценным 64-битным (то есть таким, что команды второй и третьей групп будут рассматривать регистры процессора как 64-битные) программное обеспечение станет только тогда, когда будут созданы 64-битные компиляторы и тексты старых программ будут оттранслированы заново.

Создание нового компилятора – штука хлопотная, ибо любой оператор языка высокого уровня в процессе трансляции преобразовывается в последовательность команд центрального процессора, причем таких команд может быть до нескольких десятков. Соответственно, компилятор нужно переделать таким образом, чтобы он там, где это нужно, порождал 64-битные команды. Так что полноценное 64-битное программное обеспечение не появится, пока не выйдут 64-битные версии популярных компиляторов.

А что делает язык программирования (или его компилятор) популярным? Одни языки используются на протяжении десятилетий, другие забываются вскоре после своего появления. В чем причина? На популярность того или иного языка программирования оказывает влияние ряд факторов. Например, массовое использование языка “Си” (во всех его ипостасях) обусловлено относительной простотой его освоения, с одной стороны, и возможностью получать очень быстрый и компактный объектный код – с другой. Кто-то спросит: “Быстрый? Что значит быстрый код?”

А в том-то вся и штука – среднестатистический пользователь уверен, что на скорость выполнения программы влияют только узлы компьютера: марка и скорость процессора, объем оперативной памяти и т. п. Однако реальность такова, что однотипные программы (со сходными функциями) могут выполняться быстрее или медленнее на одной и той же конфигурации в зависимости от того языка (вернее, от компилятора языка), на котором они написаны. Справедливо и обратное – одни и те же исходные тексты могут быть одним и тем же компилятором оттранслированы в более быстрый или более медленный объектный код в зависимости от того, машина какой конфигурации использовалась для компиляции.

Строго говоря, компьютер – это не набор микросхем и разных девайсов. Компьютер – это единая система, в которой hardware и software интегрированы друг с другом так сильно, что в принципе можно утверждать: изменение конфигурации компьютера – это не только модификация его аппаратной части, но и инсталляция нового программного обеспечения (как системного, так и прикладного).

hardware и software

(Друзья! Внимание! Только что на глазах изумленной публики наш почетный историк Дмитрий Румянцев на примере зависимости hardware от software доказал и ту аксиому, что журнал Upgrade может существовать только в том виде, в котором вы привыкли его видеть. Ура, товарищи! – прим. ред.)

Динамическая кодогенерация

 

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

Теоретически, наиболее правильно было бы поставлять ПО в виде исходных текстов и соответствующих компиляторов к ним (частично это реализовано в OpenSource).

Такой подход, однако, потребовал бы, чтобы пользователи обладали достаточными навыками программирования, что нереально.

В феврале 1994 года профессор Михаэль Франц (один из ведущих исследователей в проекте Oberon Никлауса Вирта) опубликовал диссертацию, в которой предложил метод представления программ в абстрактном и независящем от возможной конкретной архитектуры компьютера виде, позволявшем получить в два раза более компактное представление файлов, нежели машинный код для CISC-процессора.

Дмитрий Румянцев

Никто не прокомментировал материал. Есть мысли?