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










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

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

Сравнение строк. Пример

К сожалению, способность оператора .TYPE распознавать непосредственные операнды и регистры значительно уменьшается при выяснении типа операндов макро. Так как особенно важно знать, является ли аргумент макро регистром, мы должны сконструировать способ выявления этого. Определение того, является ли аргумент регистром, обычно полезно только вместе с неявным предположением, что если он не является регистром и не является определенной адресной ссылкой, то предположительно является ссылкой на непосредственные данные.


Это хорошо сочетается с использованием условного ассемблирова ния на базе директив IRP и IRPC. Целью в данном случае является определение принадлежности аргумента макро к какому-либо набору. Для решения задачи - является ли аргумент регистром, используется сопоставление строк. Так как оператор .TYPE может определить только то, что эти регистры объявлены локально и абсолютны, для явной проверки имени регистра применяется макро сопоставления строк. Эту функцию выполняет приведенное в Листинге 1-8 макро ?reg.



              Листинг 1-8. Макро сопоставления имен регистров - ?reg
         -----------------------------------------------------------------

            FALSE    EQU     0
            TRUE     EQU     0FFFFh
            ;;
            ;;**** ?REG - Определить, является ли аргумент регистром
            ;;
            ?reg     MACRO   arg
            ?isr8    =       FALSE
            ?isr16   =       FALSE
                     IRP     reg,
                     IFIDN   <&®>,<&arg>
                     ?isr16  =       TRUE
                     EXITM
                     ENDIF
                     ENDM    ;; конец секции IRP
            ;; Если сравнились, остановиться здесь
                     IF      (?isr16)
                     EXITM
                     ENDIF
            ;; Если еще не сравнились, продолжить далее
                     IRP     reg,
                     IFIDN   <&®>,<&arg>
                     ?isr8   =        TRUE
                     EXITM
                     ENDIF
                     ENDM    ;; конец секции  IRP
            ;; Если сравнились, остановиться здесь
                     IF      (?isr8)
                     EXITM
                     ENDIF
            ;; Если не сравнились, попробовать прописные имена регистров
                     IRP     reg,
                     IFIDN   <&®>,<&arg>
                     ?sir16  =       TRUE
                     EXITM
                     ENDIF
                     ENDM    ;; конец секции IRP
            ;; Если сравнились, остановиться здесь
                     IF      (?isr16)
                     EXITM
                     ENDIF
            ;; Если еще не сравнились, попробовать еще
                     IRP     reg,
                     IFIDN   <&®>,<&arg>
                     ?isr8   =        TRUE
                     EXITM
                     ENDIF
                     ENDM    ;; конец секции IRP
                     ENDM    ;; конец макроописания
         -----------------------------------------------------------------

Cердцевиной этого макро, как и любого макро сопоставления, являются команды:



            IRP       reg,
            IFIDN     <&®>,<&arg1>
            ?isr16    %        TRUE

            Интерпретировать эти строки можно так:

            Для reg равного ax...ss выполнить . . .
                Если reg равно аргументу arg . . .
                     Аргумент есть регистр!

Здесь следует остановиться на двух интересных моментах. Во-первых, необходимо явно проверять имена регистров, написанные как малыми, так и большими буквами. Директива условного ассембли рования IFIDN сравнивает строки на точное соответствие. Несмотря на все усилия, макро ?reg не полно. Оно не сопоставляет имена регистров, состоящие из одной большой и одной малой буквы (например "aL"). Во-вторых, необходимо проводить две проверки: одну для 16-битовых регистров и одну для 8-битовых регистров. В данной реализации наличие двух отдельных проверок не приносит нам никакой выгоды, однако такие проверки окажутся полезными в следующем примере.


Макро ?reg имеет два дополнительных синтаксических элемента. Один - директива завершения макро EXITM. Эта директива используется для завершения работы макро ?reg при обнаружении совпадения.


Менее очевидно использование двойного амперсанда в операторе IFIDN. Согласно Руководству по MASM фирмы Майкрософт пользователь должен "указывать столько амперсандов, сколько имеется уровней вложенности". Столь лаконичное выражение не вносит ясности в решение проблемы. "Уровни вложенности" относятся не к глубине блоков, где появляется ссылка, а к глубине блоков, где находится ее описание. Таким образом, arg1 приводится только с одним амперсандом, в то время как reg, описание которого находится во вложенном блоке, требует наличия двух амперсандов. Фирма Майкрософт не утверждает, что это предел разрешенного количества уровней вложенности или количества требуемых амперсандов. В тех случаях, когда казалось бы необходимо указывать множество амперсандов, попытки написания примеров, позволяющих выявить правильное функционирование, не увенчались успехом.


Приведенный Листинг 1-9 с макро ?reg показывает, что это макро выполняет возложенную на него функцию. Заметьте,что регистр bР, который распознается MASM, отбрасывается макро ?reg. Это может быть истолковано, как необходимость соблюдения строгого правила ввода исходного текста программы с клавиатуры.



              Листинг 1-9. Тест макро сравнения имен регистров - ?reg
         -----------------------------------------------------------------

                       ?reg   ax      ; "AX" - регистр ?
            FFFF       dw     ?isr16               <--- TRUE
                       ?reg   CS      ; "CS" - регистр ?
            FFFF       dw     ?isr16               <--- TRUE
                       ?reg   zork    ; "ZORK" - регистр ?
            0000       dw     ?isr16               <--- FALSE
            0000       dw     ?isr8                <--- FALSE
                       ?reg   01234h  ; "1234" - регистр ?
            0000       dw     ?isr16               <--- FALSE
            0000       dw     ?isr8                <--- FALSE
                       ?reg   bР      ; "BP" - регистр ?
            0000       dw     ?isr16               <--- FALSE
            0000       dw     ?isr8                <--- FALSE
         -----------------------------------------------------------------

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

Hosted by uCoz