И.Г. Головин, И.А. Волкова - Языки и методы программирования (1160773), страница 8
Текст из файла (страница 8)
Следовательно, выгоднее иметьуниверсальную машинную архитектуру и реализовывать трансляторыс новых языков в этой архитектуре.Еще раз отметим, что прикладным программистам-пользователяммашинной архитектуры в принципе безразлично, как именно (чистопрограммно, аппаратно, программно-аппаратно) реализована этаархитектура. Таким образом, мы приходим к концепции виртуальноймашины языка программирования. Машинным языком такой виртуальной архитектуры является собственно язык программирования,а способ реализации (программно-аппаратная интерпретация, чистопрограммный интерпретатор, компилятор) не имеет значения.Понятие виртуальной машины полезно, потому что позволяет почти полностью абстрагироваться, от особенностей машинного языкаи конкретной архитектуры компьютера, разновидности процессораи других технических характеристик вычислительной системы.Однако интересен следующий вопрос: от чего нельзя абстрагироваться при программировании на некотором языке (или, что тоже самое, при программировании на виртуальной машине языка)?Иными словами, что нужно знать при программировании на языке,кроме самого языка программирования? Ответ на этот вопрос такой:необходимо знать способы взаимодействия виртуальной машиныязыка с операционной системой.
Операционной системой (ОС)компьютера называется комплекс программ, управляющих ресурсамикомпьютера. Заметим, что компьютер под управлением операционной системы тоже можно рассматривать как виртуальный. Подобнотому, как виртуальная машина языка позволяет абстрагироватьсяот машинной архитектуры, виртуальный компьютер ОС позволяетабстрагироваться, например от деталей взаимодействия с внешнимиустройствами ввода-вывода.
Виртуальный компьютер ОС предоставляет возможность управления внешними устройствами, файлами дан35ных, процессами и много других. Подробнее устройство и функцииоперационных систем рассматриваются, например в [30].Форма представления интерфейса с виртуальной машиной ОСзависит, прежде всего, от языка программирования. Например,в языках С и C++ — это библиотеки системных вызовов и структур,в языке C# — библиотеки классов, объединенных в сборки, а в языке Java — библиотеки классов, объединенных в пакеты, и т.д. В данном учебнике мы не будем заниматься интерфейсами с ОС.В некоторых случаях понятие виртуальной машины языка (и еереализации) тесно связано с понятием промежуточного языка.Дело в том, что конструкции языков программирования плохоподходят для непосредственной интерпретации. Они имеют сложную структуру, представляются в виде последовательности символови ориентированы не на машинную реализацию, а на восприятиечеловеком-программистом (что неудивительно).
Поэтому «чистых»интерпретаторов языков программирования крайне мало. Почти всереальные интерпретаторы используют промежуточный язык (ПЯ),который обладает следующими двумя свойствами:• легкость интерпретации (по сравнению с исходным языком L);• легкость перевода программ с языка L в ПЯ (по сравнению с переводом в машинный код).В этом случае процесс трансляции и выполнения программывключает в себя два этапа: перевод программы с языка L в ПЯ и непосредственная интерпретация текста на ПЯ. Интерпретатор ПЯназывают в этом случае исполнительной системой (или системойвремени выполнения).
Выгода этой схемы состоит в том, что в силусвойств ПЯ обе компоненты (транслятор в ПЯ и интерпретатор ПЯ)достаточно просты и компактны. Кроме того, схема обеспечиваетдополнительные преимущества.Рассмотрим задачу реализации языка L для N различных машинных архитектур. При этом требуется, чтобы все реализации работалиодинаково (т.е. оттранслированные программы должны обеспечивать получение одних и тех же результатов на всех архитектурах).В обычном случае требуется разработать N различных и достаточно сложных программ-трансляторов (неважно компиляторов илиинтерпретаторов). Если же использовать единый промежуточныйязык, то требуется одна программа-транслятор с языка L в ПЯ и Nинтерпретаторов ПЯ для каждой архитектуры (как вы думаете, накаком языке лучше всего написать программу-транслятор?).
Каждаяиз этих программ существенно проще, чем интерпретатор или компилятор с языка L, поэтому суммарные усилия по реализации всехтрансляторов меньше. Кроме того, добавление реализации для новойархитектуры также существенно проще, потому что интерпретаторПЯ существенно проще компилятора или интерпретатора L. Подробнее ПЯ и его интерпретации рассматриваются в ч. III данногоучебника.36Одна из первых реализаций этой схемы — система UCSD-Pascal,использовавшаяся для организации выполнения студенческого практикума на множестве компьютеров разных архитектур. Входной языкэтой системы Паскаль, а промежуточный язык — P-code.Такой же подход использовался при реализации первого чистого объектно-ориентированного языка SmallTalk. Авторы SmallTalkпредложили свой вариант ПЯ — байт-код.
Такое название выбрано,потому что каждая команда байт-кода имеет простую структуру —код операции размером один байт и далее операнд (операнды) переменной длины. Программы на SmallTalk транслируются в байт-код,который далее интерпретируется.Еще одним важным примером использования ПЯ является языкJava. Вместе с Java была разработана спецификация виртуальной Javaмашины (Java Virtual Machine — JVM). Машинным языком JVM является байт-код JVM. Байт-код не зависит от конкретной машиннойархитектуры и достаточно легко интерпретируется.
СпецификацияJVM содержит описание байт-кода и описание среды времени выполнения (Java run-time environment — Java RTE). Функции Java RTEпохожи на функции ОС, но не зависят ни от одной ОС. Разработчикязыка (компания Sun Microsystems) представила компилятор javac,транслирующий программы с языка Java в байт-код JVM. Таким образом, JVM в терминах виртуальных архитектур — это прослойка междувиртуальной машиной языка Java и виртуальным компьютером ОС.Наличие JVM позволяет абстрагироваться не только от конкретнойархитектуры, но и от операционной системы, поэтому программы наJava могут выполняться везде, где есть реализация JVM.
РеализацияJVM подразумевает реализацию интерпретатора байт-кода и реализацию Java RTE. В настоящее время реализации JVM существуютпрактически для всех операционных систем.Некоторым недостатком систем с ПЯ является невысокая скорость интерпретации ПЯ. Одно из очевидных средств увеличенияРис.
4.1. Иерархия виртуальных компьютеров для Java-приложения37их быстродействия — аппаратная реализация ПЯ. Например, былиразработаны микропроцессоры, непосредственно интерпретирующиебайт-код SmallTalk (микропроцессор Катана [32]), а также архитектура процессоров picoJava для интерпретации байт-кода JVM [29].Итак, при создании приложений программист использует виртуальную машину языка программирования, которая представляетсяна самом деле иерархией виртуальных компьютеров. Рассмотрим этуиерархию на примере приложения, написанного на Java (рис. 4.1).В основе иерархии лежит реальное физическое устройство — компьютер. Машинный язык этого компьютера — микрокод. Следующий уровень иерархии — программно-аппаратный виртуальныйкомпьютер (ПАВК), машинный язык которого интерпретируетсямикропрограммно.
Далее находится слой виртуального компьютераОС, реализуемый программами на языке ПАВК. Следующий слой —виртуальная машина байт-кода (реализация JVM), машинным языкомкоторой служит байт-код JVM. Вершиной иерархии является виртуальная машина языка Java (машинный код — язык Java).ЧАСТЬIIВВЕДЕНИЕ В СОВРЕМЕННЫЕ ЯЗЫКИПРОГРАММИРОВАНИЯГлава 5БАЗИС СОВРЕМЕННЫХ ЯЗЫКОВПРОГРАММИРОВАНИЯ5.1. Простые типы данных, операциинад нимиВ соответствии со схемой, приведенной в подразд. 1.3, рассмотрим основные конструкции языков программирования, начинаясо скалярного базиса.Все значения простых типов данных (называемых иногда элементарными, или примитивными) являются атомарными, т.е. они неимеют внутренней структуры.Классификация простых типов данных приведена на рис. 5.1.В данном подразделе рассмотрим все простые типы данных, кромеподпрограммного, который имеет смысл обсуждать вместе с понятием подпрограммы (см.
гл. 6).Арифметические типы данныхВ компьютерах эти типы данных представляют числа, и поэтомудействительно являются основными.Как уже отмечалось, в некоторых языках (JavaScript) существуетединственный числовой тип (Number), представляющий все допустимые числа. С точки зрения упрощения программ это, конечно,удобно, однако в большинстве индустриальных языков программирования арифметические типы данных разделяются на два вида: целые(для представления целочисленных значений) и вещественные (дляпредставления чисел с дробной частью). Основная причина такогоразделения состоит в том, что представление целых и вещественныхчисел в современных компьютерах различное, а также различаетсяи набор операций. Например, операции сложения целых и вещественных чисел представляются разными машинными командами.39ЦелыеЗнаковыеБеззнаковыеАрифметические ^ПлавающиеВещественные Г ^ФиксированныеСимвольныеЛогическиеСсылочные и указательныеПодпрограммныеРис.
5.1. Классификация простых типов данныхСама номенклатура машинных операций над целыми и вещественными числами различается (например, для вещественных чиселотсутствуют побитовые операции). Реализация операций над вещественными числами сложнее с аппаратной точки зрения, поэтомув ряде архитектур вещественные числа вообще могут отсутствовать.Для того чтобы программист мог учитывать эти нюансы, многиеязыки (в том числе Паскаль, C++, Java, С#) разделяют числовыетипы на два вида.Целые типы данныхД л я целых типов данных необходимо рассмотреть следующиеосновные вопросы:• универсальность (насколько полно учтены машинные типы);• наличие (или отсутствие) беззнаковых типов;• представление (размер значения, диапазоны значений);• надежность (какие ошибки могут возникать при выполненииопераций с целыми значениями);• набор операций.Универсальность.