На главную
Подписка
Новости










Главная / MS-DOS / MS-DOS. РУКОВОДСТВО РАЗРАБОТЧИКА / Глава 1 / Структурные операторы управления в языке Ассемблер Сделать домашней страницей Добавить в избранное Написать писмо

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Структурные операторы управления в языке Ассемблер

Теперь, когда мы имеем все необходимые средства для построения структурных операторов управления, разрешите приступить к этому. Наиболее часто употребимые операторы структурного управления представлены в Табл. 1-8.


Операторы Табл. 1-8 наиболее часто используются для реализации структурного управления в структурированных программах. В некоторых языках их больше; в других - меньше. Заметим только, что ФОРТРAH добился использования структуры IF-THEN-ELSE в ФОРТРАНЕ-77. Почти все ассемблеры не имеют таких структур для целей кодирования, хотя многие из них поддерживают IF-THEN-ELSE для условного ассемблирования. Причина проста: полагается, что ассемблеры находятся на более низком уровне чем языки высокого уровня. Так как мы решили, что эти структуры могут значительно упростить программирование, и мы можем реализовать их, используя средства, рассмотренные ранее.


Мы упустили из рассмотрения одну конструкцию. Это - оператор CASE (выбор). Конструкция, которую мы представим, заимствована из синтаксиса языка Паскаль, однако аналогичные конструкции имеются в Си и других языках программирования. Задача оператора CASE заключается в проверке на равенство значения ключевой переменной var элементу из списка. Если исходный оператор и варианты из списка не содержатся в одном и том же макро, невозможно определить, что является ключевой переменной. Вспомним, что MASM не разрешает использовать строки с (=) оператором назначения символа.


Создать оператор CASE можно, перечисляя для него все вероятные случаи и соответствующие им метки в качестве аргументов одного макро. Это псевдомакро рассматривается в следующем разделе данной главы.


