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










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

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

Приемы кодирования и некоторые предупреждения

Когда необходимо создать действительную команду перехода и метку перехода, мы будем использовать макросы mkjmp, mkjmp2, mklbl и mklbl1. Действительные метки состоят из идентификатора типа и номеров. Единственный способ получить числовое значение символа заключается в применении оператора процента (%), который действителен только при использовании с аргументом вызова макро. Мы хотим вычислить символ, определяемый двумя элементами информации из счетчика, так:



            mkjmp2      p1,p2,%&p3&p2

Однако Руководство по MASM сообщает нам, что оператор амперсанда (&) не может быть использован в вызове макро. Таким образом, мы должны создать временную переменную и использовать ее.



            ??tmp =     &p3&p2
                    mkjmp2 p1,p2,%??tmp

Все это влечет за собой следующее. Первая форма, содержащая амперсанды в вызове макро, должна работать. Однако выбор скрытой возможности вызывает проблемы будущей совместимости и даже реализуемости. Кроме того, Вы всегда должны задаваться вопросом, может ли неподдерживаемая или несанкционированная функция зависеть от реализации совместимости. Решение этой дилеммы остается за читателем.


Авторы использовали эту несанкционированную возможность в программе, не генерирующей программного кода, но решающей знаменитую задачу "Ханойские башни" в рекурсивной манере. Кроме того, для достижения общности наш метод создания символов счетчиков из нескольких частей позволяет при необходимости создавать новые счетчики. Перед своим использованием эти счетчики должны инициализироваться, в противном случае первая попытка увеличить или уменьшить их значение вызовет ошибку "Символ не определен". Используя условный оператор IFDEF, можно проверить, требуется ли инициализация при каждом использовании символа.


Инициализация связана еще с одной тонкостью работы MASM. Как мы установили, MASM является двухпроходным ассемблером, определяющим символы при первом проходе и затем использующим их при втором. Это значит, что определения символов защищены от первого прохода ко второму. Таким образом, когда MASM начинает второй проход, все счетчики первого прохода уже определены и содержат свои старые значения. Если в начале второго прохода переинициализация символов не происходит,возникает фазовая ошибка, так как начальные значения счетчиков отличаются.


Для инициализации символов на первом проходе необходима конструкция IFDEF, так как заранее мы не знаем, сколько счетчиков потребуется, а использования IFDEF на втором проходе недостаточно. Мы решили эту проблему, создав символы ?р2sw ..., которые на втором проходе анализируются на необходимость установки в нулевые значения. Имя получается из Switch (переключателя) фазы 2. Этот процесс проверки предоставляет хорошую возможность выявить, принадлежат ли уровни вложенности самому верхнему уровню, указывая, что конструкции IF-IFEND, DOWHILE-DOEND и т.д. спарены правильно.


В Листинге 1-16 приведены простые примеры расширения макросов структурного управления, определенных ранее. Как можно видеть, мы подавили те части расширения, которые не вырабатывают код или метки переходов. Если Вы хотите ознакомиться с работой этих макросов более детально, используйте директиву .LALL. Прибегайте только к сокращенному примеру, так как обработка этих макро вызывает выполнение множества шагов. Количество шагов также объясняет, почему происходит увеличение требуемого времени ассемблирования программы. Используя эти макро, не ожидайте быстрого ассемблирования, но рассчитывайте на быстрое кодирование.



                  Листинг 1-15. Вложенная структура IF-THEN-ELSE

         ----------------------------------------------------------------
                         ; Сжатый исходный код программы

                      @IfTrue e             условие (a)
                        @IfTrue e           условие  (b)
                        @IfElse             "else" для условия (b)
                        @IfEnd              конец условия (b)
                      @IfElse               "else" для условия (a)
                        @IfTrue e           условие (c)
                        @IfElse             "else" для условия (c)
                        @IfEnd              конец условия (c)
                      @IfEnd                конец условия (a)
                         ; Листинг расширения
                      @IfTrue e             условие (a)
            1         je    ??0000
            3         jmp     ?if_100
            1 ??0000:
              ; выполнить, если условие (а) истинно
                      @IfTrue e             условие (b)
            1         je    ??0001
            3         jmp     ?if_110
            1 ??0001:
              ; выполнить, если условие (b) истинно
                      @IfElse               "else" для условия (b)
            3         jmp     ?if_111
            3 ?if_110:
              ; выполнить, если условие (b) не истинно
                      @IfEnd                конец условия (b)
            3 ?if_111:
                      @IfElse               "else" для условия (a)
            3         jmp     ?if_101
            3 ?if_100:
              ; выполнить, если условие (а) не истинно
                      @IfTrue e              условие (c)
            1         je    ??0002
            3         jmp     ?if_112
            1 ??0002:
              ; выполнить, если условие (с) истинно
                      @IfElse               "else" для условия (c)
            3         jmp     ?if_113
            3 ?if_112:
              ; выполнить, если условие (с) не истинно
                      @IfEnd                конец условия (c)
            3 ?if_113:
                      @IfEnd                конец условия (a)
            3 ?if_101:
         ---------------------------------------------------------------


               Листинг 1-16. Расширение  структурированных макросов

         ----------------------------------------------------------------
                      @IfTrue e
            1         je    ??0000
            3         jmp     ?if_100
            1 ??0000:
              ; Выполнить, если истина
                      @IfElse
            3         jmp     ?if_101
            3 ?if_100:
              ; Выполнить, если не истина
                      @IfEnd
            3 ?if_101:
              ;- - - - - - - - - - - - - - - - - - - - - - - - - -
                      @DoWhile ax,le,bx
            3 ?do_100:
            1         cmp      ax,bx
            1         jle    ??0001
            3         jmp     ?do_101
            1 ??0001:
              ; Выполнять пока  ax <= bx
                      @DoExit
            3         jmp     ?do_101
              ; Выйти из программы
                      @DoEnd
            3         jmp      ?do_100
            3  ?do_101:
            ;- - - - - - - - - - - - - - - - - - - - - - - - - -  - -
                       @Repeat
            3  ?rep_100:
               ; Выполнять пока соблюдается условие
                       @Until   ax,e,bx
            1          cmp      ax,bx
            1          je     ??0002
            3          jmp      ?rep_100
            1  ??0002:
               ;- - - - - - - - - - - - -- - - - - - - - - - - - - - -
                       @For     ax,10,20,+
            1          mov      ax,10       ;инициализировать счетчик
            1          jmp      ??0003      ;начать цикл FOR
            3  ?for_100:
            1          inc      ax          ;увеличить счетчик
            1  ??0003:        ;проверить на необходимость продолжения
            1          cmp      ax,20       ;достигнут ли конец
            1          jl       ??0004      ;нет - продолжить цикл
            3          jmp      ?for_101
            1  ??0004:
               ; Выполнить для ах = 10 до 20 с шагом 2
                       @ForEnd
            3          jmp      ?for_100
            3  ?for_101:
         ----------------------------------------------------------------

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

Hosted by uCoz