<<
>>

Цикл FOR

Цикл FOR очень удобен, но он тяжел для трансляции. Не столько потому, что сама конструкция трудна... в конце концов это всего лишь цикл... но просто потому, что она трудна для реализации на ассемблере.

Как только код придуман, трансляция достаточно проста.

Фаны Си любят цикл FOR этого языка (фактически он проще для кодирования), но вместо него я выбрал синтаксис очень похожий на синтаксис из старого доброго Бейсика:

FOR = TO ENDFOR

Сложность трансляции цикла «FOR» зависит от выбранного вами способа его реализации, от пути, которым вы решили определять правила обработки ограничений. Рассчитывается ли expr2 каждый раз при прохождении цикла, например, или оно обрабатывается как постоянное ограничение? Всегда ли вы проходите цикл хотя бы раз, как в Fortran, или нет. Все становится проще, если вы приверженец точки зрения что эта конструкция эквивалентна:

=

TEMP =

WHILE (SP)

BRA L1 ; цикл для следующего прохода

L2: ADDQ #2,SP ; очистить стек

Ничего себе! Это же куча кода...

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

Однако, подпрограмма анализа довольно проста теперь, когда у нас есть код:

{–}

{ Parse and Translate a FOR Statement }

procedure DoFor;

var L1, L2: string;

Name: char;

begin

Match('f');

L1 := NewLabel;

L2 := NewLabel;

Name := GetName;

Match('=');

Expression;

EmitLn('SUBQ #1,D0');

EmitLn('LEA ' + Name + '(PC),A0');

EmitLn('MOVE D0,(A0)');

Expression;

EmitLn('MOVE D0,-(SP)');

PostLabel(L1);

EmitLn('LEA ' + Name + '(PC),A0');

EmitLn('MOVE (A0),D0');

EmitLn('ADDQ #1,D0');

EmitLn('MOVE D0,(A0)');

EmitLn('CMP (SP),D0');

EmitLn('BGT ' + L2);

Block;

Match('e');

EmitLn('BRA ' + L1);

PostLabel(L2);

EmitLn('ADDQ #2,SP');

end;

{–}

Так как в этой версии синтаксического анализатора у нас нет выражений, я использовал тот же самый прием что и для Condition и написал подпрограмму:

{–}

{ Parse and Translate an Expression }

{ This version is a dummy }

Procedure Expression;

begin

EmitLn('');

end;

{–}

Испытайте его. Снова, не забудьте добавить вызов в Block. Так как у нас нет возможности ввода для фиктивной версии Expression, типичная входная строка будет выглядеть так:

afi=bece

Хорошо, генерируется много кода, не так ли? Но, по крайней мере, это правильный код.

<< | >>
Источник: Креншоу Джек. Давайте создадим компилятор!. 1999

Еще по теме Цикл FOR:

  1. Когда нарушается цикл
  2. ЦИКЛ
  3. Цикл вины
  4. Цикл 2х7
  5. Эволюционный цикл
  6. Универсальный цикл
  7. Глава 5 СЕМЕЙНОЕ ВДИНСТВО И ЖИЗНЕННЫЙ ЦИКЛ СЕМЬИ
  8. Тема 6. Модели жизненного цикла
  9. Задачи и упражнения
  10. Главный режиссер на телевидении
  11. МЕТОД МАНИПУЛЯЦИИ В СПОРЕ
  12. Аспекты транзитного Меркурия с натальным Солнцем
  13. 77
  14. 77
  15. Марс
  16. ИССЛЕДОВАНИЕ ПАТОГРАФИЧЕСКОЕ
  17. Тема 5. Основные понятия теории социальных изменений
  18. ЛУННЫЕ ЦИКЛЫ
  19. Статья 892. Договор на выполнение научно-исследовательских или опытно-конструкторских и технологических работ