Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Machinarium |#5| The Bremen Town Musicians (1)
Machinarium |#4| Lower street
Machinarium |#3| Jail
Machinarium |#2| Pit & Boiler

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Различные авторы Весь текст 2311.07 Kb

Программирование и кодирование

Предыдущая страница Следующая страница
1 2 3 4  5 6 7 8 9 10 11 12 13 14 ... 198
         требуется,  так  как  он  выделяет формальный аргумент при чтении
         макро и проясняет для MASM, что имелось в виду.


                                 Метки типа LOCAL

            До сих пор макросы, использованные нами, предназначались  лишь
         для  генерации  простых ассемблерных команд.  Теперь предположим,
         что мы хотим создать макро,  которое выбирает меньшее из двух чи-
         сел  и  помещает  результат в какую-то ячейку.  Такое макро может
         выглядеть, например, так:

                                      - 1-5 -
            min  MACRO    result,first,second
                 mov      &result,&first
                 cmp      &first,&second
                 jl       order_ok
                 mov      &result,&second
            order_ok:
                 ENDM

            Когда мы вызываем макро min,  оно вырабатывает правильный код,
         однако имеется одна проблема: хотя макро вычисляется превосходно,
         оно может быть использовано лишь единожды. Так как метка order_ok
         может быть определена в программе только один раз,  при использо-
         вании данного макро в двух местах программы MASM распознает  мно-
         жественное определение символа.
            Чтобы в добавление к другим параметрам разрешить указание  па-
         раметра метки, мы можем выполнить небольшое изменение макро:

            min   MACRO     result,first,second,order-ok
                  mov       &result,&first
                  cmp       &first,&second
                  jl        &order_ok
                  mov       &result,&second
            оrder_ok&:
                  ENDM
            При вызове нового макро min,  показанного в следующем  номере,
         мы можем указать имя,  которое будет использоваться для метки пе-
         рехода. Теперь макро min может быть использовано всякий раз, ког-
         да это необходимо,  так как каждый раз метке перехода будет прис-
         ваиваться новое имя.  Однако действительное имя не имеет для  нас
         никакого значения, ибо метка является собственностью функции min.

                  min       ax,bx,cx,jmp1        <- вызов макро
            1     mov       ax,bx
            1     cmp       bx,cx
            1     jl        jmp1
            1     mov       ax,cx
            1  jmp1:

            Такой способ создания нового имени при каждом вызове макро min
         является лучшим.  Именно для этой цели MASM имеет директиву LOCAL
         (локальный). Когда MASM встречает LOCAL, для стоящего рядом имени
         создается уникальная метка. Другой способ заключается в помещении
         параметра LOCAL в список параметров MACRO,  но при этом MASM про-
         изводит  присваивание действительного аргумента.  Предупреждение:
         операторы LOCAL всегда должны помещаться сразу  же  после  строки
         именования MACRO! После включения директивы LOCAL новое макро min
         выглядит так:
            min    MACRO     result,first,second
                   LOCAL     order_ok
                   mov       &result,&first
                   cmp       &first,&second
                   jl        order_ok
                   mov       &result,&second
            order_ok:
                   ENDM

                                      - 1-6 -

            Теперь, когда мы снова вызовем макро min, образуется листинго-
         вый файл, как показано в следующем примере. Значение order_ok бу-
         дет заменено на ??0000.  Каждый раз при вызове макро order_ok за-
         меняется на новое значение, вырабатываемое MASM.

                    min       ax,bx,cx   ;первый вызов
            1       mov       ax,bx
            1       cmp       bx,cx
            1       jl        ??0000
            1       mov       ax,cx
            1  ??0000:
                    min       ax,bx,cx   ;второй вызов
            1       mov       ax,bx
            1       cmp       bx,cx
            1       jl        ??0001
            1       mov       ax,cx
            1  ??0001:

            Конечно, остается  вероятность  возникновения конфликта меток,
         если Вы решите использовать метки, начинающиеся с ??. Если Вы ус-
         траните использование меток, начинающихся с ??, то Вы сможете вы-
         зывать макро min столько раз, сколько захотите.
            Использование меток  LOCAL не ограничивается только переходами
         по адресам. Метки LOCAL могут также использоваться с данными, как
         показано  в следующем макросе.  В этом случае макрос используется
         для вставки текстовых строк в сегмент данных и последующего  соз-
         дания ссылки на них в сегменте кода.
            Сравнивая исходный текст с макрорасширением  в  Листинге  1-1,
         можно увидеть, насколько удобно использовать макрос. Листинг  1-1
         также содержит некоторые полезные  макросы,  облегчающие  решение
         задачи по написанию программ .ЕХЕ. Однажды определив эти макросы,
         Вы можете не беспокоиться  за  правильность  синтаксиса  программ
         .ЕХЕ!

                        Листинг 1-1. Программа Hello World
             -------------------------------------------------------------
            ;********************************************************
            ;        С Е К Ц И Я   М А К Р О О П И С А Н И Я
            ;********************************************************
            ;
            @DosCall  MACRO
                      int      21h  ;вызвать функцию MS-DOS
                      ENDM
            ;
            @InitStk  MACRO         ;определить размер стека
            stk_seg   SEGMENT  stack
                      DB       32 dup ('stack   ')
            stk_seg   ENDS
                      ENDM
            ;
            @InitPrg  MACRO    segment  ; инициализировать сегмент
                      ASSUME ds:segment ; данных
            start:                      ; основная точка входа
                      mov      ax,segment

                                      - 1-7 -
                      mov      ds,ax    ;установить сегмент данных
                      mov      es,ax    ;установить внешний сегмент
                      ENDM
            ;
            @Finis    MACRO
                      mov      ax,4C00h ;завершить процесс
                      @DosCall
                      ENDM
            ;
            @DisStr   MACRO    string   ;отобразить строку памяти
                      mov      dx,offset string
                      mov      ah,09h
                      @DosCall
                      ENDM
            ;
            @TypeStr  MACRO     string  ;определить и отобразить строку
                      LOCAL     saddr   ;установить локальную метку
            cod_seg   ENDS              ;завершить сегмент кода
            dat_seg   SEGMENT           ;перейти к сегменту данных
            saddr     DB    string,'$'  ;определить строку в сегм.данных
            dat_seg   ENDS              ;завершить сегмент данных
            cod_seg   SEGMENT           ;вернуться к сегменту кода
                      @DisStr   saddr   ;отобразить строку
                      ENDM
            ;
            ;
            ;********************************************************
            ;         П Р О Г Р А М М Н А Я    С Е К Ц И Я
            ;********************************************************
            ;
                      @IniStk                ;установить стек
            cod_seg SEGMENT                  ;определить сегмент кода
            main    PROC        FAR          ;главная (одна) процедура
                    ASSUME      cs:cod_seg   ;назначить сегм.кода рег.CS
                    @InitPrg dat_seg         ;инициализ-ать сегмент кода
                    @TypeStr 'Hello world!'  ;выдать приветствие
                    @Finis                   ;закончить программу
            main    ENDP                     ;завершить процедуру
            cod_seg ENDS                     ;завершить сегмент кода
                    END         start        ;завершить программу и ...
                                             ;определить адрес пуска
            -------------------------------------------------------

            Программу можно вводить точно так,  как она приведена, а затем
         ее ассемблировать и  выполнять.  Слова  "Hello  world!"  подлежат
         отображению на экране.Сам по себе результат не очень выразителен,
         однако,  если используемый макрос сохранен в файле include (вклю-
         чить),  написание .EXE-программ значительно облегчается.  Давайте
         посмотрим на распечатку расширения программы, приведенного в Лис-
         тинге 1-2.


                                      - 1-8 -
                Листинг 1-2. Макрорасширение программы Hello World
             -------------------------------------------------------------
            ;********************************************************
            ;           П Р О Г Р А М М Н А Я   С Е К Ц И Я
            ;********************************************************
            ;
            ;       @InitStk                 ;установить стек
            1       stk_seg   SEGMENT stack
            1                 DB      32 dup ('stack   ')
            1       stk_seg   ENDS
             cod_seg          SEGMENT        ;определить сегмент  кода
             main             PROC   FAR     ;главная (одна) процедура
                    ASSUME    cs:cod_seg     ;назначить сегм.кода рег.CS
                    @InitPrg  dat_seg        ;инициализ-ать сегмент данных
            1       start:                   ;главная точка входа
            1                 mov  ax,dat_seg
            1                 mov  ds,ax     ;установить сегмент данных
            1                 mov  es,ax     ;установить внешний сегмент
                    @TypeStr 'Hello World!'  ;выдать приветствие
            1       cod_seg   ENDS           ;приостановить сегмент кода
            1       dat_seg   SEGMENT        ;перейти к сегменту данных
            1       ??0000    DB   'Hello world!,'$' ;определить строку
            1       dat_seg   ENDS        ;приостановить сегмент данных
            1       cod_seg   SEGMENT     ;вернуться к сегменту кода
            2                 mov   dx,offset ??0000
            2                 mov   ah,09h
            3                 int   21h      ;вызвать функцию MS-DOS
                    @Finis                   ;завершить программу
            1                 mov   ax,4C00h ;завершить процесс
            2                 int  21h       ;вызвать функцию MS-DOS
                    main      ENDP           ;закончить процедуру
                    cod_seg   ENDS           ;закончить сегмент кода
                    END       start          ;закончить программу ...


            Прежде всего необходимо заметить,  что используемый  локальный
         адрес  (saddr)  в  @TypeStr  отлично работает как метка оператора
         данных.  При связывании меток с данными не используйте  двоеточие
         (:). Далее посмотрим, как макрорасширение использует зарезервиро-
         ванное слово SEGMENT (сегмент) в  макро  @InitPrg.  Нет  проблем!
         Вспомните,  что  имена  формальных аргументов в списке аргументов
         перекрывают все другие описания MASM.
            Обратите внимание,  что некоторые строки не включены в листин-
         говый файл.  Например,  оператор ASSUME ds:data_seg  из  @InitPrg
         опущен.  Оператор был отассемблирован,  но MASM подавил вывод его
         расширения.
            Все это произошло по причине специфики обработки  макросов. По
         умолчанию, исходные строки, не вырабатывающие исполнительного ко-
         да,  в листинге подавляются.  Оператор ASSUME является директивой
Предыдущая страница Следующая страница
1 2 3 4  5 6 7 8 9 10 11 12 13 14 ... 198
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама