Редактор – это инструментальное средство для создания и
изменения исходных символьных файлов,
написанных на языке программирования.
Компилятор – транслирует символы из исходного файла в
объектный модуль, который содержит команды в
машинном коде для конкретного компьютера.
Библиотекарь – поддерживает совокупности объектных
файлов, называемые библиотеками.
Компоновщик, или редактор связи – собирает объектные
файлы программы и разрешает внешние ссылки
между компонентами программы, формируя
исполняемый файл.
Загрузчик – копирует исполняемый файл с диска в память и
инициализирует компьютер перед выполнением
программы.
Отладчик – инструментальное средство, которое
представляет возможность программисту
управлять выполнением программы по
диагностике ошибок.
Профилировщик – измеряет время, затрачиваемое на каждый
компонент программы.
Средства тестирования автоматизируют процесс
тестирования программ и анализируют результаты
тестирования.
Средства конфигурирования автоматизируют создание
программ и отслеживают изменения в них до
уровня исходных файлов.
Интерпретатор непосредственно выполняет исходный код
программы, без создания объектного файла.
2.2 Транслятор
Процесс преобразования исходного модуля в загрузочный и выполнение его на ЭВМ можно представить в виде схемы:
ИМ (исходный модуль) – исходный текст программы, написанный на конкретном языке программирования (ЯП).
Транслятор – программа, предназначенная для перевода исходного модуля (ИМ) в загрузочный (ЗМ).
ОМ (объектный модуль) – программа в машинных кодах, подготовленная для обработки блоком 4.
Компоновщик (редактор связи) – специальная программа, устанавливающая все внешние ссылки на другие модули и создающая ЗМ. Если ОМ содержит неразрешимые ссылки, то процесс образования ЗМ прекращается.
ЗМ (загрузочный модуль) – программа в машинных кодах, определяющая последовательность выполнения команд на ЭВМ, готовая к выполнению.
Загрузчик устанавливает абсолютные адреса в оперативной памяти (ОП) ЭВМ.
Загрузочный модуль (ЗМ) будет выполняться только после прохождения программ пользователя всех шести этапов (блоков) процесса трансляцию
Трансляторы бывают двух типов: компиляторы (англ.:compiler) и интеграторы.
2.3. Компиляторы
Структура компилятора показана на рис.
Во входной части компилятора анализируется синтаксис и семантика программы согласно правилам языка. Синтаксический анализатор преобразует последовательности символов в абстрактные синтаксические объекты, называемые лексемами. Например, символ '' = '' в языке С преобразуется в оператор присваивания. Если за ним следует еще символ '' = '', т.е. '' = = '', то оба символа '' = = '' преобразуются в операцию проверки равенства. Анализатор семантики придает смысл этим абстрактным объектам. Например, в фрагменте программы семантический анализатор выделит глобальный адрес для первого i и вычислит смещение для второго i:
static int i
void proc ( int i ) {…}
Завершается работа входной части компилятора формированием промежуточного представления программы. По нему можно восстановить исходный текст программы, за исключением имен идентификаторов и физического формата строк: пробелов, комментариев и т. д.
Входная часть компилятора принимает промежуточное представление программы и генерирует машинный код для конкретного компьютера. Таким образом, входная часть является языковозависимой, а выходная – машинозависимой.
Для улучшения эффективности кода выходная часть компилятора содержит два оптимизатора. Первый предназначен для оптимизации промежуточного представления программы до формирования, второй при генерации объектного кода. Рассмотрим три способа оптимизации:
1.Машинозависимую оптимизацию промежуточного представления продемонстрируем на примере оптимизации выражения:
a= b (x+y)+c (x+y)
Сумма (x+y) вычисляется один раз и сохраняется во временной переменной или регистре. Подобная оптимизация не зависит от конкретного компьютера и может быть выполнена до генерации кода.
2.Машинно-ориентированная компиляция основана на специфике архитектуры компьютера. Например, для хранения промежуточных результатов в регистрах, а не в памяти, следует знать их число и тип, которые различны в различных компьютерах, точнее, процессорах.
3.Локальная оптимизация обычно выполняется как до, так и при генерации объектного кода. Ее основная функция – это замена коротких последовательностей команд на одну. Например в С выражение n++ может быть скомпилировано в последовательность команд:
load R1,n - Загрузить содержимое n в R1
add R1,# 1 - Прибавить к содержимому R1, 1 (ед.)
store R1,n - Сохранить содержимое R1 в n
Локальный оптимизатор мог бы заменить эти три команды одной: inter n.
Использование оптимизатора требует осторожности.
Ошибку оптимизатора трудно обнаружить, потому что отладчик создан для работы с исходным текстом, а не с оптимизированным объектным кодом, в котором изменен порядок выполнения команд. Для избежания ошибки необходимо проводить тестирование программы до и после работы оптимизатора. Например, в фрагменте программы для устройства ввода-вывода с регистрами, отображенными на память,
transmit_ register = 0x70
/* Ждать 1 секунду */
transmit_ register = 0x70
оптимизатор может удалить второе присваивание, предположив, что оно лишнее.
Так как конечным результатом работы компилятора является объектный модуль, то целесообразно, чтобы он был составлен в кодах конкретной машины. Однако такой подход имеет существенный недостаток – объектный модуль становится машинно-зависимым, и для каждого типа ЭВМ требуется свой компилятор. Чтобы не выполнять большую рутинную работу по преобразованию старого компилятора, было принято решение о разделении процесса компиляции на две части: команды для абстрактной (виртуальной) и конкретной ЭВМ. В этом случае схема компиляции выглядит так:
Рис. Схема двухуровневой компиляции
На первом уровне (блок 2) ИМ обрабатывается компилятором, транслирующим исходный текст на ЯВУ в объектный модуль в кодах некоторой виртуальной (абстрактной ) ЗВМ, учитывающей архитектуру конкретных классов процессоров (блок 3 ).
На втором этапе (блок 4 ) производится перевод ОМ в командах абстрактной ЭВМ (блок 3) в ОМ для конкретной ЭВМ (блок 5). Команды абстрактной машины (блок 3) машино - независимые и могут быть использованы на ЭВМ различных типов. Как правило, выходной ОМ (блок 5) формируется простым компилятором на языке ассемблера (англ. assembler – собирать) конкретной ЭВМ.
2.4. Библиотекарь
Библиотека – это структурированная совокупность типов и подпрограмм, не содержащая новых языковых конструкций.
Многие конструкции языка программирования реализуются не с помощью откомпилированного кода, выполняемого внутри программы, а через обращения к процедурам, которые хранятся в библиотеке, предусмотренной поставщиком компилятора. Из-за увеличения объема языков программирования библиотеки становятся их неотъемлемой частью.
Пр. Использование библиотеки ввода-вывода, которая в С++
находится в файле iostream.h или iostream.
# include < iostream.h>
include – директива препроцессора, которая выполняется в
первую очередь.
2.5. Компоновщик
При написании больших программных систем в несколько тысяч строк используется модульный подход. Вся программа разбивается на модули, связь между которыми осуществляется через обращения к заранее оговоренным процедурам. Если обращение делается к процедуре, находящейся вне текущего модуля, то компилятор вместо адреса этой процедуры записывает внешнюю ссылку. Когда все модули откомпилированы, компоновщик разрешает эти ссылки, разыскивая описания процедур и нелокальных переменных.
В современной практике модульное программирование используется для декомпиляции программы. Применение такого подхода имеет как и медаль две стороны. Положительный эффект (лицевая сторона) – быстрая и короткая компиляция. Обратная сторона медали – связь компоновщиком сотни модулей с тысячами ссылок. В этом случае даже незначительное изменение одного исходного модуля потребует продолжительной компоновки.
2.6. Загрузчик
Загрузчик загружает программу в память и инициализирует ее выполнение. На старых ПК загрузчик помимо этих функций занимался еще и перемещением программ. Такая команда, как load 140, содержала абсолютный адрес памяти, который приходилось настраивать на конкретные адреса загружаемой программы.
В современных ПК адреса команд и данных задаются относительно значений в регистрах. Для каждой области памяти программы или данных выделяется регистр, указывающий на начало этой области. Загрузчик копирует программу в память и инициализирует несколько регистров. Теперь команда load 140 означает “загрузить значение, находящееся по адресу, полученному сложение регистра и 140”.
2.7. Отладчик
Отладчик – предназначен для поиска ошибок в программе с помощью трех функций:
- Трассировка – пошаговое выполнение программы. Позволяет отслеживать команды в порядке их выполнения.
- Контрольная точка – средство, предназначенное для выполнения программы до конкретной строки. Разновидность контрольной точки – точка наблюдения вызывает выполнение программы, пока не произойдет обращение к определенной ячейке памяти.
- Проверка / изменение данных – возможность посмотреть и изменить значение любой переменной в любой точке вычисления.
Символьные отладчики работают с символами исходного кода (именами переменных и процедур), а не с абсолютными машинными адресами. Символьный отладчик взаимодействует с компилятором и компоновщиком для создания таблиц, связывающих символы и их адреса.
Некоторые проблемы трудно решить даже с помощью отладчика. Порой, помощь со стороны другого программиста может оказаться эффективней нескольких дней работы отладчика.
2.8. Профилировщик
Профилировщик периодически опрашивает указатель выполняемой команды компьютера и затем строит в процентах гистограмму времени выполнения каждой процедуры или команды.
Использовать профилировщик рекомендуется в (следующих ) ситуациях:
1. Существующая эффективность программы неприемлема.
2. Необходимо установить оптимальный вариант выполнения программы.
3. поиск время емких алгоритмов программы.
4. Анализ эффективности выполнения программы.
2.9. Средства тестирования
Средства тестирования выполняют функции:
1. Фиксируют ввод с внешнего источника (вроде нажатия пользователем клавиши на клавиатуре) во фрагменте программы.
2. Сравнивают выводимые результаты со спецификацией.
3. Выводят анализ сравнения.
2.10. Средства конфигурирования
Инструментальное средство конфигурирования относится к программному обеспечению и используется для автоматизации задач управления. В его состав входят такие инструменты, как сборка, управление исходными текстами и изменениями.
Сборка – создает исполняемый файл из исходных текстов, вызывая компилятор, компоновщик и т.д.; гарантирует, что новый исполняемый файл создан корректно с минимальным количеством перекомпиляций. Инструментальное средство управления исходными текстами отслеживает и регистрирует все изменения в модулях исходного текста.
Средство управления изменениями сохраняют первоначальные версии модулей до изменения и позволяют на их основе легко восстановить любую предыдущую версию.
2.11. Интерпретаторы
Интерпретатор – это программа, которая непосредственно выполняет код исходной программы.
Его преимущество перед компилятором состоит в том, что не нужно последовательно вызывать компилятор, компоновщик, загрузчик и т. д.
Интерпретаторы традиционно не пытаются что – либо оптимизировать.
Как правило, интерпретатор переводит исходный код программы в код некой абстрактной машины (см. рис.).
Рис. Структура интерпретатора
Если предположить, что машинный код компьютера совпадает с выработанным интерпретатором абстрактным кодом, то интерпретатор превратится в компилятор. Поэтому в действительности провести различие между интерпретатором и компилятором очень трудно установить.
История создания интерпретатора связана с разработкой Pascal – компилятора для получения машинного кода ЭВМ CDC 6400. Никлаус Вирт создал компилятор, который вырабатывал код, названный Р – кодом, для абстрактной стековой машины. Написав программы по преобразованию исходного модуля в Р – коды в машинные коды конкретной машины, им были получены соответственно интерпретатор и компилятор для языка Pascal.
Условная схема процесса выполнения программы в среде интерпретатора
Считается, что интерпретаторы легко писать, так как они не машинно-ориентированные.
3. Элементы лингвистического обеспечения.
Основными элементами лингвистического обеспечения, необходимого для построения языков программирования, являются синтаксис, семантика, данные, операторы присваивания, контроль соответствия типов, управляющие операторы, подпрограммы и модули. Лингвистика – наука о языке (Ожегов).
3.1. Синтаксис
Лексика – словарный состав (набор) языка, который используется при информационном общении.
Синтаксис языка – это набор или свод правил, которые определяют, какие последовательности символов считаются допустимыми выражениями в языке. Применительно к языку программирования – это свод законов о построении предложений из данного набора слов.
Синтаксис задается с помощью формальной нотации. Самая распространенная формальная нотация – это расширенная форма Бекуса-Наура (РФБН). Синтаксис в РФБН начинается с верхнего уровня и, после применения декомпозиции объекта, достигает уровня отдельного символа. Например, в языке С синтаксис условного оператора if задается правилом:
if (выражение) оператор [else оператор];
Имена “выражение и оператор ” представляют синтаксические категории. Символы : if, else : , -фактические символы, которые должны появиться при использовании оператора if. else – оператор, указанный в квадратных скобках [ ], не является обязательным.
Правила синтаксиса легче изучить на диаграмме:
оператор
Рис. Синтаксическая диаграмма
В кругах находятся фактические символы, а в прямоугольниках – синтаксические категории, которые имеют собственные диаграммы. Последовательность символов, получаемых при последовательном прохождении пути на диаграммах, является программой.
3.2. Семантика
Семантика – это смысл высказывания, а также смысл, значение языковой единицы или слова.
В любой точке выполнения программы можно описать ее состояние, определяемое: 1) указателем на следующую выполняемую команду и 2) содержимым памяти программы. Семантика программы задается описанием изменения состояния, вызванного выполнением команды. Например, выполнение:
a :=18
заменит предыдущее состояние а на новое 18, т.е. ячейка памяти а будет содержать теперь 18.
Рассмотрим семантику управляющего оператора if. Предположим, что известны смыслы двух операторов S1 и S1 в состоянии S. Обозначим это через формулы p (S 1, S) и p (S2, S). Тогда смысл if - оператора :
Дата добавления: 2016-08-08; просмотров: 1730;