Трансляция программы в машинный код .

D8

BB 03 00

B8 02 00

Эволюция языков программирования.

Особенности устройства ЭВМ определяют способы её управления. Составные части ЭВМ (процессор, ОЗУ и т.п.) оперируют битовыми последовательностями. Поэтому наиболее естественным способом управления ЭВМ является кодирование информации для ЭВМ в виде всё тех же битовых последовательностей. Для первых ЭВМ альтернативных способов программированию в машинных кодах просто не существовало. Это требовало досконального знания системы команд машины и большого внимания, а сам процесс программирования в кодах был малоэффективен. Метод программирования в машинных кодах применим и к современным ЭВМ, для удобства числа записывают не в двоичной, а в шестнадцатиричной форме.

Например, так выглядит программа для системы на основе процессора 80x86, складывающая два числа:

 

Отметим, что данная программа, написанная для процессора с иной системой команд, выглядела бы совершенно по-другому.

Первая попытка оптимизации программирования в двоичных кодах заключалась в разработке специальной системы кодирования двоичных машинных команд многобуквенными мнемоническими сокращениями. Так появился язык ассемблер.

Приведённая выше программа стала выглядеть следующим образом:

 

mov AX, 02h

mov BX, 03h

add AX,BX

 

Каждый оператор в ассемблере - это одна машинная команда (но не обязательно записываемая однобайтным кодом), а программисты должны иметь дело с низкоуровневыми особенностями платформы, наподобие назначения регистров и распределения памяти. Как результат, большие программы на ассемблере достаточно трудно писать и сопровождать.

В конце 50-х начали появляться языки более высокого уровня: Лисп, Фортран и Алгол, в которых уже не было однозначного соответствия между операторами и машинными командами. В них компилятор транслирует каждый оператор исходной программы в последовательность двоичных команд. В дальнейшем линия Алгола продолжилась в целом ряде языков программирования: PL/1, Паскаль, Си, С++ и Java. Постепенно они почти полностью вытеснили ассемблер при разработке больших приложений.

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

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

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

· для управляющих структур можно использовать простые ключевые слова, такие как while и if - компилятор сам генерирует все необходимые для их реализации машинные команды.

Пример, рассмотренный выше, приобретает вид:

Res=2+3; C

Res:=2+3; Pascal

Исходная программа, написанная на каком-либо языке программирования высокого уровня, должна быть преобразована в машинный код – поскольку это это единственный язык, который понимается ПЭВМ напрямую. Для этого программа, точнее ее текст, называемый исходным кодом, подается на вход другой программы - транслятора, который осуществляет перевод текста с одного языка на другой - машинный язык, который без дальнейших преобразований может быть исполнен на данной платформе.

Понятие компьютерной платформы (или просто платформы) описывает компьютерную технику, создаваемую на базе определенной архитектуры и определенного типа процессора. Также иногда оно описывает операционную систему и тип виртуальной машины, с помощью которых исполняется ПО.

 

Трансляторы бывают двух видов: компиляторы и интерпретаторы.

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

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

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

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

 

Трансляция программы в исполняемый модуль происходит в несколько этапов. Весь процесс можно разбить на две основных части – собственно компиляция (compiling) и компоновка (linking).

Компиляция программы проходит в несколько этапов. На первом исходный текст (он обычно хранится в виде текстового файла) подвергается лексической обработке. Программа разделяется на предложения, предложение делится на элементарные составляющие (лексемы). Каждая лексема распознаётся (имя, ключевое слово, литерал, символ операции или разделитель) и преобразуется в соответствующее двоичное представление. Этот этап работы транслятора называют лексическим анализом.

Затем наступает этап синтаксического анализа. На этом этапе из лексем собираются выражения, а из выражений - операторы.

После синтаксического анализа наступает этап генерации кода. На этом этапе происходит замена операторов языка высокого уровня последовательностями машинных команд. Результат преобразования записывается в виде двоичного файла (его называют объектным модулем) с расширением ".obj".

 

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

· Распределение памяти для размещения модулей, расстановка адресов точек вызова функций.

· Согласование адресов памяти переменных и объектов, совместно используемых модулями.

· Добавление стандартных объектных модулей – библиотек функций, а также кода, обеспечивающего корректное начало и завершение программы.

 

Преобразованная компоновщиком программа называется загрузочным или исполняемым модулем. Файлы, содержащие загрузочные модули, называют загрузочными или исполняемыми файлами.