Полный список описаний структурированных макросов управления приведен в Листинге 1-14. Обратите внимание на обильное использование комментариев макро (;;), экономящих память области макро. Эти макросы вырабатывают множество символов.Они могут использоваться в любом допустимом порядке с теоретическим ограничением уровней вложенности до 89. Однако MASM скорее выходит за пределы памяти, чем за предел вложенности. Никакая инициализация не требуется. Все символы самоинициализирующиеся.



                  Таблица 1-8. Операторы структурного управления

            --------------------------------------------------------
            Оператор                         Структура
            --------------------------------------------------------
            IF-THEN           IF<условие> (выполнить, если условие
                              истинно)
                              ENDIF
            IF-THEN-ELSE      IF<условие> (выполнить, если условие ис-
                              тинно)
                              ELSE (выполнить, если условие ложно)
                              ENDIF
            DO-WHILE          WHILE <условие> (выполнить, если усло-
                              вие истинно)
                              END_WHILE
            REPEAT-UNTIL      REPEAT (выполнить, если условие ложно)
                              UNTIL <условие>
            FOR-DO            FOR =  to  (выполнить
                              для каждого целого значения var между
                              begin и  end  включительно,  увеличивая
                              или уменьшая var при каждом прохождении
                              цикла)
                              END_FOR
            CASE_OF_     CASE  OF
                               (выполнить, если var = A)
                               (выполнить, если var = B)
                              .  .  .
                               (выполнить, если var = N)
                              <по умолчанию> (выполнить, если нет со-
                              ответствия)
                              END_CASE


                Листинг 1-14. Структурированные макросы управления
         -----------------------------------------------------------------

            PAGE    50,132   ;установить выдачу листинга на полный экран
            ;;********************************************************
            ;;                М А К Р О О П И С А Н И Я
            ;;********************************************************
            ;;
            FALSE   EQU     0          ;определить "FALSE"
            TRUE    EQU     0FFFFh     ;определить "TRUE"
            ;;
            ;;** @TestSym *************************SUPPORT MACRO******
            ;; Выявить, был ли определен уровень вложенности. Если нет,
            ;; то установить "?SYMDEF" для инициализации счетчика этого
            ;; уровня. Обычно все процессы первого прохода запускают
            ;; счетчик с 0. Значения всех символов в начале прохода 2
            ;; должны быть сброшены. Заметьте, что символы "?p2sw..."
            ;; остаются для "Phase 2 SWitch" (переключатели фазы 2).
            ;; Проверьте, что первым уровнем при реинициализации явля-
            ;; ется уровень 10. Замечание: значение 10 выбрано для пер-
            ;; воначального уровня с тем, чтобы зарезервировать для
            ;; уровня вложенности   две цифры.
            ;;
            @TestSym MACRO p1,p2
                    IF1       ;;если 1-ый проход,проверить что определено
                    IFNDEF    &p1&p2
            ?p2sw&p1&p2      = TRUE    ;;установить для 2-го прохода
                                       ;;переопределение переключателей,
            ?symdef          = FALSE   ;;вызывающее инициал-ию счетчика
                     ELSE
            ?symdef          = true    ;;разрешить приращение счетчика
                     ENDIF   ;;конец проверки описания символа
                     ENDIF   ;;конец проверки 1-го прохода
                     ;;
                     IF2     ;;если 2-ой проход, переинициал-ать
                     IF      (?p2sw&p1&p2) ;;если переинициал. нет, то
            ?p2sw&p1&p2      = FALSE   ;;очистить переключатель переопре-
                                       ;;деления 2-го прохода
                     IF      (?p2sw&р1&10) ;; и проверить инициал-ию
                                           ;;уровня 10
                     .ERR    ;; выйти с сообщением об ошибке
                     %OUT @TestSym mfcro: &p1 уровень вложенности не
                     %OUT                 закрыт на 2-ом проходе
                     ENDIF   ;;закон. уровень 10 по проверке инициал-ции
            ?symdef          = FALSE   ;;вызвать переинициал-ию счетчика
                     ELSE
            ?symdef          = TRUE    ;;разрешить приращение счетчика
                     ENDIF   ;;закончить проверку "если не переинициал."
                     ENDIF   ;;закончить проверку прохода 2
                     ENDM    ;;закончить макроописание
            ;;
            ;;**@ZeroSym**************************SUPPORT MACRO********
            ;; Инициализировать счетчик последовательности вложенностей
            ;; при первом использовании
            @ZeroSym         MACRO     p1,p2
            &p1&p2 =        0
                   ENDM
            ;;
            ;; ** @IncSym *********************** SUPPORT MACRO ******
            ;; Увеличить на 1 счетчик последовательности вложенностей
            @IncSym          MACRO    p1,p2
            &p1&p2 =                  &p1&p2   + 1
                   ENDM
            ;;
            ;; ** @DecSym *********************** SUPPORT MACRO *****
            ;; Уменьшить на 1 счетчик последовательности вложенностей
            @DecSym          MACRO    p1,p2
            &p1&p2 =                  &p1&p2   -1
                   ENDM
            ;;
            ;; ** @MakeJmp2 ********************** SUPPORT MACRO *****
            ;; Вставить команду перехода (JMP) в программный код
            @MakeJmp2        MACRO    p1,p2,p3
                    jmp               &p1&p2&p3
                   ENDM
            ;;
            ;; ** @MakeJmp *********************** SUPPORT MACRO *****
            ;; Переформатировать символы для команды JMP
            @MakeJmp         MACRO    p1,p2,p3
            ??tmp  =                  &p3&p2
                   @MakeJmp2          p1,p2,%??tmp
                   ENDM
            ;;
            ;; ** @MakeJmpLabel2 *****************SUPPORT MMACRO *****
            ;; Вставить метку команды JMP в программный код
            @MakeJmpLabel2   MACRO    p1,p2,p3
            &p1&p2&p3:
                   ENDM
            ;;
            ;; ** @MakeJmpLabel ****************** SUPPORT MACRO *****
            ;; Переформатировать символы для определения метки опера-
            ;; тора JMP
            @MakeJmpLabel    MACRO    p1,p2,p3
            ??tmp  =                  &p3&p2
                  @MakeJmpLabel2      p1,pp2,%??tmp
                  ENDM
            ;;
            ;; ** @IfTrue ************ STRUCTURED CONTROL MACRO *****
            ;; Структурированное макро "IF" - IF TRUE
            @IfTrue          MACRO    p1
                  LOCAL         iftrue
                   j&p1          iftrue    ;;перейти к секции "IF"
                   IFNDEF        ?if_level ;;установить новый уровень
                                           ;;вложенности
            ?if_level            =      10
                   ELSE
            ?if_level            =      ?if_level + 1
                   ENDIF
                   @TestSym      ?if_nest,%?if_level  ;;установить новый
                                        ;;номер последовательности
                   If            (?symdef)
                   @IncSym       ?if_nest,%?if_level
                   ELSE
                   @ZeroSym      ?if_nest,%?if_level
                   ENDIF
            ;; Вставить переход  в секцию "ELSE" или "IF NOT"
                   @MakeJmp      ?if_,%?if_level,?if_nest
            iftrue:
                   ENDM
            ;;
            ;; **  @IfElse *********** STRUCTURED CONTROL MACRO *****
            ;; Структурированное макро "ELSE"
            @IfElse          MACRO
                   IFNDEF         ?if_level
            ; ОШИБКА - "@IfElse" без открытого оператора "@IfTrue"
                   EXITM
                   ENDIF
                   IF(?if_level LT 10)
            ; ОШИБКА - "@IfElse" без открытого оператора "@IfTrue"
                   EXITM
                   ENDIF
            ;; Сгенерировать код "@IfElse"
                   @IncxSym       ?if_nest,%?if_level
                   @MakeJmp       ?if_,%?if_level,?if_nest
                   @DecSym        ?if_nest,%?if_level
                   @MakeJmpLabel  ?if_,%?if_level,?if_nest
                   @IncSym        ?if_nest,%?if_level
                   ENDM
            ;;
            ;; ** @IfEnd *********** STRUCTURED CONTROL MACRO *****
            ;; Структурированное макро "END" для совместного
            ;; использования с "@IfTrue"
            @IfEnd  MACRO
                    IFNDEF    ?if_level
            ; ОШИБКА - "@IfEnd" без открытого оператора "@IfTrue"
                   EXITM
                   ENDIF
                   IF  (?if_level LT 10)
            ; ОШИБКА - "@IfEnd" без открытого оператора "@IfTrue"
                   EXITM
                   ENDIF
            ;; Сгенерировать метку "@IfEnd"
                   @MakeJmpLabel  ?if_,%?if_level,?if_nest
            ?if_level     =       ?if_level - 1
                   ENDM
            ;;
            ;; ** @DoWhile ******** STRUCTURED CONTROL MACRO *****
            ;; Структурированное макро "DO_WHILE"
            @DoWhile       MACRO  p1,p2,p3
                   LOCAL   iftrue
                   IFNDEF  ?do_level      ;;установить новый уровень
                                          ;;вложенности
            ?do_level      =      10
                   ELSE
            ?do_level      =      ?do_level + 1
                   ENDIF
            ;; Установить номер новой последовательности для уровня
            ;; вложенности
                   @TestSym       ?do_nest,%?do_level
                   IF             (?symdef)
                   @IncSym        ?do_nest,%?do_level
                   ELSE
                   @ZeroSym       ?do_nest,%?do_level
                   ENDIF
            ;; Вставить метку начала цикла
                   @MаkeJmpLabel  ?do_,%?do_level,?do_nest
            ;; Вставить в программный код проверку условия
                   cmp      &p1,&p3
            ;; Перейти к секции "DO_WHILE_TRUE"
                   j&p2     iftrue
            ;; Перейти к следующей метке последовательности
                   @IncSym        ?do_nest,%?do_level
            ;; Вставить в программный код переход на конец цикла
                   @MakeJmp       ?do_,%?do_level,?do_nest
            ;; Начать секцию "DO_WHILE_TRUE"
            iftrue:
                   ENDM
            ;;
            ;; ** @DoExit *********** STRUCTURED CONTROL MACRO *****
            ;; Структурированное макро "DO_EXIT" для совместного
            ;; использования с "@DoWhile"
            @DoExit      MACRO
            ;; Вставить в программный код переход на конец цикла
                         @MakeJmp        ?do_,%?do_level,?do_nest
                         ENDM
            ;;
            ;; ** @DoEnd ************ STRUCTURED CONTROL MACRO *****
            ;; Структурированное макро "DO_END" для совместного
            ;; использования с "@DoWhile"
            ;; Макро @DoEnd генерирует программный код для структури-
            ;; рованного ENDDO
            @DoEnd       MACRO
                         IFNDEF          ?do_level
            ; ОШИБКА - "@DoEnd" без открытого оператора "@DoWhile"
                         EXITM
                         ENDIF
                         IF  (?do_level LT 10)
            ; ОШИБКА - "@DoEnd" без открытого оператора "@DoWhile"
                         EXITM
                         ENDIF
            ;; Переход на предыдущую метку последовательности
                         @DecSym         ?do_nest,%?do_level
            ;; Сгенерировать переход на начало цикла
                         @MakeJmp        ?do_,%?do_level,?do_nest
            ;; Перейти к следующей метке последовательности
                         @IncSym         ?do_nest,%?do_level
            ;; Сгенерировать метку для "@DoEnd"
                         @MakeJmpLabel   ?do_,%?do_level,?do_nest
            ?do_level      =       ?do_level - 1
                         ENDM
            ;;
            ;; ** @Repeat *********** STRUCTURED CONTROL MACRO *****
            ;; Структурированное макро "@Repeat"
            ;; "@Repeat" генерирует программный код для структури-
            ;; рованного REPEAT-UNTIL
            @Repeat      MACRO
                   IFNDEF   ?rep_level   ;;установить новый уровень
                                          ;;вложенности
            ?rep_level     =        10
                   ELSE
            ?rep_level     =        ?rep_level + 1
                   ENDIF
            ;; Установить новый номер последовательности для уровня
            ;; вложенности
                   @TestSym         ?rep_nest,%?rep_level
                   IF               (?symdef)
                   @IncSym          ?rep_nest,%?rep_level
                   ELSE
                   @ZeroSym         ?rep_nest,%?rep_level
                   ENDIF
            ;; Вставить метку перехода на начало цикла
                   @MakeJmpLabel    ?rep_,%?rep_level,?rep_nest
                   ENDM
            ;;
            ;; ** @Until ***********STRUCTURED CONTROL MACRO *****
            ;; Структурированное макро "@Until" для совместного
            ;; использования с "@Repeat"
            @Until       MACRO      p1,p2,p3
                         LOCAL      iftrue
                         IFNDEF     ?rep_level
            ; ОШИБКА - "@Until" без открытого оператора "@Repeat"
                         EXITM
                         ENDIF
                         IF (?rep_level LT 10)
            ; ОШИБКА - "@Until" без открытого оператора "@Repeat"
                         EXITM
                         ENDIF
            ;; Вставить в программный код проверку условия
                         cmp             &p1,&p3
            ;; Перейти к секции "@Until" .TRUE.
                         j&p2            iftrue
            ;; Вставить переход на начало цикла
                         @MakeJmp    ?rep_,%?rep_level,?rep_nest
            iftrue:
            ?rep_level     =        ?rep_level- 1
                         ENDM
            ;;
            ;; ** @For *********** STRUCTURED CONTROL MACRO *****
            ;; Структурированное макро "@For". Используйте это
            ;; макро так:
            ;;     @For     counter,begin,end,dir,step
            ;;
            @For    MACRO           p1,p2,p3,p4,p5
                    LOCAL           first
                    LOCAL           iftrue
                    IFNDEF          ?for_level  ;;установить новый
                                    ;;уровень вложенности
            ?for_level     =        10
                    ELSE
            ?for_level     =        ?for_level + 1
                    ENDIF
            ;; Установить новый номер последовательности для
            ;; уровня вложенности
                    @TestSym        ?for_nest,%?for_level
                    IF              (?symdef)
                    @IncSym         ?for_nest,%?for_level
                    ELSE
                    @ZeroSym        ?for_nest,%?for_level
                    ENDIF
            ;; Вставить в программный код инициализацию счетчика -
            ;; (обойти 1-ый шаг)
                    mov             &p1,&p2 ;инициализировать счетчик
                    jmp             first   ;начать цикл FOR
            ;; Вставить метку перехода на начало цикла
                    @MakeJmpLabel   ?for_,%?for_level,?for_nest
            ;; Вставить в программный код шаг вычислений и выполнить
            ;; его проверку
                    IFIDN           ,<+>
                    inc             &p1     ;увеличить счетчик
                    ELSE
                    IFIDN           ,<->
                    dec             &p1     ;уменьшить счетчик
                    ELSE
            ; ОШИБКА - неверная спецификация шага в операторе "@For"
                    EXITM
                    ENDIF
                    ENDIF
            first:           ;проверить на необходимость продолжения
            ;; Вставить в программный код проверку условия
                    cmp             &p1,&p3  ;достигнут ли конец?
            ;; Перейти к секции "FOR_TRUE"
                    IFIDN           ,<+>
                    jl              iftrue   ;нет - продолжить цикл FOR
                    ELSE            ;;по умолчанию - к шагу "-"
                    jg              iftrue   ;нет - продолжить цикл FOR
                    ENDIF
            ;; Перейти к следующей метке последовательности
                    @IncSym         ?for_nest,%?for_level
            ;; Вставить в программный код переход на конец цикла
                    @MakeJmp        ?for,%?for_level,?for_nest
            iftrue:
                    ENDM
            ;;
            ;; ** @ForEnd ******** STRUCTURED CONTROL MACRO *****
            ;; Структурированное макро "FOR_END" для совместного
            ;; использования с "FOR"
            ;; @ForEnd генерирует программный код для структури-
            ;; рованного цикла FOR
            @ForEnd MACRO
                    IFNDEF          ?for_level
            ; ОШИБКА - "@ForEnd" без открытого оператора "FOR"
                    EXITM
                    ENDIF
                    IF  (?for_level LT 10)      page_end12
            ;
                    EXITM
                    ENDIF
            ;;
                    @DecSym          ?for_nest,%?for_level
            ;;
                    @MakeJmp         ?for_,%?for_level,?for_nest
            ;;
                    @IncSym          ?for_nest,%?for_level
            ;;
                    @MakeJmpLabel    ?for_,%?for_level,?for_nest
            ?for_level       =       ?for_level- 1
                    ENDM
            ;; **************************************************

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Hosted by uCoz