Главная · Поиск книг · Поступления книг · 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 ... 4 5 6 7 8 9 10  11 12 13 14 15 16 17 ... 198
            0000       dw     ?isr8                <--- FALSE
         -----------------------------------------------------------------

                      Синтаксический анализ аргументов макро

            С помощью макро, распознающего имена регистров, можно реализо-
         вать обобщенное макро PUSH,  которое мы назовем @PUSHOP (протолк-
         нуть операнд).  (Замечание: мы рассматриваем имя pusha для " про-
         толкнуть все", но PUSHA является кодом операции для чипов 186,188
         и 286 фирмы Intel.  Использование его для макро может  ограничить
         совместимость снизу вверх. Конечно, Вы всегда можете использовать
         команду PUSHA в макро pusha для микропроцессоров 8086 и 8088).
            Как упоминалось  ранее относительно типа операнда,  который не

                                      - 1-27 -
         определен и не является регистром,  необходимо  делать  некоторые
         предположения.  Для  макро  @PUSHOP предположим,  что неизвестные
         операнды являются ссылками на  непосредственные  данные.  @PUSHOP
         ссылается  на  макро  ?reg,  и  макро ?reg должно быть включено в
         программу с @PUSHOР. Макро @PUSHOP см. в Листинге 1-10.
            @PUSHOP использует возможность макро ?reg различать 16-  и  8-
         битовые регистры. Так как команда PUSH не обрабатывает  8-битовый
         регистр, для получения первого символа имени регистра использует-
         ся директива IRPC. Затем @PUSHOP добавляет х, формируя ,таким об-
         разом,  имя 16-битового регистра, которое приемлемо для PUSH. За-
         метим,  что  в  этом  операторе  снова  необходимо  использование
         удвоенного амперсанда, причем с обеих сторон формального аргумен-
         та, так как сцепление строк возникает с обоих концов.
            Для тех случаев, когда предполагается наличие непосредственных
         данных,  вызывается макро @PushIm.  Это макро более сложное , чем
         минимально необходимое,  так как предполагается, что для передачи
         непосредственных данных  в  стек  нельзя  использовать  регистры.
         Вместо этого макро использует указатель базы (BP) на адрес стека.
         После сохранения BP и AX в стеке @PushIm заносит непосредственные
         данные  поверх содержимого AX,  обменивая их со старым содержимым
         BP.  После восстановления содержимого BP макро извлекает содержи-
         мое AX,  выталкивая его из стека.  Макро @PushIm приведено в Лис-
         тинге 1-11.

                   Листинг 1-10. Обобщение макро PUSH - @PushOp
         ----------------------------------------------------------------

            ;; **** @PushOp макро с обобщенным операндом команды PUSH
            ;; Если операнд определен, он может быть:
            ;;              регистром
            ;;              ссылкой на данные
            ;;
            ;; Если операнд не определен, он полагается ссылкой на
            ;;              непосредственные данные
            @PushOp  Macro  arg
                     .SALL
                     IFDEF  &arg                 ;; операнд определен ...
                        ?argtyp = .type &arg           ;; выявить его тип
                        IF     ((?argtyp and 3) EQ 2)  ;;операнд - данные
                          ?argsiz = ((type &arg) + 1)/2 ;; получить длину
                                                        ;; в словах
                          ?argoff = 0          ;; установить смещение в 0
                          REPT   ?argsiz   ;; повторить для каждого слова
                             ?argadd = word ptr &arg + ?argoff ;;получить
                             .XALL                               тип ptr
                             push     ?argadd ;;продв-ть непоср.в память
                             .SALL
                             ?argoff = ?argoff + 2 ;;след-ее слово данных
                           ENDM
                         ENDIF
                         IF ((?argtyp AND 3) EQ 1)  ;;операнд - программа
                           @PushImOff   &arg  ;;продвинуть смещение метки
                         ENDIF
                         IFE    (?argtyp and 3) ;;операнд - абс.значение
                           ?reg &arg
                           IF   (?isr16)        ;;операнд - регистр 16
                             .XALL

                                      - 1-28 -
                             push        &arg   ;;продвинуть непосред.
                             .SALL
                          ELSE
                            IF  (?isr8)         ;;операнд - регистр 8
                              IRPC chr1,&arg1
                                .XALL
                                push  &&chr1&&x ;;сохранить короткий рег.
                                .SALL
                                EXITM
                                ENDM
