История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...
Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...
Топ:
Устройство и оснащение процедурного кабинета: Решающая роль в обеспечении правильного лечения пациентов отводится процедурной медсестре...
Оценка эффективности инструментов коммуникационной политики: Внешние коммуникации - обмен информацией между организацией и её внешней средой...
Установка замедленного коксования: Чем выше температура и ниже давление, тем место разрыва углеродной цепи всё больше смещается к её концу и значительно возрастает...
Интересное:
Влияние предпринимательской среды на эффективное функционирование предприятия: Предпринимательская среда – это совокупность внешних и внутренних факторов, оказывающих влияние на функционирование фирмы...
Искусственное повышение поверхности территории: Варианты искусственного повышения поверхности территории необходимо выбирать на основе анализа следующих характеристик защищаемой территории...
Уполаживание и террасирование склонов: Если глубина оврага более 5 м необходимо устройство берм. Варианты использования оврагов для градостроительных целей...
Дисциплины:
2020-12-27 | 51 |
5.00
из
|
Заказать работу |
Конструкция A[<выр>,..,<выр>] записывается в виде
<выр>.. <выр> A $SUBS
Оператор $SUBS, используя элемент A таблицы символов и индексные выражения, вычисляет адрес элемента массива. Затем операнды исключаются из стека и на их место заносится новый операнд, специфицирующий тип элемента массива и его адрес.
Методика обращения к элементу массива представляется очень важной для понимания того, как происходит вызов функций и процедур. Дело в том, что при обращении к функции нам также необходимо извлекать откуда-то необходимое количество аргументов. А количество их мы можем определить по содержимому таблицы имен. Поэтому вызов функции вида f(x1,x2) в польской форме записи будет выглядеть как
x1 x2 f $CALL,
где x1 и x1 – аргументы, f - имя функции, $CALL – команда передачи управления по адресу, определяемому именем функции. При этом предполагается, что мы заранее занесли в таблицу имен информацию о том, сколько и каких аргументов у функции f, а также ее адрес – индекс начала кода подпрограммы в массиве польской формы.
Не случайно поэтому, что в подавляющем количестве языков программирования имена функций ассоциируются с их адресами.
Циклы
Реализация циклов также не вызывает сложностей. Во-первых, имея оператор безусловного перехода и условный оператор, можно всегда сконструировать цикл "вручную". Например, цикл вида
FOR I=N1 TO N2 DO Operator
может быть сконструирован на исходном языке:
I:= N1;
L1: IF I>N2 THEN GOTO L2;
Operator;
I:=I+1;
GOTO L1;
L2:
Тем не менее, если необходимо реализовать этот цикл как оператор языка, то в польской форме записи он будет выглядеть так:
Рассмотрим фрагмент программы:
BEGIN
INTEGER K;
ARRAY A[1..I-J];
K:= 0;
L: IF I>J THEN
K:= K+A[I-J]*6
ELSE
BEGIN
I:= I+1;
I:= I+1;
GOTO L;
END
END.
Добавим еще два оператора без операндов - $BLOCK ("начало блока") и $BLOCKEND ("конец блока"). Эти операторы иногда очень важны – в некоторых языках программирования с их помощью можно вводить локальные, "внутриблоковые" переменные, вызывать автоматически деструкторы и т.п. Кроме того, нам понадобится оператор присваивания ":=", который ничего не заносит обратно в стек. Польская форма нашего фрагмента будет выглядеть так:
В заключение хотелось бы добавить одно замечание. Хранение оператора, ключевого слова и т.п. в массиве польской формы трудностей не вызывает – мы содержим там лишь числовой код (например, в виде отрицательного числа). Операнды тоже представлены числами – индексами таблицы имен, где хранятся и переменные, и константы.
Сложнее обстоит дело со стеком аргументов, необходимым для вычисления польской формы, и в котором хранятся значения рабочих, промежуточных переменных. Это могут быть и целые, и действительные числа, строки, символы, адреса и т.п. Следовательно, необходимо предусмотреть хранение, помимо собственно значения, и тип аргумента, и размер и, возможно, многое другое. На это следует обращать особое внимание при разработке компиляторов.
Одним из возможных вариантов организации рабочего стека является использование т.н. тегового стека. В теговом стеке каждый хранимый элемент предваряется неким описателем его типа, называемым тегом. Тег может содержать самую разнообразную информацию, описывающую данные – тип, размер, права доступа и т.д.
Для простейшего интерпретатора можно различать такие типы данных, как числовые, строковые и адресные. В качестве адреса в простейшем случае может использоваться целое число – номер записи в таблице имен.
ТЕТРАДЫ
Добавление тетрад с другими операторами также не вызывает трудностей и происходит аналогично. Тот же фрагмент программы, представленный в форме тетрад, выглядит так:
$BLOCK (10) + K, T4, T5
- I, J, T1 (11):= T5,, K
$BOUNDS 1, T1 (12) $BR 18
$ADEC A (13) + I, 1, T6
:= 0,, K (14):= T6,, I
- I, J, T2 (15) + I, 1, T7
$BMZ 13, T2 (16):= T7,, I
- I, J, T3 (17) $BRL L
* A[T3], 6, T4 (18) $BLOCKEND
Здесь используются следующие операторы:
Оператор | Операнды | Описание |
$BR | i | переход на i-ю тетраду |
$BZ (BP,BM) | i, P | переход на i-ю тетраду, если P=0 (P>0,P<0) |
$BG (BL,BE) | i, P1, P2 | переход на i-ю тетраду, если P1>P2 (P1<P2,P1=P2) |
$BRL | P | переход на тетраду, номер которой задан в P-м элементе таблицы символов |
$BOUNDS | P1, P2 | P1 и P2 описывают граничную пару массива |
$ADEC | P | Массив описан в P. Если размерность массива равна n, то этой тетраде должны предшествовать n операторов $BOUNDS, задающих n граничных пар |
С тетрадой номер 9 могут возникнуть определенные проблемы. Трудности связаны с использованием аргумента в виде переменной с индексом. Решение может заключаться в использовании той же методики, что и в случае описания массивов.
Введем пару операторов типа
$AINDX I
$AGET A, R
$AINDX заносит аргумент I (индекс массива) в специальный стек – стек индексов. Это необходимо для того, чтобы команда $AGET смогла вычислить адрес элемента массива A, используя содержимое стека индексов, и занести значение этого элемента в R. В этот же момент может происходить и очистка стека (по мере извлечения необходимого количества аргументов)
Например, выражение "A[1,2]+B[J]" будет представлено в виде
$AINDX 1
$AINDX 2
$AGET A, T1
$AINDX J
$AGET B, T2
+ T1, T2, T3
По такому же принципу может быть организован и вызов подпрограмм. Кстати, здесь особенно явно проявляется роль стека при обращении к подпрограммам. Иллюстрацией этому могут служить наверняка знакомые большинству программистов неприятности со стеком, когда неверно указывается количество или тип аргументов при вызове подпрограмм (особенно в языке С).
ОПТИМИЗАЦИЯ ПРОГРАММ
Оптимизация программ – это очень объемная тема, на которую написаны (и пишутся до сих пор) многочисленные труды. Здесь мы лишь вкратце затронем этот вопрос.
Различают два основных вида оптимизации – машинно-зависимую (МЗО) и машинно-независимую (МНЗО):
МЗО связана с типом генерируемых команд и включается в фазу генерации кода (т.е. оптимизации подлежат машинные коды). МЗО напрямую зависит от архитектуры вычислительной машины и потому рассматриваться нами не будет.
В отличие от МЗО, МНЗО - отдельная фаза компилятора, предшествующая генерации кода. Она включается на этапе генерации промежуточного кода - внутренней формы представления программы.
Оптимизации подлежат:
время выполнения;
емкостные ресурсы (память).
Существуют 4 основных типа машинно-независимой оптимизации МНЗО.
I. Исключение общих подвыражений (оптимизация линейных участков)
Оптимизация линейных участков - это процедура, позволяющая не рассчитывать одно и то же выражение несколько раз, исключая общие подвыражения. Эта процедура разделяется на следующие шаги:
(11) представить выражение в форме, пригодной для обнаружения общих подвыражений;
(12) определить эквивалентность двух и более подвыражений;
(13) исключить повторяющиеся;
(1) изменить команды так, чтобы учесть это исключение.
Например, пусть выражение A = c*d*(d*c+b) записано в виде тетрад:
1) * c d T1
2) * d c T2
3) + T2 b T3
4) * T1 T3 T4
5) = A T4
Упорядочим операнды в алфавитном порядке (там, где это возможно):
1. * c d T1
2. * c d T2
3. + T2 b T3
4. * T1 T3 T4
5. = A T4
Далее определим границы операторов и найдем общие подвыражения (это (1) и (2)) и затем исключим подвыражение (2). После чего заменим далее везде T2 на T1:
* c d T1
+ T1 b T3
* T1 T3 T4
= A T4
Этот прием неудобен тем, что возможны варианты, когда либо не представляется возможным отыскать сразу общие выражения, либо в тех случаях, когда b, c, d – функции, имеющие побочный эффект; в этом случае мы можем поломать всю логику вычислений.
Кормораздатчик мобильный электрифицированный: схема и процесс работы устройства...
Археология об основании Рима: Новые раскопки проясняют и такой острый дискуссионный вопрос, как дата самого возникновения Рима...
Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...
Таксономические единицы (категории) растений: Каждая система классификации состоит из определённых соподчиненных друг другу...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!