е                             ELSE            ;;предположить непосред.данны
                                @PushIm &arg  ;;продвинуть непосред. данные
                              ENDIF
                            ENDIF
                          ENDIF
                        ELSE                  ;;продвинуть непосред.данные
                           @PushIm &arg
                        ENDIF
                        ENDM                  ;;конец макроописания
         -----------------------------------------------------------------


            Листинг 1-11. Макро проталкивания непосредственных данных -
                                      @PushIm
         ----------------------------------------------------------------

            ;; **** @PushIm макро проталкивания непосредственных данных
            @PushIm Macro arg
                    .XALL
                    push   bp       ;;сохранить указатель базы
                    mov    bp,sp    ;;переместить указатель стека в BP
                    push   ax       ;;сохранить накопитель
                    mov    ax,&arg  ;;получить непосредственные данные
                    xchg   [bp],ax  ;;обменять старый BP и непосред. данные
                    mov    bp,ax    ;;восстановить старый BP из AX
                    pop    ax       ;;восстановить накопитель
                    .SALL
                    ENDM            ;;конец макроописания
         ----------------------------------------------------------------

            Эта операция свертывания может быть сведена к обмену элемента-
         ми  внутри  стека.  Однако ведение подобных игр со стеком опасно.
         Если Ваш компьютер поддерживает прерывания, для предохранения це-
         лостности данных стека эта операция должна выполняться только че-
         рез запрещение прерываний.
            Для тех  случаев,  когда  делается  попытка протолкнуть в стек
         программные адреса,  мы предполагаем, что программист желает сох-
         ранить  действительное  смещение метки.  Для проталкивания в стек
         смещения метки,  как непосредственных данных,  было  использовано
         макро @PushImOff.  Оно отличается от макро @PushIm только исполь-
         зованием команды:

             mov      ax,offset  &arg   ,

         что противоположно простому перемещению в  макро  @PushIm.  Макро
         @PushImOff приведено в Листинге 1-12.


                                      - 1-29 -

                Листинг 1-12.  Макро  продвижения  в стек смещения
                       непосредственных данных - @PushImOff
         ---------------------------------------------------------------

            ;; **** @PushImOff макро продвижения смещения непосред.данных
            @PushImOff  MACRO  arg
                   .XALL
                   рush    bp       ;;сохранить указатель базы
                   mov     bp,sp    ;;переместить указатель стека в BP
                   push    ax       ;;сохранить накопитель
                   mov     ax,offset &arg ;;получить смещение
                                          ;;непосред.данных
                   xchg    [bp],ax  ;;обменять старый BP и непоср.данные
                   mov     bp,ax    ;;восстановить старый  BP из AX
                   pop     ax       ;;восстановить накопитель
                   .SALL
                   ENDM             ;;конец макроописания
         ----------------------------------------------------------------


            Последним дискретным случаем,  который распознает @PushOp, яв-
         ляется попытка прямого проталкивания в стек данных памяти.  Слож-
         ность  в  этом  случае  заключается в том,  что стек воспринимает
         только 16-битовые данные.  Используя  директиву  перекрытия  PTR,
         можно убедить MASM сохранять нужные данные пословно.  @PushOp со-
         держит цикл,  который повторяет эту операцию  для  каждого  слова
         сохраняемых  данных,  увеличивая  адрес на два при каждом проходе
         цикла.  Таким образом можно сохранять в стеке двойные слова, чет-
         верные слова, 10-байтовые данные и структуры данных.
            Наконец, заметим,  что макро @PushOp все еще  не  обрабатывает
         ссылки, содержащие сложную адресацию (2[BP] и т.д.). В случае не-
         обходимости Вы можете применить подобные проверки, используя мак-
         родирективу  IRPC  для  выявления в аргументах квадратных скобок,
         адресации "база + индекс" и "база + смещение".
            Итоговый тест  макро @PushOp приведен в Листинге 1-13, который
         содержит результат нескольких вызовов макро @PushOp.
            Последняя операция листинга,  где @PushOр обрабатывает 4-слов-
         ную переменную,  не может быть изъята. Каждое проталкивание имеет
         один  и  тот  же аргумент.  Однако из этого красивого листинга не
         видно,  что каждая его строка имеет перемещаемый адрес (0000  для
         первого слова, 0002 для второго и т.д.). К сожалению, мы не можем
         в данной книге привести 132-колоночные листинги, и, если Вы хоти-
         те проверить, попробуйте получить такой листинг сами.
            Этот пример особенно полезен тем,  что демонстрирует одну  об-
         ласть,  где применение макро почти всегда предпочтительнее приме-
         нения подпрограмм.  Что касается обработки стека (как в @PushIm и
         @PushImOff),  макросы  способны выполнять эти операции без "угро-
         зы" влияния команды CALL на стек.  Это особенно важно при переме-
         щении или изъятии данных из стека,  так как подпрограмма не может
         изменить вершину стека и осуществить возврат, не вызвав серьезных
         осложнений.

                             Некоторые предупреждения
                    по использованию условного  ассемблирования
                                 и макросов в MASM

            Применяя макросы,  мы старались забыть,  что они  вырабатывают

                                      - 1-30 -
         построчный  код  и не вызывают программ.  Хотя это и представляет
         некоторые преимущества при быстрой генерации программного  кода и
         освобождает нас от ограничений по использованию стека,  результа-
         том линейной программы является более объемный код.  Как програм-
         мист, Вы должны решить, когда целесообразно вызывать быстро рабо-
         тающее макро,  а когда  -  подпрограмму,  экономящую  память,  но
         имеющую разветвленную структуру. В общем случае  используйте мак-
         ро, когда программный код невелик, а время критично, или когда Вы
         хотите конфигурировать программу, настроив ее на конкретные усло-
         вия.  Используйте подпрограмму, когда программный код велик и его
         нужно расположить в одном месте (так,  чтобы его можно было легко
         изменить).
            Другим тонким  моментом  работы  макро  является использование
         символов.  Вы помните, что символы определяются при помощи опера-
Предыдущая страница Следующая страница
1 ... 4 5 6 7 8 9 10  11 12 13 14 15 16 17 ... 198
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама