ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



 

Часть 12

ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
            Авторский коллектив "*.*" и "ГермеСофт"

ЦДДДДДДДДДДї                   ЦДДДДДДї       ЦДДДДДДДї   ЦДДї
ИННН»  ХНННѕ                   є ХННННѕ       є ХНН»  і   є  і
    є  і  ЦДї  ЦДїЦДДДДДДїЦДДДДЅ і  ЦДДДДДДї  ИНѕЦДЅ  і   є  і
    є  і  є і  є іє ХНН» іє ХНН» і  є ХНН» і     ИН»  і   є  і
    є  і  є АДДЅ іє АДДЅ іє АДДЅ і  є АДДЅ і  ЦДї  є  і   є  і
    ИННѕ  ИНННН» іє ХННННѕИННННННѕ  ИННННННѕ  є АДДЅ  іЦДїє  і
            ЦДДЅ іє і                         ИНННННННѕИНѕИННѕ
            ИННННѕИНѕ
          РЕЗИДЕНТНАЯ ПРОГРАММА-СПРАВОЧНИК ПО РУКОВОДСТВАМ
                                         ЦДДДї
 ЦДДДДїЦДДДДїЦДДДДїЦДДДДДїЦДДї  ЦДДї     є ХНѕ ЦДДДїЦДДДДДїЦДДДДї
 є ХН»ієХНННѕєХНННѕє  ДД іє  АїЦЅ  іЦДДДДЅ і  ЦЅ   іє  ДД іє ХНёі
 є АДЅієі    єі    є ХНННѕє Х»АЅХ» іє ХНН» і ЦЅ Х» іє ХНННѕє АДЩі
ЦЅ ХН»ієАДДДїєАДДДїє АДДДїє іИ»ЪЩє іє АДДЅ іЦЅ ЪЩє іє АДДДїє ХННѕ
ИННѕ ИѕИННННѕИННННѕИНННННѕИНѕ Иѕ ИНѕИННННННѕИННѕ ИНѕИНННННѕИНѕ

                        г.Москва, 1993 г.

ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН

              Дополнение для Borland C++ 3.1
ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН

           Новые средства Турбо ассемблера версии 3.1
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо ассемблер версии 3.1 предусматривает  следующие  новые
средства:

     1. Расширенные инструкции SETFIELD и GETFIELD.

        Когда исходное  значение  совпадает  с целевым регистром,
        инструкция SETFIELD больше не выполняет операцию  OR  над
        исходным значением. Вместо этого SETFIELD будет обеспечи-
        вать, что неустановленные поля целевого региста будут ну-
        левыми.

        Аналогично, если  вы используете при совпадении исходного
        и целевого регистра инструкцию  GETFIELD,  то  инструкция
        больше  не будет генерировать нефункциональную инструкцию
        "MOV приемник, источник".

     2. Дополнительные параметры командной строки.

        Турбо ассемблер 3.1 позволяет  теперь  задавать  дополни-
        тельные объектные форматы, используемые отдельными компо-
        новщиками. Это следущие параметры:

ЪДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Параметр   і   Значение                                    і
ГДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і   /o          і   Генерируются стандартные совместимые с TLINKі
і               і   объектные файлы   с   разрешенной поддержкойі
і               і   оверлеев.                                   і
і               і                                               і
і   /oi         і   Генерируются объектные файлы в формате, сов-і
і               і   местимом с компоновщиком IBM.               і
і               і                                               і
і   /op         і   Генерируются объектные файлы в формате, сов-і
і               і   местимом с компоновщиком Phar Lap.          і
і               і                                               і
і   /os         і   Генерируются стандартные совместимые с TLINKі
і               і   объектные файлы   с   запрещенной поддержкойі
і               і   оверлеев. Этот параметр задается по  умолча-і
і               і   нию.                                        і
АДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
     3. Новый атрибут сегмента и предупреждение о неинициализиро-
        ванном сегменте.

        Атрибут сегмента UNINIT позволяет вам выявлять  непредна-
        меренную запись инициализированных данных в неинициализи-
        рованные сегменты данных.  Использование данного атрибута
        в описании сегмента позволяет вам генерировать предупреж-
        дающее сообщение, уведомляющее об этой проблеме.

        Приведем пример сегментной директивы,  использующей новый
        атрибут:

            BSS SEGMENT PUBLIC WORD UNINIT 'BSS'

        Данная директива  будет генерировать следующее предупреж-
        дающее сообщение:

           Warning: Data or code written to uninitialized segment
           (Предупреждение: Данные или код записываются в  неини-
           циализированный сегмент)

           Для запрещения данного сообщения используйте директиву
           NOWARN UNI.  Вновь разрешить это сообщение можно с по-
           мощью директивы WARN UNI.

     4. Директивы PUSHSTATE и POPSTATE.

        Директива PUSHSTATE сохраняет текущее оперативное состоя-
        ние внутреннего стека,  имеющего глубину 16 уровней.  Ди-
        ректива PUSHSTATE особенно полезна,  если у  вас  имеется
        код в макрокоманде,  функциирующий независимо от текущего
        оперативного состояния,  но не влияющий на текущий опера-
        тивный режим.

        Сохраняемая Турбо  ассемблером информация о состоянии со-
        держит:

        - текущую версию эмуляции (например, T310);
        - выбор режима (например, IDEAL, MASM, QUIRKS, MASM51);
        - переключатели EMUL и NOEMUL;
        - выбор текущего процессора и сопроцессора;
        - переключатели MULTERRS или NOMULTERRS;
        - переключатели SMART или NOSMART;
        - текущее основание системы счисления;
        - переключатели JUMPS или NOJUMPS;
        - переключатели LOCALS или NOLOCALS;
        - текущий префикс локального символа.

        Для возврате  последнего  сохраненного состояния из стека
        используйте директиву POPSTATE.
; примеры директив PUSHSTATE и POPSTATE

ideal
model small
codeseg

jumps
locals  @@

        ; Показывает  изменение  состояние процессора,  основание
        ; чисел и режим JUMPS
        pushstate
        nojumps
        radix   2          ; Установить в двоичное основание
        p386
        jl      next1      ; После этого нет дополнительных NOPS
        mov     eax,100    ; Теперь 100 означает двоичное число
                           ; 100 или десятичное 4.
next1:
        popstate           ; Восстановить JUMPS и режим не 386.

        ; Вернуться к директиве JUMPS, не 386 и десятичному осно-
        ; ванию

        jl      next2      ; Три дополнительных NOPS для
                           ; обработки JUMPS
        xor     eax,eax    ; Теперь не режим 386!

        mov     cx,100     ; Теперь 100 означает десятичное 100

        pushstate
        MULTERRS
        mov     ax,[bp+abc
        popstate

        mov     ax,[bp+abc

        ; Показазывает  запрещение  локальной  области   действия
        ; идентификаторов
        locals
next2:
@@a:    loop @@a
next3:
@@a:    loop @@a           ; Допутимо благодаря области действия
                           ; NEXT2: и NEXT3:
        pushstate
        nolocals
next4:
@@b:    loop @@b
next5:
@@b:    loop @@b           ; Это приведет к конфликту из-за
                           ; нелокальности
        popstate

        ; Показывает изменение префикса локального идентификатора
        ; и режим MASM/IDEAL
        pushstate
        masm
        locals @$

testproc proc              ; Режим MASM для описания процедуры
         jmp    @$end

@$end:   nop
@@end:   ret
testproc endp

testproc2 proc
        jmp    @$end
@$end:  nop                ; Это не приводит к конфликту с меткой
                           ; в TESTPROC
@@end:  ret                ; Эта метка приведет к конфликту
testproc2 endp
        popstate

        ; Теперь вернемся к @@ в качестве локального  префикса  и
        ; режиму IDEAL
testproc2b proc            ; Это будет работать, так как мы снова
                           ; в режиме IDEAL
        ret
testproc2b  endp           ; а это даст ошибку.

proc    testproc3
        jmp    @$end2
@$end2: nop
@@end2: ret
endp    testproc3

proc    testproc4
        jmp    @$end2
@$end2: nop                ; Эта метка не приведет к конфликту
@@end2: ret                ; Эта метка не приведет к конфликту
                           ; с меткой в TESTPROC3
endp    testproc4
end

     5. Новые директивы процессора.

        Новые директивы  процессора добавлены для работы с платой
        486SX.

        .487 - разрешает ассемблирует инструкций  числового  про-
               цессора 487.  Данная  инструкция работает только в
               режиме MASM.

        P487 - разрешает ассемблирует инструкций  числового  про-
               цессора 487.  Данная инструкция работает как в ре-
               жиме MASM, так и в режиме Ideal.

     6. Подстановка текстовых присваиваний.

        Для улучшения совместимости с MASM в TASM 3.1 введены из-
        менения в характер постановки текстовых присваиваний. Это
        приводит к тому,  что старый код дает в TASM 3.1  ошибки,
        что можно устранить двумя способами:

        1) Используйте  директиву командной строки /UT300 для вы-
           бора обработки в стиле TASM 3.0.

        2) В начале строк,  которые вызывают ошибки в  TASM  3.1,
           но не в TASM 3.0,  явно используйте оператор текстовой
           макроподстановки %.

        Примером этого являются файлы WHEREIS.  Для WHEREIS, раз-
        мер  модели определятеся в командной строке следующим об-
        разом:

           TASM /dMDL=small iwhereis.asm

        Затем в IWHEREIS.ASM, код делает проверку, чтобы убедить-
        ся,  что определено MDL,  и, если это так, в TASM 3.0 ис-
        пользуется следующая строка кода:

           model MDL

        TASM 3.0 перед вычислением выражения автоматически  подс-
        тавляет значение MDL.  TASM 3.1 теперь требует от вас яв-
        ного указания оператора %:

           % model MDL

                    Исправления и добавления
        к "Руководству пользователя по Турбо ассемблеру"
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

                           Исправления

     На стp.  333 в Приложении D, "Утилиты," говорится, что спра-
вочное  средство Турбо ассемблера называется TASMHELP.  Вы можете
использовать TASMHELP как описывается в данном руководстве только
если установите Турбо ассемблер в каталоге, отличном от Borland C
++.  В противном случае следует использовать утилиту THELP, кото-
рая модифицирована таким образом, что может обращаться к множест-
ву справочных файлов с помощью меню.

     Утилиту THELP можно использовать следующим образом:

     1) После установки Borland C++ и Турбо  ассемблера  вызовите
        THELP в ответ на подсказку DOS.

     2) Чтобы  вывести меню доступных справочных файлоа,  нажмите
        клавиши ALT-F.

     3) Для доступа к справочной информации по  Турбо  ассемблеру
        выберите файл TASM.TAH.

                         Введение
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер фирмы Borland представляет  собой  многопро-
ходный ассемблер с разрешением опережающих ссылок,  скоростью ас-
семблирования до 48000 строк в минуту (на  компьютере  IBM  PS/2,
модель 60), совместимый с макроассемблером фирмы Microsoft MASM и
дополнительной  возможностью  использования  режима  расширенного
синтаксиса Ideal.  Независимо  от вашего опыта в программировании
вы,  несомненно,  оцените эти особенности,  а  также  ряд  других
средств,  которые  значительно  облегчают программирование на Ас-
семблере.  Среди таких средств можно кратко  упомянуть  следующие
(подробно они будут описаны позднее):

     - возможности объектно-ориентированного программирования;

     - 32-разрядная модель и поддержка кадра стека;

     - поддержка интерфейса защищенного режима DOS (DPMI) для ра-
       боты  Турбо Ассемблера в защищенном режиме под управлением
       Microsoft Windows;

     - полная поддержка процессора 80386 и i486;

     - упрощенные директивы определения сегментов;

     - улучшенное управление листингом;

     - поддержка таблиц;

     - перечислимые типы;

     - развитые инструкции работы с флагами;

     - новые средства поддержки структур;

     - быстрая операция умножения с непосредственным операндом;

     - поддержка множественных определений;

     - директива спецификации VERSION;

     - режим Quirks для эмуляции MASM;

     - полная отладка на уровне исходного текста с помощью  Турбо
       отладчика;

     - встроенная утилита генерации перекрестных ссылок (TCREF);

     - файлы конфигурации и командные файлы;

     - утилита-преобразователь файлов .h в .ash (включаемые  фай-
       лы).

     Турбо Ассемблер является мощным  ассемблером,  работающим  с
командной строкой, который воспринимает ваши исходные файлы (фай-
лы с расширением .ASM) и создает из них объектные модули (файлы с
расширением  .OBJ).  После  этого вы можете использовать програм-
му-компоновщик фирмы Borland TLINK.EXE, отличающуюся высокой ско-
ростью компоновки,  для компоновки полученных объектных модулей и
создания выполняемых файлов (файлов с расширением .EXE).

     Требования к программному и аппаратному обеспечению
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер работает на компьютерах  семейства  IBM  PC,
включая  модели XT, AT и PS/2, а также на полностью совместимых с
ними компьютерах.  Для работы Турбо Ассемблера требуется операци-
онная система MS-DOS (версии 2.0 или более поздняя)  и  не  менее
256К оперативной памяти.

     Турбо  Ассемблер  генерирует  инструкции  процессоров  8086,
80186, 80286, 80386 и i486, а также инструкции с плавающей точкой
для арифметических сопроцессоров 8087,  80287 и 80387. (Подробнее
об инструкциях процессором семейства 80х86/80х87 рассказывается в
книгах фирмы Intel.)

                      Поддержка DPMI
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер поддерживает спецификацию  Интерфейса  защи-
щенного  режима DOS (DOS Protected Mode Interface - DPMI). Будучи
разработанным комитетом ведущих компаний-производителей программ-
ного и аппаратного обеспечения (включая Borland), DPMI определяет
стандартный  интерфейс,   полностью   использующий   преимущества
средств защищенного режима процессоров 80286, 386 и i486.

     По мере увеличения числа компьютеров на базе процессоров 386
и i486 растет и число программных продуктов, использующих возмож-
ности этих процессоров. Защищенный и виртуальный 8086 режимы дан-
ных процессоров означают изменение самого вычислительного процес-
са. Теперь  мы  можем использовать многозадачный режим и средства
расширенной памяти. Раньше организация работы прикладной програм-
мы,  использующей  расширенную  память,  в многозадачном режиме с
другим  программным  обеспечением  представляла  собой  проблему.
Стандарт DPMI решает эту проблему.  Прикладные программы, исполь-
зующие расширенную память,  разработанные в стандарте DPMI, будут
надежно работать в многозадачных системах.

     В настоящее   время  Турбо  Ассемблер  использует  сервисные
средства DPMI,  предлагаемые Microsoft Windows.  Турбо  Ассемблер
может работать в операционной среде,  использующей средства DPMI.
Если вы решите перейти на новую операционную среду, в которой эти
сервисные средства доступны, то ваши затраты на программное обес-
печение себя оправдают.

          Примечание: Стандарт DPMI поддерживает версия Турбо Ас-
     семблера TASMX.EXE.  Подробнее о TASMX.EXE рассказывается  в
     Главе 2.

                    О данной документации
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Описание Турбо Ассемблера поставляется в виде  двух пособий:
"Руководства пользователя  по  Турбо Ассемблеру" (данный текст) и
"Краткого справочного руководства по Турбо Ассемблеру".  В "Руко-
водстве пользователя" даются основные инструкции по использованию
Турбо Ассемблера,  организации его интерфейса с другими языками и
описываются предопределенные операции,  идентификаторы и директи-
вы, используемые Турбо Ассемблером. "Краткое справочное руководс-
тво" позволяет  быстро находить информацию по инструкциям процес-
сора и сопроцессора и директивам.

     Рассмотрим содержание "Руководства пользователя" более  под-
робно.

                  Руководство пользователя
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Часть 1: "Использование Турбо Ассемблера":

     Глава 1:  "Начало работы в Турбо Ассемблере" сообщает о том,
что  необходимо  сделать  для  установки Турбо Ассемблера в вашей
системе.

     Глава 2:  "Использование директив и параметров"  приводит  в
алфавитном порядке подробную информацию обо всех директивах Турбо
Ассемблера,  и показывает, как с их помощью можно управлять рабо-
той Турбо Ассемблера.

     Глава 3: "Общие принципы программирования" описывает отличие
режимов Ideal и MASM,  а также рассказывает о том,  как использо-
вать предопределенные идентификаторы, символы комментариев и т.д.

     Глава 4: "Объектно-ориентированное программирование" расска-
зывает как можно в языке Ассемблера использовать методы объектно-
ориентированного программирования.

     В Главе  5 "Использование выражений и значений идентификато-
ров" описывается вычисление и определение выражений и операций.

     Глава 6 "Выбор директив процессора и идентификаторов"  расс-
казывает, как генерировать код для конкретных процессоров.

     Глава 7 "Использование моделей памяти программ  и  сегмента-
ции" сообщает   о  моделях  программ,  генерации  идентификаторов
(символических имен), упрощенных определений сегментов и о поряд-
ке сегментов.

     В Главе 8: "Определение типов данных" поясняется как опреде-
лять структуры,  объединения, таблицы, встроенные записи и объек-
ты.

     В Главе 9:  "Установка и использование счетчика адреса" опи-
сывается как и для чего желательно использовать счетчик адреса, а
также об определении таблиц.

     В Главе  10:  "Описание  процедур"  рассказывается о том как
можно использовать различные типы процедур,  а также как  опреде-
лять и использовать аргументы и локальные переменные.

     В Главе  11:  "Управление областью действия идентификаторов"
обсуждается как можно ограничивать или расширять области, в кото-
рой идентификатор имеет конкретное значение.

     В Главе 12:  "Определение данных" описываются простые дирек-
тивы  определения  данных,  рассказывается о создании экземпляров
структур,  объединений, записей, перечислимых типов данных и объ-
ектов.

     В Главе  13 "Расширенные инструкции" описываются расширенные
инструкции Турбо Ассемблера.

     Глава 14 "Использование макрокоманд" рассказывает о  том как
можно использовать в исходном коде макрокоманды.

     В Главе 15 "Использование условных директив" обсуждаются ди-
рективы, которые позволяет реализовать условное выполнение кода.

     Глава 16:  "Интерфейс с компоновщиком" описывает  как  можно
при компоновке  кода включать в него библиотеки и описывать иден-
тификаторы как общедоступные.

     Глава 17 "Генерация листинга" рассказывает о директивах  уп-
равления листингом Турбо Ассемблера и их использовании.

     Глава 18:  "Интерфейс Турбо Ассемблера с Borland C++" описы-
вает, как использовать язык Ассемблера совместно с языком высоко-
го уровня Borland C++.

     Глава 19:  "Интерфейс Турбо Ассемблера с Турбо Паскалем" со-
общает вам, как связывать программу на Ассемблере с программой на
Турбо Паскале; здесь также приводятся примеры программ.

     Приложение A: "Примеры программ" приводит примеры различного
типа программных структур.

     Приложение В:  "Сводный синтаксис Турбо Ассемблера" содержит
краткое изложение синтаксиса Турбо Ассемблера" иллюстрирует выра-
жения Турбо Ассемблера (для режимов MASM и Ideal)  в  модифициро-
ванной записи Бэкуса-Наура (BNF).

     Приложение С:  "Вопросы совместимости" описывает отличия ре-
жима Турбо Ассемблера MASM и макроассемблера MASM.

     Приложение D: "Утилиты" описывает новую утилиту-преобразова-
тель файлов .h в .ash,  поставляемую с данным пакетом.  Здесь со-
держится информация об утилитах MAKE,  TLINK,  TLIB  и  THELP,  а
также информация  о программах GREP,  TCREF и OBJXREF находится в
файлах на дистрибутивных дисках.

     Приложение D: "Сообщения об ошибках" описывает все сообщения
об ошибках,  которые могут быть сгенерированы Турбо  Ассемблером:
информационные сообщения,  сообщения о фатальных ошибках, сообще-
ния уровня предупреждения и сообщения об ошибках.

                 Соглашения по обозначениям
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Когда мы  говорим о компьютерах IBM PC и совместимых с ними,
то речь идет о любых компьютерах,  в которых используются процес-
соры 8088,  8086,  80186,  80286,  386 и i486 (все эти процессоры
обозначаются, как 80х86).  Когда вы встречаете термин PC-DOS  или
MS-DOS, то речь идет о версии операционной системы 2.0 и старше.
     В данном руководстве используются следующие соглашения:

ЪДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і   Обозначение і   Описание обозначения                        і
ГДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і               і Столбец из точек перед строками, где описыва- і
і     .         і ется синтаксис или приводится пример програм- і
і     .         і мы,  говорит  о  том,  что фрагмент программы і
і     .         і опущен.                                       і
і               і                                               і
і образец       і Слова, указанные  в примерах строчными буква- і
і               і ми, показывают,  что  вместо  них должны быть і
і               і подставлены  значения.  Например,  ниже  при- і
і               і веден синтаксис оператора ОFFSET:             і
і               і                                               і
і               і       OFFSET выражение                        і
і               і                                               і
і               і Он показывает,  что  за оператором OFFSET мо- і
і               і жет  следовать  любое  выражение.  При записи і
і               і исходного кода в соответствии с  этим синтак- і
і               і сисом вы можете записать:                     і
і               і                                               і
і               і      OFFSET here+6                            і
і               і                                               і
і               і где  here+6 является выражением.              і
і               і                                               і
і [ необ_элем ] і В двойные квадратные  скобки  заключается не- і
і               і обязательный  синтаксический элемент.  Напри- і
і               і мер, синтаксис индексного  оператора  показан і
і               і следующим образом:                            і
і               і                                               і
і               і  [ выраж_1 ] выраж_2                          і
і               і                                               і
і               і Это указывает на то,  что  "выраж_1" является і
і               і необязательным,  поскольку  оно  заключено  в і
і               і квадратные скобки. Однако выражение "выраж_2" і
і               і является обязательным.                        і
і               і                                               і
і{выбор1івыбор2}і Фигурные скобки  и  вертикальные  разделители і
і               і указывают на необходимость выбора между двумя і
і               і или более элементами. Варианты  выбора заклю- і
і               і чаются в фигурные скобки и разделяются верти- і
і               і кальной чертой. Вы должны выбрать один из ва- і
і               і риантов.                                      і
і               і                                               і
і               і Например, необязательный параметр /W (уровень і
і               і предупреждающих  сообщений  об  ошибке) имеет і
і               і следующий синтаксис:                          і
і               і                                               і
і               і           /W{0і1і2}                           і
і               і                                               і
і               і Вы можете ввести /W0, /W1 или /W2, указав та- і
і               і ким образом желаемый уровень  предупреждений. і
і               і Однако указывать /W3 не допускается, посколь- і
і               і ку 3 не содержится ни  в  одном  из вариантов і
і               і выбора, которые указаны в фигурных скобках.   і
і               і                                               і
іПовторяющиеся  і Три точки, следующие за элементами, показыва- і
і элементы...   і ют, что можно в таком  же виде ввести большее і
і               і количество элементов.  Ниже, например, приве- і
і               і ден синтаксис директивы PUBLIC:               і
і               і                                               і
і               і         PUBLIC имя[, имя ]...                 і
і               і                                               і
і               і Точки  за  вторым  элементом "имя" указывают, і
і               і что вы можете  ввести  столько  имен, сколько і
і               і захотите, пока каждому из них будет предшест- і
і               і вовать запятая.  Однако, поскольку первое имя і
і               і не заключено  в  квадратные скобки, вы должны і
і               і ввести по крайней мере одно имя.              і
і               і                                               і
іОпределяемые   і В кавычки  заключаются  определяемые в тексте і
і термины и     і термины.  Например,  термин  "промежуточный", і
і "подсказки"   і если он определяется в первый раз, заключает- і
і               і ся в кавычки.                                 і
АДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

          Как обратиться за помощью к фирме Borland
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Фирма Borland предлагает вам множество услуг, которые позво-
лят ответить на вопросы о данном программном продукте. Убедитесь,
что  вы  послали  регистрационную  карту.  Для зарегистрированных
пользователей обеспечивается техническое сопровождение, кроме то-
го,  они могут получать информацию обо всех изменениях и дополне-
ниях к продукту.

                    Ресурсы вашего пакета
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Данный пакет содержит много ресурсов,  которые могут вам по-
мочь:

     - В руководстве  дана информация по каждому аспекту програм-
       мы. Используйте его, как основной источник информации.

     - Ответы на общие вопросы,  обзор новых средств,  информация
       об установке содержатся в файле README,  который находится
       в основном каталоге.

                  Возможности фирмы Borland
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Службы технического  сопровождения  фирмы  Borland публикуют
техническую информацию по множеству тем.  Там вы можете  получить
ответы на возникшие вопросы.

     TechFax (8000-822-4269)  - это 24-часовая автоматизированная
служба, позволяющая свободно получить техническую  информацию  по
факсу. Вы можете запросить до трех документов за один вызов.

     408-439-9096 (модем)  - пересылка файлов (File DownLoad BBS,
2500 бод).  Через модем вы можете получать образцы файлов,  прик-
ладных программ  и техническую информацию.  Специальной установки
не требуется.

     Подписчики информационных услуг CompuServe,  GEnie  или  BIX
могут получать  техническую  поддержку  с помощью модема.  Чтобы,
имея доступ к информационной службе, связаться с Borland, исполь-
зуйте следующую таблицу:

     Оперативные информационные услуги
     ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     Служба               Команда
     ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     CompuServe           Go BORLAND
     BIX                  JOIN BORLAND
     GEnie                BORLAND
     ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Передачу электронных сообщений адресуйте All или Sysop.  Се-
рийный номер вам указывать не нужно: если сообщения не посылаются
по частной системе пересылки, они общедоступны. Включите в вопрос
максимум информации.  Обслуживающий персонал ответит на сообщение
в течении одного рабочего дня.

     408-438-5300 - по этому телефону можно обратиться в наш  от-
дел технического обслуживания по рабочим дням с 6 утра до 5 вече-
ра. Звоните пожалуйста по телефону, который находится недалеко от
компьютера с работающей программой.  Прежде чем позвонить, подго-
товьте следующую информацию:

     1. Название продукта и  серийный  номер  вашей  оригинальной
        дистрибутивной дискеты.  Этот номер обязателен,  иначе мы
        не сможем обслужить вашу заявку.

     2. Марку  и модель компьютера,  а также любого используемого
        вами дополнительного аппаратного обеспечения.

     3. Название и номер версии операционной системы. (Номер вер-
        сии можно определить,  введя по приглашению  DOS  команду
        VER).

     4. Содержимое  вашего  файла AUTOEXEC.BAT и содержимое файла
        CONFIG.SYS (в корневом каталоге (\) на  загрузочном диске
        компьютера.

     5. Телефон,  по  которому  с  вами можно связаться в рабочее
        время.

     6. Если звонок связан с какой-то проблемой, какие шаги нужно
        выполнить, чтобы возникла эта проблема.

     По телефону  408-438-5300 с 7 до 17 часов вы можете получить
ответы на нетехнические вопросы,  включая цены,  изменения и т.д.
(служба покупателя).

           ЧАСТЬ 1. ИСПОЛЬЗОВАНИЕ ТУРБО АССЕМБЛЕРА
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Далее следует содержимое первой части.

         Глава 1. Начало работы на Турбо Ассемблере
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Если вы никогда ранее не программировали на языке  Ассембле-
ра,  то начните с данной главы. Возможно вам приходилось слышать,
что программирование на Ассемблере - это дело  темное,  доступное
только посвященным и мудрецам. Не верьте этому. Язык Ассемблера -
это не более чем человеческая форма языка  самого  компьютера,  а
он,  как и можно было предположить, в высшей степени логичен. Как
вы можете также догадаться, язык Ассемблера -  это  очень  мощный
язык. Фактически, программирование на Ассемблере представляет со-
бой единственный способ  реализации  всего  спектра  возможностей
процессоров  серии  80х86  фирмы Intel, являющихся "сердцем" всех
компьютеров семейства IBM PC  и совместимых с ними компьютеров.

     Вы можете писать программы целиком на языке Ассемблера  или,
если  захотите,  использовать язык Ассемблера в программах, напи-
санных на Турбо С++,  Турбо Паскале и других языках. В любом слу-
чае с помощью языка Ассемблера вы сможете разрабатывать  компакт-
ные  и быстрые программы.  Наряду со скоростью большое значение в
программе на языке Ассемблера имеет также  возможность управления
всеми аспектами работы компьютера, до последнего такта системного
таймера.

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

     Разумеется, мы не сможем при  помощи  этих  нескольких  глав
сделать вас крупным специалистом по программированию на языке Ас-
семблера;  мы просто дадим вам введение в язык Ассемблера и помо-
жем написать первые программы.  Мы очень надеемся, что у вас есть
хотя бы одна из множества замечательных книг, полностью посвящен-
ных  программированию  на  языке ассемблера и архитектуре PC (см.
ссылки на литературу в конце данной книги).  Кроме того, полезные
справочные материалы содержатся в "Техническом справочнике по IBM
DOS", "Техническом справочнике по интерфейсу BIOS" и "Техническом
справочнике по персональным компьютерам XT";  в этих руководствах
документируется интерфейс при программировании на языке ассембле-
ра  с  программным и аппаратным обеспечением системы персональных
компьютеров IBM.

     Вы можете следовать данному руководству поэтапно,  вводя все
примеры программ по мере их изучения, либо можете распаковать на-
ходящийся на диске файл с примерами (во время установки Турбо Ас-
семблера) и иметь все эти программы под рукой. (Независимо от ва-
шего решения,  имена программ приводятся  для  удобства  в  самом
начале примеров этих программ).

          Установка Турбо Ассемблера в системе
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Перед тем, как познакомиться с  программированием  на  Турбо
Ассемблере,  вам нужно сделать следующее. Возьмите дистрибутивные
диски Турбо Ассемблера и сделайте для каждого из них  (с  помощью
утилиты DOS) рабочую копию. После этого исходные (дистрибутивные)
диски уберите в надежное место.

     Если собираетесь использовать Турбо  Ассемблер  вместо  MASM
(макроассемблер фирмы Microsoft),  прочитайте Главу 2 и посмотри-
те, в чем поведение Турбо Ассемблера отличается от MASM.

     На диске INSTALL находится  программа  INSTALL.EXE,  которая
поможет  вам установить Турбо Ассемблер версии 3.0 в вашей систе-
ме. При установке следует учесть два параметра:

     1. Hard Disk Users (пользователям системы с жестким диском):
        этот параметр позволяет выбрать  подкаталоги,  в  которые
        будут загружены файлы.

     2. Floppy Disk Users (пользователям системы с гибкими диска-
        ми): этот параметр установит файлы, необходимые для рабо-
        ты Турбо Ассемблера,  в системе с двумя  дисководами  для
        гибких дисков. До начала работы подготовьте четыре отфор-
        матированных диска.
     Для начала  установки  перейдите  в  каталог  с   программой
INSTALL и наберите команду:

      INSTALL

     Вам будут даны инструкции относительно каждого приглашения в
рамке в нижней части экрана установки.

     При запуске INSTALL в системе портативного компьютера  или в
любой другой  системе  с  жидкокристаллическим  дисплеем   запуск
INSTALL следует выполнять с параметром /b,  который позволяет пе-
ревести систему в черно-белый режим:

      INSTALL /b

                Текстовые справочные файлы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     В состав Турбо Ассемблера входят несколько  справочных  фай-
лов: FILELIST.DOC.  README,  HELPME!.TSM, MANUAL.TSM, H2ASH.TSM и
TCREF.TSM. Первые два файла содержатся  на  установочной  дискете
"Installation Disk" и копируются в основной каталог языка. Другие
файлы находятся в подкаталоге DOC.

                       Файл README
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

       Перед тем,  как начать работу с Турбо Ассемблером,  не за-
будьте прочесть файл README. В нем находится последняя информация
о программе, а также исправления и/или дополнения к руководствам.
Там вы также найдете полный список всех поставляемых на дистрибу-
тивных дисках файлов и их описания. В ответ на подсказку DOS вве-
дите:

     README

     Вы можете также использовать  программу  README  для  чтения
файлов документации (с расширением .DOC)

                  Файл HELPME!.TSM
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

   На установочной дискете содержится также файл  HELPME!.TSM.  В
нем можно найти ответы на вопросы, с которыми обычно сталкиваются
пользователи. Он содержит также вопросы и ответы, касающиеся раз-
личных режимов Турбо Ассемблера.

                  Файл H2ASH.TSM
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Данный файл содержит подробную информацию об  утилите-преоб-
разователе файлов .h в .ahs.  Краткое описание этой утилиты можно
найти в Приложении D.

                  Файл TCREF.TSM
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В данном файле описывается использование для создании перек-
рестных ссылок идентфикаторов и идентификации использующих их мо-
дулей утилиты TCREF.

                  Оперативный справочник
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Оперативную справочную  информацию по Турбо Ассемблеру можно
получить с помощью резидентной с памяти справочной программы-ути-
литы TASMHELP. Например, если вы используете Турбо отладчик, мож-
но загрузить TASMHELP,  затем загрузить Турбо отладчик и получать
во время  отладки справочную информацию по Турбо Ассемблеру. Либо
вы можете использовать TASMHELP для поиска  информации  по  языку
при написании исходного кода.

     Так как  TASMHELP  - это резидентная в памяти программа,  ее
нужно загрузить в память перед запуском редактора.  Чтобы  загру-
зить TASMHELP, в ответ на подсказку командной строки DOS C: набе-
рите:

     TASMHELP

     После этого вы можете запустить редактор,  как обычно. Нахо-
дясь в редакторе, нажмите для вызова TASMHELP оперативную клавишу
- клавишу 5 на дополнительной клавиатуре (справа).  Если при этом
курсор у вас находится на пустой строке, TASMHELP выведет таблицу
справочных экранов.  Для перемещения курсора по  ключевым  словам
используйте клавишу Tab и нажмите клавишу Enter.

     Программа TASMHELP работает точно также, как справочная ути-
лита компилятора THELP.

     Подробнее о TASMHELP и ее параметрах командной  строки можно
узнать в  документации  по компилятору,  где описывается работа с
THELP.

          Ваша первая программа на Турбо Ассемблере
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В программировании первой  программой  традиционно  является
программа,  выводящая на экран сообщение "Привет!". Не будет иск-
лючением и наша программа, поскольку это является хорошей отправ-
ной точкой.

     Войдите в текстовый редактор (один из тех редакторов,  кото-
рые  формируют  файлы  в  коде  ASCII) и введите следующие строки
программы под названием HELLO.ASM:

     .MODEL SMALL
     .STACK 100h
     .DATA
Message  DB 'Привет!',13,10,'$'
     .CODE
     mov    ax,@Data
     mov    dx,ax                ; установить регистр DS таким
                                 ; образом, чтобы он указывал
                                 ; на сегмент данных
     mov    ah,9                 ; функция DOS вывода строки
     mov    dx,OFFSET Message    ; ссылка на сообщение "Привет!"
     int    21h                  ; вывести "Привет!" на экран
     mov    ah,4ch               ; функция DOS завершения
                                 ; программы
     int    21h                  ; завершить программу
     END

     После того, как вы введете эту программу,  сохраните  ее  на
диске.

     Если вы знакомы с языками Си, С++ или Паскаль, вам может по-
казаться,  что эта версия  программы  несколько  длинновата.  Это
действительно  так,  программы  на Ассемблере длиннее,  поскольку
каждая инструкция Ассемблера выполняет меньше функций,  чем  инс-
трукция Паскаля,  С++ или языка Си. С другой стороны, вам предос-
тавляется свобода,  и вы можете комбинировать эти инструкции  Ас-
семблера так, как захотите. Это означает, что в отличие от языков
Си и Паскаль,  Ассемблер позволяет вам программировать  компьютер
таким образом,  что он будет делать все,  на что способен.  Часто
это стоит нескольких дополнительных строк.

           Ассемблирование вашей первой программы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     После того, как вы сохранили файл HELLO.ASM, вы захотите за-
пустить  программу.  Однако,  перед тем, как вы сможете ее запус-
тить, потребуется преобразовать программу в выполняемый  вид. Как
показано на Рис. 1.1, где изображен полный цикл создания програм-
мы (редактирование,  ассемблирование,  компоновка и  выполнение),
это  потребует двух дополнительных шагов - ассемблирования и ком-
поновки.

     На этапе ассемблирования ваш исходный код (текст  программы)
превращается  в промежуточную форму, которая называется объектным
модулем, а на этапе компоновки один или несколько модулей  комби-
нируются в выполняемую программу. Ассемблирование и компоновку вы
можете выполнять с помощью командной строки.

     Для ассемблирования файла HELLO.ASM наберите:

     TASM hello

                          Создание новой программы
                                     і
    ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДі
    і                                і
    і                          Редактирование
    і                                і
    і                                
    і          ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
    і          і     Исходный файл Ассемблера HELLO.ASM       і
    і          АДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДЩ
    і                                і
    і                         Ассемблирование
    і                                і
    і                                
    і          ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
    і          і          Объектный файл HELLO.OBJ           і
    і          АДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДЩ
    і                                і
    і                            Компоновка
    і                                і
    і                                
    і          ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
    і          і         Выполняемый файл HELLO.EXE          і
    і          АДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДЩ
    і                                і
    і                            Выполнение
    і   ЪДДДДДДДДДДДДДДДДДДДДДД·     і
    АДДДґ Если нужны изменения єДДДДЩ
        АДДДДДДДДДДДДДДДДДДДДДДЅ

     Рис. 1.1 Редактирование, ассемблирование, компоновка  и  вы-
полнение.

и нажмите клавишу Enter. Если  вы  не  задали  другое  имя,  файл
HELLO.ASM  будет  ассемблирован  в  файл HELLO.OBJ. (Заметим, что
расширение имени файла вводить не требуется. Турбо Ассемблер под-
разумевает в этом случае, что файл имеет расширение .ASM.) На эк-
ране вы увидите следующее:

   Turbo Assembler Version 3.0 Copyright (C) 1988,1991   (1)
                                    by Borland International Inc.
   Assembling file: HELLO.ASM       (2)
   Error messages: None             (3)
   Warning messages: None           (4)
   Passes: 1                        (5)
   Remaining memory: 266K           (6)

     1 - Турбо  Ассемблер,  версия  3.0;  авторские  права  фирмы
Borland, 1991 г.; 2 - ассемблирован файл HELLO.ASM; 3 - сообщения
об ошибках:  нет;  4 - предупреждающие сообщения:  нет; 5 - число
проходов: 1; 6 - остается памяти: 266К

     Если вы введете файл HELLO.ASM в точности так, как показано,
то вы не получите никаких предупреждающих сообщений или сообщений
об ошибках. Если вы получаете такие сообщения, они появляются  на
экране  наряду  с номерами строк, указывающими строки, где содер-
жатся ошибки. При получении сообщений об ошибках проверьте исход-
ный код (текст) программы и убедитесь, что он выглядит точно так,
как исходный код в нашем примере,  а  затем  снова  ассемблируйте
программу.

                    Компоновка программы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     После ассемблирования файла HELLO.ASM вы продвинулись только
на  один шаг в процессе создания программы. Теперь, если вы ском-
понуете только что полученный объектный код в выполняемый вид, вы
сможете запустить программу.

     Для  компоновки  программы  используется  программа   TLINK,
представляющая собой поставляемый вместе с Турбо Ассемблером ком-
поновщик. Введите командную строку:

     TLINK HELLO

     Здесь опять не требуется  вводить  расширение  имени  файла.
Компоновщик TLINK по умолчанию предполагает, что этим расширением
является  расширение  .OBJ.  Когда  компоновка  завершится (самое
большее через несколько секунд),  компоновщик автоматически прис-
воит  файлу  с расширением .EXE имя,  совпадающее с именем вашего
объектного файла (если вы не определили другое имя). При успешной
компоновке на экране появляется сообщение:

     Turbo Linker Version 3.0 Copyright (c) 1988, 1991 by Borland
     International Inc.

     В процессе компоновки  могут  возникнуть  ошибки  (в  данной
программе  это маловероятно). Если вы получили сообщения об ошиб-
ках компоновки (они выводятся на экран),  измените  исходный  код
программы так, чтобы он в точности соответствовал тексту програм-
мы в приведенном выше примере, а затем снова выполните  ассембли-
рование и компоновку.

                Запуск вашей первой программы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Теперь программу можно запустить на выполнение. Для этого  в
ответ на подсказку операционной системы DOS введите hello. На эк-
ран выведется сообщение:

     Привет!

     Пока это все.  Вы только что создали и выполнили свою первую
программу на Ассемблере!.

                       Что происходит?
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Теперь, когда вы получили и выполнили  программу  HELLO.ASM,
давайте  вернемся  назад  и рассмотрим подробно, что происходит с
момента ввода текста программы до ее выполнения.

     Когда вы ассемблируете файл HELLO.ASM, Турбо Ассемблер прев-
ращает  текст  инструкций в этом файле в их двоичный эквивалент в
объектном файле HELLO.OBJ. Этот файл является промежуточным  фай-
лом (промежуточным звеном в процессе перехода от текстового к вы-
полняемому файлу). Файл HELLO.OBJ содержит всю информацию,  необ-
ходимую для создания выполняемого кода из инструкций, содержащих-
ся в файле HELLO.ASM, но она записана в виде,  который  позволяет
комбинировать ее  с другими объектными файлами для создания одной
программы.

     При компоновке файла HELLO.OBJ TLINK преобразует его  в  вы-
полняемый  файл  HELLO.EXE,  который вы запускаете, введя hello в
ответ на подсказку DOS.

     Теперь введите:

     dir hello.*

При этом будет выведен список файлов HELLO на  диске.  Это  будут
файлы HELLO.ASM, HELLO.OBJ, HELLO.EXE и HELLO.MAP.

   Модификация вашей первой программы на Турбо Ассемблере
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Теперь снова войдем в редактор и модифицируем программу  та-
ким  образом,  чтобы  она  могла  воспринимать какие-то данные из
внешней среды (этой "внешней средой" будете вы, а вводимые данные
будут набираться на клавиатуре). Измените программу следующим об-
разом:

        .MODEL SMALL
        .STACK 100h
        .DATA
     TimePrompt DB 'Это время после полудня? (ДА/НЕТ) - [Y/N]$'
     GoodMorningMessage LABEL BYTE
                DB 13,10,'Доброе утро!',13,10,'$'
     GoodAfternoonMessage LABEL BYTE
                DB 13,10,'Здравствуйте!',13.10,'$'
        .CODE
        mov    ax,@Data
        mov    dx,ax             ; установить регистр DS таким
                                 ; образом, чтобы он указывал
                                 ; на сегмент данных
        mov    dx,OFFSET TimePrompt ; ссылка на сообщение-запрос
        mov    ah,9              ; функция DOS вывода строки
        int    21h               ; получить ответ из одного
                                 ; символа
        cmp    al,'Y'            ; указано время после полудня
                                 ; (прописная буква Y)
        jz     IsAfternoon       ; да, время указано после
                                 ; полудня
        cmp    al,'y'            ; указано время после полудня
                                 ; (строчная буква y)
        jnz    IsMorning         ; нет, время указано до
                                 ; полудня
     IsAfternoon:
        mov    dx,OFFSET GoodAfternoonMessage ; указывает на
                                 ; приветствие "Здравствуйте"
        jmp    DisplayGreeting
     IsMorning:
        mov    dx,OFFSET GoodMorningMessage ; указывает на
                                 ; приветствие "Доброе утро"
     DisplayGreeting:
        mov    ah,9              ; функция DOS вывода сообщения
        int    21h               ; вывести соответствующее
                                 ; сообщение
        mov    ah,4ch            ; функция DOS завершения
                                 ; программы
        int    21h               ; завершить программу
        END

     Таким образом вы добавили в программу два очень важных новых
средства:  возможность  ввода  и  принятие решений. Эта программа
запрашивает у вас, является ли вводимое время временем после  по-
лудня,  воспринимая  ответ (один символ) с клавиатуры. Если таким
ответом будет буква Y в верхнем или нижнем регистре (что означает
ответ ДА), то программа выводит сообщение "Здравствуйте!", в про-
тивном случае выводится сообщение "Доброе утро!". В данной  прог-
рамме  имеются  все основные элементы полезной программы: ввод из
информации внешней среды, обработка данных и принятие решения.

     Сохраните эту  модифицированную  программу  на диске.  После
этого заново ассемблируйте и скомпонуйте программу,  как в преды-
дущем примере.  Запустите ее снова,  введя hello в ответ на подс-
казку DOS. Выведется сообщение:

     Это время после полудня? (ДА/НЕТ) - [Y/N]

     Курсор будет мерцать у последнего символа в  ожидании  ввода
ответа. Нажмите Y. Программа ответит:

     Здравствуйте!

     Таким образом HELLO.ASM стала теперь интерактивной  програм-
мой с принятием решений.

     В ходе ассемблирования вы, конечно, получите различные сооб-
щения об ошибках из-за неправильного набора программы и ошибках в
синтаксисе. Турбо Ассемблер перехватывает такие ошибки, сообщая о
них. Выводимые сообщения об ошибках разбиваются на две категории:
предупреждения и ошибки. Если Турбо Ассемблер обнаруживает что-то
подозрительное,  но необязательно неверное, он выводит предупреж-
дающее сообщение.  Иногда предупреждающие сообщения можно игнори-
ровать,  но всегда лучше их проверить и убедиться в том,  что  вы
понимаете  суть  проблемы.  При обнаружении чего-либо явно непра-
вильного в вашей программе, что делает невозможным завершение ас-
семблирования и  формирование  объектного файла,  Турбо Ассемблер
выводит сообщение об ошибке.

     Другими словами, предупреждающие сообщения не свидетельству-
ют о критических ошибках,  в то время как ошибки, о которых гово-
риться в сообщениях об ошибках,  должны быть исправлены перед за-
пуском программы. В Приложении E содержится перечень сообщений об
ошибках и предупреждающих сообщений.

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

     Чтобы получить распечатку программы (вывести ее на  устройс-
тво печати),  обратитесь к руководству по редактору текстов.  Ис-
ходные файлы Турбо Ассемблера представляют собой обычные  тексто-
вые  файлы  в  коде  ASCII  (американский  стандартный код обмена
информацией),  поэтому вы можете также напечатать исходный  текст
программы на Ассемблере с помощью команды PRINT, введя ее в ответ
на подсказку операционной системы DOS.

            Вывод информации на устройство печати
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Устройство печати (принтер) - это очень полезное устройство.
Вам может не только потребоваться распечатать текст программы, но
и передать на  принтер  выводимую  информацию.  Следующая  версия
программы выводит информацию вместо экрана на принтер:

        .MODEL SMALL
        .STACK 100h
        .DATA
     Message  DB 'Привет!',13,10,'$'
     Message_Length EQO $ - Message
        .CODE
        mov    ax,@Data
        mov    dx,ax                ; установить регистр DS таким
                                    ; образом, чтобы он указывал
        mov    ah,40h               ; функция DOS вывода строки
                                    ; на устройство
        mov    bx,4                 ; описатель принтера
        mov    cx,Message_Length    ; число печатаемых символов
        mov    dx,OFFSET Message    ; ссылка на "Привет!"
        int    21h                  ; вывести "Привет!" принтер
        mov    ah,4ch               ; функция DOS завершения
                                    ; программы
        int    21h                  ; завершить программу
        END

     В данной версии программы функция DOS вывода строки на экран
заменена на функцию DOS, которая передает информацию на выбранное
устройство или в файл, в данном случае - на  принтер.  Введите  и
запустите  программу.  Посмотрите, как она напечатает на принтере
слово "Привет!". (Перед запуском программы не забудьте ее  сохра-
нить при завершении работы в редакторе.  При этом программа будет
сохранена в файле HELLO.ASM,  а предыдущая версия программы будет
потеряна.)

     Вы можете модифицировать эту программу таким образом,  чтобы
она  снова  посылала выходные данные на экран, а не на устройство
печати, заменив просто строку:

        mov   bx,4     ; описатель принтера

на строку:

        mov   bx,1     ; описатель стандартного вывода

     Сделайте такое изменение, а затем снова выполните перекомпи-
ляцию  и  перекомпоновку  программы  перед  ее запуском. Запустив
программу, вы увидите, что сообщение появится на экране,  а  пос-
ледним символом будет графический символ перевода формата (кружок
с крестиком внизу - "зеркальце Венеры").  Этот  символ  программа
передает  на  принтер,  чтобы вынудить его после вывода сообщения
выполнить перевод страницы,  поскольку на экране страниц нет,  он
ничего не знает о переводе формата и просто выводит на экран сим-
вол из набора символов компьютера РС.

          Ваша вторая программа на Турбо Ассемблере
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Теперь вы готовы к тому, чтобы ввести и запустить программу,
которая действительно что-то делает. Вернитесь в текстовый редак-
тор и введите следующую программу REVERSE.ASM:

       .MODEL SMALL
       .STACK 100h
       .DATA
    MAXIMUM_STRING_LENGTH  EQU  1000
    StringToReverse        DB   MAXIMUM_STRING_LENGTH  DUP (?)
    ReverseString          DB   MAXIMUM_STRING_LENGTH  DUP (?)
       .CODE
       mov    ax,@Data
       mov    dx,ax             ; установить регистр DS таким
                                ; образом, чтобы он указывал
       mov    ah,3fh            ; функция DOS чтения ввода
       mov    bx,0              ; описатель стандартного ввода
       mov    cx,MAXIMUM_STRING_LENGTH ; считать до максималь-
                                ; ного числа символов
       mov    dx,OFFSET StringToReverse ; сохранить строку
       int    21h               ; получить строку
       and    ax,ax             ; были считаны символы?
       jz     Done              ; нет, конец
       mov    cx,ax             ; поместить длину строки в
                                ; регистр СХ, который можно
                                ; использовать, как счетчик
       push   cx                ; сохранить в стеке длину
                                ; строки
       mov    bx,OFFSET StringToReverse
       mov    si,OFFSET ReverseString
       add    si,cx
       dec    si                ; указывает на конец буфера
                                ; строки
    ReverseLoop:
       mov    al,[bx]           ; получить следующий символ
       mov    [si],al           ; сохранить символы в
                                ; обратном порядке
       inc    bx                ; указатель на следующий
                                ; символ
       dec    si                ; указатель на предыдущую
                                ; ячейку buffer
       loop   ReverseLoop       ; переместить следующий
                                ; символ, если он имеется
       pop    cx                ; извлечь длину строки
       mov    ax,40h            ; функция записи DOS
       mov    bx,1              ; описатель стандартного
                                ; вывода
       mov    dx,OFFSET ReverceString ; напечатать строку
    Done:
       mov    ah,4ch            ; функция DOS завершения
                                ; программы
       int    21h               ; завершить программу
       END

     Скоро вы увидите, что сможет делать эта программа. Для нача-
ла не забудьте ее сохранить (под именем REVERSE.ASM).

                Запуск программы REVERSE.ASM
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для запуска программы REVERSE.ASM вы должны  сначала  ассем-
блировать ее:

     TASM reverse

а затем ввести:

     TLINK reverse

для создания выполняемого файла. Запустите программу, введя в от-
вет на подсказку DOS слово reverse. В случае вывода при ассембли-
ровании сообщений об ошибках, внимательно проверьте исходный код,
сравните его с приведенным текстом, а затем попытайтесь повторить
процесс.

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

     ABCDEFG

а затем нажмите клавишу ENTER. Программа выведет на экран:

     GFEDCBA

и завершит работу.

     Теперь ясно, что делает программа REVERSE.ASM: она  изменяет
порядок  символов во введенной строке на обратный. Быстрая работа
со строками и символами - эта одна из областей, где  язык  Ассем-
блера  превосходно  демонстрирует свои качества. Вы увидите это в
следующих нескольких главах.

     Вас можно поздравить! Вы только что ввели, ассемблировали  и
скомпоновали  несколько  программ на Ассемблере и, таким образом,
ознакомились в действии с основами программирования на  Ассембле-
ре: вводом, обработкой данных и выводом.

     Если вы не хотите создавать объектный файл, но хотите  полу-
чить файл листинга, или если вы хотите получить файл перекрестных
ссылок, но не хотите создавать файл листинга или объектный  файл,
задайте в   качестве  имени  файла  пустое  (нулевое)  устройство
(NULL). Например, команда:

     TASM FILE1,,NUL,

ассемблирует файл FILE1.ASM в объектный файл FILE1.OBJ, не созда-
вая файла листинга, и создает файл перекрестных ссылок FILE1.XRF.

               Литература по языку Ассемблера
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Многие ведущие   издательства   издают  по  продуктам  фирмы
Borland превосходные книги,  предназначенные для любого круга чи-
тателей - от начинающих пользователей до тех, кто имеет достаточ-
ный опыт работы.  Приведем несколько  названий  книг,  в  которых
можно найти  дополнительную информацию о Турбо Ассемблере,  Турбо
отладчике и Турбо Профайлере:

     Ackerman, Charles. Turbo Debugger and Tools: A Self-Teaching
     Guide, John Wiley and Sons (New York: 1990).

     Swan, Tom.  Mastering Turbo Assembler.  Indianapolis: Hayden
     Books, 1989.

     Swan, Tom.  Mastering Turbo Debugger and  Tools.  Howard  W.
     Sams and Co. (Carnel, IN: 1990).

     Syck, Gary.  The   Waite  Group's  Turbo   Assembler  Bible,
     Howard W. Sams and Co. (Carmel, IN: 1990).

        Глава 2. Использование директив и параметров
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Данная глава познакомит вас  с  необязательными  параметрами
командной строки Турбо Ассемблера.  Мы опишем каждый параметр ко-
мандной строки,  который вы можете использовать для  того,  чтобы
изменить поведение Ассемблера,  и покажем, как и где используются
командные файлы. Наконец, мы опишем также файл конфигурации и то,
как можно управлять выводом предупреждающих сообщений и сообщений
об ошибках.

               Запуск Турбо Ассемблера из DOS
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     На дистрибутивных дисках находятся две версии Турбо  Ассемб-
лера - TASM.EXE и TASMX.EXE. Используемая версия зависит от того,
что вам нужно сделать.

           Примечание: TASMX  следует выбрать для ассемблирования
      очень больших модулей.

     Турбо Ассемблер TASMX можно запустить  в  защищенном  режиме
Microsoft  Windows 3.0 при помощи окна диалога Windows DOS,  если
вы запустили Windows в улучшенном режиме 386.  Используйте TASMX,
если у вас имеется большой объем расширенной памяти, и вам требу-
ется ассемблировать очень большие модули. TASMX требует задания в
маршруте  поиска  еще одного файла,  DPMILOAD.EXE,  который также
поставляется на дистрибутивных дисках.  (При  попытке  выполнения
TASMX в другой среде,  нежели MS-Windows в улучшенном режиме 386,
TASMX пытается использовать поставляемый с Турбо Ассемблером сер-
вер DPMI - поддержку интерфейса защищенного режима DOS.  Это поз-
воляет вам использовать TASMX на машинах с процессорами  286  или
386 при наличии расширенной памяти.)

           Примечание: TASM  следует  выбирать  для  того,  чтобы
      иметь большую скорость выполнения ассемблирования.

     Если вам не нужно ассемблировать очень большие модули,  сле-
дует выбрать  TASM.  Эта версия Турбо Ассемблера работает сравни-
тельно быстрее,  чем TASMX. Вы также можете запустить TASM, нахо-
дясь в диалоговом окне Windows DOS.

     Обе версии Турбо Ассемблера имеют очень мощный и гибкий син-
таксис командной строки. Если при запуске Турбо Ассемблера не за-
дать никаких аргументов, например:

     TASM

или

     TASMX

то будет выведен экран со  вспомогательным  описанием  параметров
командной  строки и синтаксиса для задания ассемблируемых файлов.
На Рис. 2.1 показан этот экран. Параметры и их синтаксис для TASM
такие же.

ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Turbo Assembler Version 3.0 Copyright (C) 1988,1991
                          by Borland International, Inc
Usage:

TASM [параметры] исх_файл [,объект_файл] [,листинг] [,пер_ссылки]

/a,/s         Упорядочивание  сегментов  по  алфавитному  порядку
              или порядку исходного кода

/c            Генерация в листинге перекрестных ссылок

/dSYM[=VAL]   Определяется SYM = 0 или SYM = VAL

/e,/r         Эмулируемые или действительные инструкции с плаваю-
              щей точкой

/h,/?         Выводится данная справочная информация

/iPATH        Включаемые файлы ищутся по маршруту,  определяемому
              PATH

/jCMD         Определяет  начальную директиву Ассемблера CMD (на-
              пример, jIDEAL)

/kh#          Мощность хеш-таблицы #

/l,/la        Генерация листинга: l=обычный листинг, la=расширен-
              ный

/ml,/mx,/mu   Различимость в регистре букв идентификаторов:
              ml=все, mx=глобальные, mu=не различаются

/mv#          Установка максимально допустимой длины имен иденти-
              фикаторов

/m#           Позволяет  выполнять # проходов для разрешения ссы-
              лок вперед

/n            Подавление в листингах таблицы идентификаторов

/o,/op        Генерация  оверлейного  кода, 32-разрядные фиксиро-
              ванные адреса для компоновщика Phar Lap.

/q            Подавление записей файла .OBJ, не нужных  для  ком-
              поновки

/p            Проверка перекрытия сегмента кода в  защищенном ре-
              жиме

/t            Подавление сообщений при успешном ассемблировании

/w0,/w1,/w2   Задание  уровня предупреждение:  w0 -  нет  предуп-
              реждений, w1 или w2 - есть предупреждения

/w-xxx,/w+xxx Запрещение или разрешение предупреждения xxx

/x            Включение в листинги блоков условного ассемблирова-
              ния

/z            Вывести на  дисплей строку исходного текста с сооб-
              щением об ошибке.

/zi,/zd,/zn   Информация об идентификаторах для отладки:  zi=пол-
              ная, zd=только о номерах строк, zn=отсутствует.
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Рис. 2.1 Командная строка Турбо  Ассемблера

     С помощью параметров командной строки вы можете задавать имя
одного  или  нескольких ассемблируемых файлов, а также параметры,
управляющие их  ассемблированием.  В  последующих  параграфах все
ссылки на TASM относятся  также  к  TASMX.  Если  вы  используете
TASMX, просто подставляйте в командах вместо TASM TASMX.

     Общий вид командной строки выглядит следующим образом:

     TASM файлы [; файлы]...

     Точка с запятой после левой квадратной скобки позволяет  вам
в  одной  командной строке ассемблировать несколько групп файлов.
По желанию вы можете задать для каждой  группы  файлов  различные
параметры, на примере:

     TASM /e FILE1; /a FILE2

     Здесь файл FILE1.ASM ассемблируется с  параметром  командной
строки /e, а файл FILE2.ASM - с параметром командной строки /a.

     В общем случае группа файлов в командной строке может  иметь
вид:

     [параметр]...исх_файл [[+] исходный_файл]...
              [,[объектный_файл] [, [файл_листинга],
              [, [файл_перекрестных_ссылок]]

     Этот синтаксис показывает, что группа файлов может начинать-
ся с любого параметра, который вы хотите применить к этим файлам,
а затем могут следовать файлы,  которые вы хотите ассемблировать.
Именем  файла может быть отдельное имя файла,  либо вы можете ис-
пользовать обычные трафаретные символы DOS  *  и  ?  для  задания
группы ассемблируемых файлов. Если расширение имени файла не ука-
зано,  Турбо Ассемблер добавляет расширение .ASM.  Например,  для
ассемблирования всех файлов с расширением .ASM в текущем каталоге
введите команду:

     TASM *

     Если вы хотите ассемблировать  несколько  файлов,  их  имена
можно разделить знаком плюс (+):

     TASM MYFILE1 + MYFILE2

     За именем  ассемблируемого файла можно задать необязательные
имена объектного файла,  файла листинга и файла перекрестных ссы-
лок. Если вы не задали имен объектного файла или файла перекрест-
ных ссылок,  то Турбо Ассемблер создаст объектный файл с  тем  же
именем, что и у файла исходного текста и расширением .OBJ.

     Файл листинга не будет создан,  пока вы в явном виде не зап-
росите его создание.  Чтобы запросить  листинг,  поместите  после
имени  объектного файла запятую и за ней имя файла листинга. Если
не задать имя файла листинга явно,  Турбо Ассемблер создаст  этот
файл  с  тем  же именем,  что и у исходного файла,  и расширением
.LST.  Если же вы задали имя файла листинга, но без расширения, к
имени будет прибавлено расширение .LST.

     Файл перекрестных  ссылок  не будет создан,  пока вы в явном
виде не запросите  его  создание.  Чтобы  запросить  перекрестные
ссылки, поместите после имени файла листинга запятую и за ней имя
файла перекрестных ссылок.  Если не задать имя файла перекрестных
ссылок  явно,  Турбо Ассемблер создаст этот файл с тем же именем,
что и у исходного файла,  и расширением .XRF.  Если же вы  задали
имя файла перекрестных ссылок,  но без расширения,  к имени будет
прибавлено расширение .XRF. Описание работы с файлом перекрестных
ссылок  при помощи утилиты глобальных перекрестных ссылок (TCREF)
находится на диске.

     Если вы желаете принять имя объектного файла по  умолчанию и
при  этом  запросить файл листинга,  вы должны поместить запятую,
которая обычно отделяет имя объектного файла от имени файла  лис-
тинга:

     TASM FILE1,,TEST

     Эта строка вызовет ассемблирование файла FILE1.ASM в объект-
ный файл FILE1.OBJ и создаст файл листинга TEST.LST.

     Если вы хотите принять по умолчанию имена объектного файла и
файла  листинга,  а  также  запросить создание файла перекрестных
ссылок,  вы должны поместить в строке запятые,  обычно отделяющие
эти имена:

     TASM MYFILE,,,MYXREF

     По этой   команде  файл  MYFILE.ASM  ассемблируется  в  файл
MYFILE.OBJ,  листинг выводится в файл с именем MYFILE.LST,  а пе-
рекрестные ссылки - в файл MYXREF.XRF.

     Если при спецификации ассемблируемых исходных файлов вы  ис-
пользуете  трафаретные  символы,  их можно использовать также для
задания имен файла листинга и объектного файла. Например, если  в
текущем каталоге содержатся файлы XX1.ASM и XX2.ASM, то командная
строка:

     TASM XX*,YY*

ассемблирует все файлы, начинающиеся с букв XX, генерирует объек-
тные  файлы,  имена  которых  будут начинаться с YY,  а остальную
часть имени формирует в соответствии с  именем  исходного  файла.
Результирующие объектные файлы получат, таким образом, имена YY1,
OBJ и YY2.OBJ.

     Если вы не хотите создавать объектный файл, но хотите  полу-
чить файл листинга, или если вы хотите получить файл перекрестных
ссылок, но не хотите создавать файл листинга или объектный  файл,
можно в  качестве имени файла задать нулевое (фиктивное) устройс-
тво. Например:

     TASM FILE1,,NUL,

     Эта команда ассемблирует файл  FILE1.ASM  в  объектный  файл
FILE1.OBJ.  При этом файл листинга не создается, а создается файл
перекрестных ссылок FILE1.XRF.

                 Параметры командной строки
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Необязательные параметры командной строки позволяют вам  уп-
равлять  поведением Ассемблера и тем, какую информацию он выводит
на экран, в листинг и объектный файл. В Турбо Ассемблере  предус-
мотрены  некоторые  параметры,  которые не выполняют никаких дей-
ствий, а  используются  только  для  совместимости текущей версии
TASM  с   предыдущими   версиями   MASM   (макроассемблер   фирмы
Microsoft):

    я1 я0/b        Задает размер буфера
   я1  я0/v        Выводит на экран дополнительную статистику

     Вы можете задавать  параметры,  представляющие  собой  любую
комбинацию букв в верхнем и нижнем регистре. Кроме того, парамет-
ры можно задавать в любом порядке (кроме параметров /I и /J), они
будут  при этом обрабатываться последовательно. При использовании
параметра /d нужно быть внимательным: идентификаторы надо опреде-
лить до того, как они будут использованы в последующих параметрах
/d.

           Примечание: С  помощью директив,  указанных в исходном
      коде, вы можете отменить эквивалентные им параметры Ассемб-
      лера.

     На Рис.  2.1 (см.  выше) приведен полный  список  параметров
Турбо Ассемблера. Далее эти параметры описаны подробно.

   Параметр /A
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Задает упорядочивание сегментов по алфавиту.

     Синтаксис: /A

     Примечания: Параметр /A указывает Турбо Ассемблеру, что сег-
менты в объектном файле должны быть размещены в алфавитном поряд-
ке. Это эквивалентно  использование  в  исходном  коде  директивы
.ALPHA.

     Этим параметром обычно приходится пользоваться тогда,  когда
вы  хотите  ассемблировать  исходный  файл, написанный для ранних
версий ассемблеров фирм Microsoft или IBM.

     Параметр /S изменяет действие данного параметра на обратное,
сохраняя  используемое по умолчанию последовательное упорядочива-
ние сегментов.

     Если в исходном файле вы задаете с  помощью  директивы  .SEQ
последовательное  упорядочивание  сегментов,  то она отменит дей-
ствие параметра /A, задаваемого в командной строке.

     Пример:

     TASM /A TEST1

     Данная командная строка создает  объектный  файл  TEST1.OBJ,
сегменты которого упорядочиваются в алфавитном порядке.

  Параметр /B
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Синтаксис: /B

     Примечания: Параметр /B используется в целях совместимости с
другими версиями. Он не приводит ни к каким действиям и не оказы-
вает влияния на ассемблирование.

  Параметр /C
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Разрешает включать в листинг перекрестные ссылки.

     Синтаксис: /C

     Примечания: Параметр /C разрешает включение в файл  листинга
информации  о  перекрестных ссылках. Турбо Ассемблер включает ин-
формацию о перекрестных ссылках в таблицу идентификаторов в конце
файла листинга. Чтобы получить информацию о перекрестных ссылках,
вам нужно также явно задать в командной строке файл листинга  или
использовать  для разрешения формирования файла листинга параметр
/L.

     Для каждого идентификатора в перекрестных ссылках указывает-
ся  строка,  в  которой он определен и все строки, где имеется на
него ссылка.

     Пример:

     TASM /l /c TEST1

     Данная команда создает файл листинга,  в таблице идентифика-
торов которого содержится информация о перекрестных ссылках.

  Параметр /D
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Определяет идентификатор.

     Синтаксис: /Dидентификатор[=значение или выражение]

     Примечания: Параметр  /D определяет идентификатор для исход-
ного  файла,  точно  также,  как если бы он определялся на первой
строке исходного файла с помощью директивы =. В командной  строке
этот параметр можно использовать любое число раз.

     Вы можете только определить  идентификатор,  равный  другому
идентификатору,  или  постоянному  значению.  Справа от знака ра-
венства (=) не допускается использовать выражение  с  операциями.
Например,  допустимо /DX=9 и /DX=Y, но параметр /DX=Y-4 не допус-
кается.

     Пример:

     TASM /DMAX=10 /DMIN=2 TEST1

     В данной командной строке  определяются  два  идентификатора
MAX и MIN, на которые могут ссылаться другие операторы в исходном
файле TEST1.ASM.

  Параметр /E
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Генерирует инструкции эмуляции работы  с  плавающей
точкой.

     Синтаксис: /E

     Примечания: Параметр /E указывает Турбо Ассемблеру, что нуж-
но генерировать инструкции работы с плавающей точкой, которые бу-
дут выполняться с  помощью  программного  обеспечения  (эмулятора
операций  с  плавающей  точкой).  Используйте этот параметр, если
ваша программа содержит библиотеку эмуляции  работы  с  плавающей
точкой,  которая  эмулирует  функции арифметического сопроцессора
80х87.

     Обычно этот параметр следует использовать только в том  слу-
чае, если ваш модуль на Ассемблере является частью программы, на-
писанной на языке высокого уровня, в которой используется библио-
тека эмуляции работы с плавающей точкой (эмуляцию операций с пла-
вающей точкой поддерживают компиляторы  Borland  C++,  Турбо  Си,
Турбо Паскаль,  Турбо Бейсик и Турбо Пролог). Вы не можете просто
скомпоновать программу на Ассемблере с библиотекой  эмуляции, так
как предполагается,  что библиотека должна инициализироваться на-
чальным кодом компилятора.

     Параметр /R изменяет действие данного параметра на обратное,
разрешая  ассемблирование  действительных  инструкций с плавающей
точкой, которые могут выполняться арифметическим сопроцессором.

     Если в исходной файле вы используете  директиву  NOEMUL,  то
она отменит действие параметра /E в командной строке.

     Параметр командной строки /E оказывает то же действие, что и
использование  в начале исходного файла директивы EMUL, и эквива-
лентно параметру командной строки /JEMUL.

     Пример:

     TASM /E SEGANT
     TCC -f TRIG.C SEGANT.OBJ

     Первая командная строка ассемблирует модуль  в  эмулируемыми
инструкциями с плавающей точкой. Вторая командная строка компили-
рует модуль языка Си с эмуляцией операций с  плавающей  точкой  и
затем компонует его с объектным файлом Ассемблера.

   Параметр /H или /?
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Выводит на экран дисплея справочную информацию.

     Синтаксис: /H или /?

     Примечания: Параметр /H указывает Турбо Ассемблеру,  что  на
экран  дисплея  нужно  вывести справочную информацию, описывающую
синтаксис командной строки. Эта справочная информация включает  в
себя  список  параметров, а также различные задаваемые имена фай-
лов. Параметр /? делает то же самое.

     Пример:

       TASM /h

   Параметр /I
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Задает маршрут доступа к включаемому файлу.

     Синтаксис: /Iмаршрут

     Примечания: Параметр /I указывает Турбо Ассемблеру, где нуж-
но искать файлы, включаемые в исходный файл по директиве INCLUDE.
В командной строке можно указать несколько параметров /I (их чис-
ло ограничено только размерами оперативной памяти).

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

     Если вы в качестве части имени файла указываете маршрут,  то
сначала делается попытка поиска по данному маршруту, а затем Тур-
бо Ассемблер  выполняет поиск в каталогах,  заданных в параметрах
командной строки /I (в том порядке,  как они указаны в  командной
строке). Затем  он ищет файл по всем каталогам,  заданным в пара-
метрах /I файла конфигурации.

     Если в спецификации имени файла вы не указываете маршрут, то
Турбо  Ассемблер  выполняет сначала поиск в каталогах, заданных в
параметрах командной строки /I, затем - в каталогах,  заданных  в
параметрах /I файла конфигурации, и, наконец, в текущем каталоге.

     Пример:

       TASM /I\INCLUDE /ID:\INCLUDE TEST1

     Если исходный файл содержит оператор:

       INCLUDE MYMACS.INC

то Турбо Ассемблер сначала ищет файл  \INCLUDE\MYMACS.INC,  затем
D:\INCLUDE\MYMACS.INC.  Если  он  еще  не  нашел  файл,  то  файл
с именем MYMACS.INC ищется в текущем каталоге. Если бы в исходном
файле содержался оператор:

       INCLUDE INCS\MYMACS.INC

то   Турбо   Ассемблер   сначала   искал   бы   включаемый   файл
\INCS\MYMACS.INC,    затем    \INCLUDE\MYMACS.INC,   и,   наконец
D:\INCLUDE\MYMACS.INC.

  Параметр /J
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Определяет директиву инициализации Ассемблера.

     Синтаксис: /Jдиректива

     Примечания: Параметр /J позволяет вам определить  директиву,
которая  будет  ассемблироваться  перед  первой строкой исходного
файла. "Директива" может представлять собой любую директиву Турбо
Ассемблера,  не  требующую  аргументов,  например,  .286,  IDEAL,
%MACS, NOJUMP и т.д. Полное описание  директив  Турбо  Ассемблера
содержится в соответствующей главе.

     В командной строке вы можете указать более одного  параметра
/J. При этом они будут обработаны слева направо.

     Пример:

     TASM /J.286 .JIDEAL TEST1

     При этом ассемблируется файл TEST1.ASM с разрешенными  инст-
рукциями  процессора  80286 и разрешением синтаксического анализа
выражений в режиме IDEAL.

  Параметр /KH
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Задает максимально допустимое  число  идентификато-
ров.

     Синтаксис: /KHnидентификаторов

     Примечания: Параметр /KH задает максимально допустимое число
идентификаторов,  которое  может  содержать программа. Если вы не
используете данный параметр, ваша программа может содержать толь-
ко  до 8192 идентификаторов. Использование этого параметра позво-
ляет увеличить  число идентификаторов до значения "nидентификато-
ров" (это значение не должно превышать 32768).

     Используйте данный параметр, если при ассемблировании  прог-
раммы вы  получаете  сообщение  "Out  of  hash  space" ("Буферное
пространство исчерпано").

     Данный параметр можно также использовать для уменьшения  об-
щего  числа идентификаторов до значения, меньшего назначенного по
умолчанию (8192). Это позволит  освободить  некоторое  количество
памяти,  что  может оказаться полезным, когда вы пытаетесь ассем-
блировать программу, а у вас не хватает памяти.

     Пример:

     TASM /KH10000 BIGFILE

     Эта команда сообщает Турбо Ассемблеру, что при ассемблирова-
нии файла BIGFILE нужно зарезервировать память для 10000  иденти-
фикаторов.

  Параметр /L
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Генерирует файл листинга.

     Синтаксис: /L

     Примечания: Параметр /L указывает,  что  вы  хотите  создать
файл  листинга,  даже  если  вы его не задаете в командной строке
явно. Файл листинга имеет то же имя, что и исходный файл, и  рас-
ширение .LST.

     Пример:

     TASM /L TEST1

     Данная командная строка приводит к созданию файла листинга с
именем TEST1.LST.

  Параметр /LA
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Показывает в исходной файле код интерфейса с языком
высокого уровня.

     Синтаксис: /LA

     Примечания: Параметр /LA указывает Турбо Ассемблеру,  что  в
файле листинга нужно отразить весь генерируемый код, включая код,
который генерируется в результате директивы языка высокого уровня
.MODEL.

     Пример:

     TASM /LA FILE1

  Параметр /M
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Устанавливает максимальное число проходов Ассембле-
ра.

     Синтаксис: /M[число_проходов]

     Примечания: Обычно Турбо Ассемблер работает как  однопроход-
ный  Ассемблер.  Параметр  /m позволяет задать максимальное число
проходов,  которое Ассемблер выполнит в процессе ассемблирования.
TASM автоматически определяет те случаи, когда фактически требуе-
мое число проходов меньше заданного. Если максимальное число про-
ходов не задано, то по умолчанию оно равно пяти.

     Некоторые модули могут содержать конструкции,  которые будут
правильно ассемблироваться только  при  двух  проходах,  либо  вы
можете захотеть  удалить инструкции NOP,  добавленные Ассемблером
из-за опережающих ссылок.  Если множественные проходы не разреше-
ны, то для такого модуля будет выдано хотя бы одно предупреждение
"Pass-dependent construction encountered"  ("Встречена  конструк-
ция,  зависящая  от  числа проходов").  При заданном параметре /m
Турбо Ассемблер сможет ассемблировать такой код, но не сможет его
оптимизировать за счет удаления пустых команд NOP,  независимо от
числа заданных проходов.  В этом случае будет выдано предупрежде-
ние  "Module  is  pass  dependent  - compatibility pass was done"
("Модуль зависим от числа проходов - сделан проход для  обеспече-
ния совместимости").

     Пример:

     TASM /M2 TEST1

     Эта строка  заставит  Турбо  Ассемблер  при  ассемблировании
программы TEST1 выполнить два прохода.

  Параметр /ML
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Интерпретирует различие в регистрах букв  идентифи-
каторов.

     Синтаксис: /ML

     Примечания: Параметр /ML указывает Турбо Ассемблеру, что  во
всех  идентификаторах  нужно  различать  буквы  разного  регистра
(строчные и прописные). Обычно строчные и  прописные  буквы  рас-
сматриваются,  как  эквивалентные, поэтому имена ABCxyz, ABCXYZ и
abcxyz обозначают один и тот же идентификатор.  Если  вы  задаете
параметр /ML, то эти три идентификатора будут считаться различны-
ми. Тем не менее, даже после задания параметра /ML ключевые слова
Ассемблера  можно вводить как в верхнем, так и в нижнем регистре.
Ключевые слова представляют собой  идентификаторы,  встроенные  в
Ассемблер, которые имеют специальное значение (мнемоники инструк-
ций, директивы и операторы).

     Пример:

     TASM /ML TEST1

где TEST1.ASM содержит следующие операторы:

 ABC   DW   1
 abc   DW   0          ; это не дублирующий идентификатор
       Mov  Ax,[Bp]    ; в ключевых словах допускается использо-
                       ; вать разный регистр

     Для модулей Паскаля параметр-переключатель /ml при использо-
вании его  совместно с параметром /mx имеет специальное значение.
Подробнее об этом рассказывается в описании параметра /mx.

  Параметр /MU
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Преобразует идентификаторы в верхний регистр.

     Синтаксис: /MU

     Примечания: Параметр /MU указывает Ассемблеру, что нужно иг-
норировать  регистр во всех идентификаторах. По умолчанию в Турбо
Ассемблере задано, что в идентификаторах все  буквы  нижнего  ре-
гистра  должны  преобразовываться  в верхний регистр (если это не
отменено с помощью директивы /ML).

     Пример:

     TASM /MU TEST1

При этом все идентификаторы будут преобразованы в верхний регистр
(что задано по умолчанию):

            EXTRN  myfunc:NEAR
            call   myfunc       ; не важно, как была
                                ; определена функция:
                                ; MYFUNC, Myfunс,...

  Параметр /MV#
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Устанавливает максимальную длину имен идентификато-
ров.

     Синтаксис: /MV#

     Примечания: Параметр /mv# устанавливает  максимальную  длину
распознаваемых  TASM  имен идентификаторов. Например, если задать
/mv12, то  TASM  будет  рассматривать  имена   ABCDEFGHIJKLL.   и
ABCDEFGHIJKL как одно и то же имя ABCDEFGHIJKLL. Заметим, что ми-
нимальное значение, которое вы здесь можете задавать, равно 12.

  Параметр /MX
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Задает различимость на на строчные и прописные бук-
вы  (верхний и нижний регистр) во внешних и общедоступных иденти-
фикаторах.

     Синтаксис: /MX

     Примечания: Параметр /MX сообщает Турбо Ассемблеру, что раз-
личать регистр букв нужно только во внешних (External) и общедос-
тупных (Public) идентификаторах. Все другие идентификаторы в  ис-
ходном  файле  будут  интерпретироваться, как набранные в верхнем
регистре.

     Использовать данную директиву следует при вызове процедур из
других модулей, которые ассемблировались или компилировались так,
что сохранилось различие в строчных и прописных буквах (например,
модулей, которые компилировались в Borland C++).

     Пример:

     TASM /MX TEST1

где TEST1 содержит следующие исходные строки:

     EXTRN Cfunc:NEAR
     myproc PROC NEAR
     call Cfunc
     .
     .
     .

           Замечание: Использование вместе параметров /mx  и  /ml
      для идентификаторов, описанных в Паскале, имеет специальное
      значение. Если вы используете эти параметры вместе, иденти-
      фикаторы будут доступны компоновщику, как символы в верхнем
      регистре.

  Параметр /N
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Подавляет в файле листинга таблицу идентификаторов.

     Синтаксис: /N

     Примечания: Параметр /N показывает, что в конце  файла  лис-
тинга  вы не хотите использовать обычную таблицу идентификаторов.
Обычно в конце файла листинга содержится полная таблица идентифи-
каторов, где показаны все идентификаторы, их имена и значения.

     Вы должны задать файл листинга либо явным образом (в  коман-
дной строке), либо с помощью параметра /L. В противном случае па-
раметр /N не приведет ни к каким действиям.

     Пример:

       TASM /L /N TEST1

     При этом генерируется файл листинга, где показывается только
генерируемый код без значений ваших идентификаторов.

  Параметр /O
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Генерирует оверлейный код.

     Синтаксис: /O

     Примечания: Задание параметра командной строки  /o  вызывает
генерацию оверлейно-совместимых адресов фиксации.  При ее исполь-
зовании ссылки 386 к сегментам USE32 не должны  выполняться,  так
как это может привести к неправильной работе компоновщика.

  Параметр /OP
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Генерирует  оверлейный  код  для  компоновщика Phar
Lap.

     Синтаксис: /OP

     Примечание: Задание параметра командной строки  /o  вызывает
генерацию оверлейно-совместимых адресов фиксации для компоновщика
Phar Lap. Полученный объектный файл не будет совместимым с компо-
новщиком фирмы Borland TLINK.

  Параметр /P
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Проверяет наличие "кода с  побочными  эффектами"  в
защищенном режиме.

     Синтаксис: /P

     Примечания: Параметр /P определяет, что вы  хотите  получить
предупреждение  при  любой  инструкции, генерирующей в защищенном
режиме код  с  возможным "побочным эффектом" (impure code).  Инс-
трукции,  перемещающие данные в память путем переопределения  ре-
гистра CS: в защищенном режиме рассматриваются, как некорректные,
поскольку они в защищенном режиме могут работать неверно, если не
принять специальных мер.

     Этот параметр нужно использовать только в том  случае,  если
вы пишете программу,  выполняемую на процессоре 80286,  i486  или
80386 в защищенном режиме.

     Пример:

     TASM /P TEST1

где TEST1 содержит следующие операторы:

          .286P
  CODE    SEGMENT
  temp    DW    ?
          mov   CS:temp,0   ; в защищенном  режиме  может  выпол-
                            ; няться некорректно

  Параметр /Q
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Подавляет вывод записей  объектного  файла  (.OBJ),
ненужных для компоновки.

     Синтаксис: /Q

     Примечания: Параметр /q удаляет из результирующего объектно-
го файла записи об авторских правах и записи  зависимости  файла,
уменьшая тем самым его размер.  Этот параметр не следует задавать
при использовании программы MAKE или аналогичной программы, рабо-
та которой основывается на записях зависимостей.

  Параметр /R
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Генерирует реальные инструкции с плавающей точкой.

     Синтаксис: /R

     Примечания: Параметр /R указывает Турбо Ассемблеру, что нуж-
но  генерировать  реальные  инструкции с плавающей точкой (вместо
генерации эмулируемых инструкций с плавающей точкой). Используйте
этот  параметр,  если вы хотите выполнять свою программу на маши-
нах, оснащенных арифметическим сопроцессором 80х87.

     Действие данного параметр изменяет на обратное  параметр  /E
(при  этом  генерируются  эмулируемые инструкции с плавающей точ-
кой).

     Если в исходном файле вы используете директиву EMUL, то  она
отменит действие инструкции /R, указанной в командной строке.

     Параметр командной строки /R имеет тот же эффект, что и  ис-
пользование в начале исходного файле директивы NOEMUL и совпадает
с действием параметра командной строки /JNOEMUL.

     Пример:

       TASM /R SEGANT
       TPC /$N+ /$E- TRIG.PAS

     Первая команда ассемблирует модуль с реальными  инструкциями
с  плавающей точкой. Вторая командная строка компилирует исходный
модуль Паскаля с реальными инструкциями с плавающей точкой, кото-
рый компонуется с объектным файлом Ассемблера.

  Параметр /S
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Задает последовательное упорядочивание сегментов.

     Синтаксис: /S

     Примечания: Параметр /S указывает Турбо Ассемблеру, что сег-
менты в объектном файле нужно разместить в том порядке, в котором
Турбо Ассемблер обнаруживает их в  исходном  коде.  По  умолчанию
Турбо Ассемблер использует именно такое упорядочивание сегментов,
если вы не изменили его с помощью параметра /A в командной строке
или в файле конфигурации.

     Если с помощью директивы .ALPHA в исходном  коде  вы  задали
упорядочивание  сегментов  в алфавитном порядке, то эта директива
отменит параметр /S, задаваемый в командной строке.

     Пример:

     TASM /S TEST1

     По данной команде создается объектный файл (TEST1.OBJ), сег-
менты  которого  упорядочены  в том порядке, как они содержатся в
исходном файле.

  Параметр /T
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Подавляет вывод сообщений при условном  ассемблиро-
вании.

     Синтаксис: /T

     Примечания: Параметр /T подавляет всю выводимую Турбо Ассем-
блером на  экран информацию,  кроме предупреждений и сообщений об
ошибках, возникающих в результате ассемблирования.

     Вы можете использовать данный параметр  при  ассемблировании
нескольких модулей, когда на экран желательно выводить только со-
общения об ошибках.

     Пример:

       TASM /T TEST1

  Параметр /V
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Синтаксис: /V

     Примечания: Параметр /V используется в целях  совместимости.
Он не приводит ни к каким действиям и не оказывает влияния на ас-
семблирование.

  Параметр /W
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Управляет генерацией предупреждающих сообщений.

     Синтаксис: /W
                 W-[класс_предупреждений]
                 W+[класс_предупреждений]

     Примечания: Параметр /W управляет выводом Турбо  Ассемблером
предупреждающих сообщений.

     Если вы просто укажете  параметр  /W,  то  будут  выводиться
"слабые"  предупреждения. Такие предупреждения показывают, что вы
можете несколько улучшить эффективность вашей программы.

     Если вы зададите параметр /W- без класса предупреждений,  то
все  предупреждения  запрещаются.  Если за параметром указывается
класс предупреждений, то запрещаются только  эти  предупреждения.
Каждое  предупреждающее  сообщение  имеет  идентификатор  из трех
букв:

     ALN  - выравнивание сегмента в памяти.
     ASS  - подразумевается использование 16-разрядного сегмента;
     BRK  - требуются квадратные скобки;
     ICG  - неэффективная генерация кода;
     LCO  - переполнение счетчика адреса;
     OPI  - открытый блок условия IF;
     OPP  - открытая процедура;
     OPS  - открытый сегмент;
     OVF  - арифметическое переполнение;
     PDC  - конструкция, зависящая от прохода;
     PQK  - предполагается константа для предупреждения [const].
     PRO  - запись в память в защищенном режиме требует
            переопределения регистра CS.
     RES  - предупреждение о резервируемом слове.
     TPI  - предупреждение о недопустимости в Турбо Паскале.

     Если вы указываете параметр /W+ без  класса  предупреждения,
то  все  предупреждения будут разрешены. Если вы задаете параметр
/W+ с классом предупреждений из предыдущего списка, то будут раз-
решены только эти предупреждения.

     По умолчанию Турбо Ассемблер сначала начинает  ассемблирова-
ние исходного файла с разрешением всех предупреждений, кроме пре-
дупреждений о неэффективности кода (ICG) и предупреждений и запи-
си в память в защищенном режиме (PRO).

     Для управления выводом определенных  сообщений  на  заданном
участке программы в файле с исходным кодом вы можете использовать
директивы WARN или NOWARN. Более подробно об этих директивах рас-
сказывается в главе, посвященной директивам.

     Пример:

     TASM /W TEST1

     Следующий оператор в TEST1.ASM выведет предупреждающее сооб-
щение, которое не появится на экране, если не указан параметр /W:

         mov   bx,ABC     ; предупреждение о неэффективности кода
         ABC   = 1

     При задании командной строки:

     TASM /W-OVF TEST2

если TEST2.ASM содержит:

         DW   1000h = 20h

предупреждения генерироваться не будут.

  Параметр /X
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Включает в листинг блоки условного ассемблирования.

     Синтаксис: /X

     Примечания: Если при вычислении блоков IF, IFNDEF,  IFDEF  и
т.д.  получается  значение FALSE, то параметр /X приводит к тому,
что операторы, содержащиеся внутри условного блока, будут включе-
ны в листинг ассемблирования. По данной директиве в листинг будут
также включены сами директивы условного  ассемблирования  (обычно
они в листинг не включаются).

     Вы должны в командной строке или с помощью параметра /L  за-
дать также необходимость генерации файла листинга, иначе параметр
/X действовать не будет.

     Для переопределения параметра /x вы можете использовать  ди-
рективы .LFCOND, .SFCOND и .TFCOND.

     Пример:

       TASM /X TEST1

  Параметр /Z
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Выводит на экран наряду с сообщениями об ошибке со-
ответствующие строки исходного текста.

     Синтаксис: /Z

     Примечания: Параметр /Z указывает Ассемблеру, что при  гене-
рации  сообщения об ошибке на экран нужно вывести соответствующую
строку исходного файла (где эта ошибка возникла). Вызвавшая ошиб-
ку  строка  выводится  перед сообщением об ошибке. При запрещении
данного параметра Турбо Ассемблер просто выводит сообщение,  опи-
сывающее ошибку.

     Пример:

       TASM /Z TEST1

  Параметр /ZD
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Разрешает включение в объектные файлы информации  о
номерах строк.

     Синтаксис: /ZD

     Примечания: Параметр /ZD приводит к тому,  что Турбо Ассемб-
лер  будет помещать в объектные файлы информацию о номерах строк.
Это позволяет автономному отладчику фирмы Borland (Турбо отладчи-
ку) выводить на экран текущее место в исходном коде, но не позво-
ляет ему осуществлять доступ к элементам данных.

     Если при попытке отладки программы с помощью Турбо отладчика
вам не хватит памяти, вы можете использовать параметр /ZD для од-
них модулей и параметр /ZI - для других.

     Пример:

       TASM /ZD TEST1

  Параметр /ZI
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Разрешает включение в объектный файл информации для
отладки.

     Синтаксис: /ZI

     Примечания: Параметр /ZI указывает Турбо Ассемблеру,  что  в
объектный  файл  нужно вывести полную информацию для отладки. Эта
информация включает в себя записи о номерах строк (для  синхрони-
зации вывода на экран исходного текста) и информацию о типах дан-
ных, позволяющую модифицировать и проверить данные программы.

     Параметр /ZI позволяет вам использовать все  средства  Турбо
отладчика для  прохождения  программы и проверки и изменения эле-
ментов данных. Вы можете использовать параметр /ZI для всех моду-
лей программы или только для тех, отладка которых вас интересует.
Поскольку параметр /ZI добавляет информацию в объектные и  выпол-
няемые файлы, может оказаться нежелательным его использование для
всех модулей программы при выполнении программы  Турбо отладчиком
(например, может возникать ситуация нехватки памяти).

     Пример:

     TASM /ZI TEST1

  Параметр /ZN
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Запрещает включение в объектный файл информацию для
отладки.

     Синтаксис: /ZN

     Примечания: Параметр /zn указывает Турбо Ассемблеру, что ин-
формацию  для отладки в объектный файл выводить не нужно. Его по-
лезно использовать для переопределения параметра /zi в файле кон-
фигурации.

                  Косвенные командные файлы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В любой момент, когда вы вводите командную строку, Турбо Ас-
семблер  позволяет  вам  задавать косвенный командный файл, с по-
мощью указания перед его именем символа @. Например:

     TASM /DTESTMODE @MYPROJ.TA

     Эта команда приводит к тому, что содержимое файла  MYPROJ.TA
становится  частью  командной строки (как если бы вы ввели ее со-
держимое непосредственно).

     Это полезное средство позволяет вам поместить наиболее часто
используемые  командные  строки и списки файлов в отдельный файл.
При этом нет необходимости помещать всю командную строку  в  один
косвенный  файл,  поскольку  в одной командной строке допускается
использовать несколько исходных файлов  с  обычными  аргументами,
например:

     TASM @MYFILES @IOLIBS /DBUF=1024

     Таким образом вы можете использовать длинный список стандар-
тных файлов и параметров, благодаря чему можно легко изменять по-
ведение Ассемблера при каждом ассемблировании.

     Вы можете либо поместить все имена и параметры файлов в одну
строку  командного файла, либо разбить их на несколько строк, как
это необходимо.

                     Файлы конфигурации
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер позволяет вам также поместить наиболее часто
используемые параметры в файл конфигурации  в  текущем  каталоге.
Таким  образом,  когда вы запускаете Турбо Ассемблер,  он будет в
текущем каталоге искать файл TASM.CFG.  При работе в операционной
системе DOS 3.x и старше поиск будет также выполняться в  катало-
ге, из которого был загружен TASM или TASMX. Если Турбо Ассемблер
находит этот файл,  то он будет интерпретировать его, как косвен-
ный файл, и обрабатывать его в командной строке первым.

     Это может оказаться полезным, когда вы  формируете  "проект"
программы, и  все  файлы проекта находятся в одном каталоге.  При
этом вы хотите,  например, всегда выполнять ассемблирование с ис-
пользованием эмулирования  инструкций  с плавающей точкой  (пара-
метр /E). Для этого вы можете поместить параметр в файл TASM.CFG,
после чего его не нужно будет задавать  каждый  раз  при  запуске
Турбо Ассемблера.

     Содержимое файла конфигурации имеет тот  же  формат,  что  и
косвенный  файл. Этот файл может содержать любую допустимую в ко-
мандной строке информацию и содержать столько строк, сколько  не-
обходимо.  Параметры обрабатываются так, как если бы они содержа-
лись на одной строке.

     Содержимое файла конфигурации обрабатывается до всех  других
аргументов командной строки. Это позволяет вам отменить любой па-
раметр, заданный в файле конфигурации, просто указав в  командной
строке  параметр,  который имеет противоположное действие. Напри-
мер, если ваш файл конфигурации содержит параметры:

     /A /E

и вы вызываете Турбо Ассемблер командой:

     TASM /S /R MYFILE

где MYFILE - файл вашей программы, то ассемблирование  будет  вы-
полнено  с  последовательным упорядочиванием сегментов (/S) и ре-
альными инструкциями с плавающей точкой (/R), хотя в файле конфи-
гурации  содержатся  директивы  /A  и /E, задающие упорядочивание
сегментов по алфавитному порядку и эмулирование инструкций с пла-
вающей точкой.

        Глава 3. Общие принципы программирования
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Данная глава  знакомит  вас  с  основными  принципами  Турбо
Ассемблера. Мы  сравним  режимы  Турбо  Ассемблера  Ideal и MASM,
рассмотрим, как можно комментировать программы и продолжать стро-
ки исходного кода,  использовать включаемые файлы, предопределен-
ные идентификаторы и как использовать некоторые директивы,  гене-
рирующие  информацию  для  модулей.  Хотя диапазон охваченным тем
велик, это даст вам хорошее представление о том, что собой предс-
тавляет язык ассемблера.

                Режим Ideal Турбо Ассемблера
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для тех,  кто пытается приспособить для своих целей макроас-
семблер MASM,  эта глава является,  вероятно,  наиболее  важной в
данном руководстве.  Кроме очень хорошей совместимости  с синтак-
сисом MASM, Турбо Ассемблер позволяет несколько сгладить  неудоб-
ства программирования с использованием MASM с помощью улучшенного
режима (режима Ideal).

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

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

     Благодаря строгой проверке типа, выражения режима Ideal Тур-
бо Ассемблера гораздо более понятны и менее способствуют  получе-
нию  непредвиденных  результатов.  В результате многие из проблем
MASM, о которых мы предупреждали вас в предыдущих главах, исчеза-
ют под зорким оком режима Ideal.

     Pежим Ideal содержит также ряд средств,  облегчающих процесс
программирования как для новичков,  так и для опытных пользовате-
лей. Вот некоторые из таких средств:

     * дублирование имен элементов во множественных структурах;

     * сложные выражения HIGH и LOW;

     * предсказуемая обработка директив EQU;

     * корректная обработка сгруппированных сегментов данных;

     * улучшенная содержательность директив;

     * хорошо воспринимаемые выражения,  заключенные в квадратные
       скобки.

             Для чего используется режим Ideal?
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Есть множество  причин,  по которым вам следует использовать
режим Ideal  Турбо Ассемблера.  Если вы изучаете язык Ассемблера,
то сможете легко строить для получения желаемого эффекта  выраже-
ния и  операторы  режима Ideal.  Вам не придется ходить вокруг да
около и пробовать различные варианты, пока вы не используете инс-
трукцию, которая делает именно то, что вы хотите. Если у вас име-
ется опыт программирования на Ассемблере,  то вы можете использо-
вать  средства  режима  Ideal  Турбо  Ассемблера  для  разработки
сложных программ, использующих расширения языка, такие, например,
как вложенные структуры и объединения.

     В результате  более четкого синтаксиса режим Ideal Турбо Ас-
семблера позволяет ассемблировать файлы на 30% быстрее, чем в ре-
жиме MASM. Чем больше объем ваших программ и программных комплек-
сов,  тем  больше  времени  вы  сэкономите  при  ассемблировании,
перейдя в режим Ideal.

     Строгие правила  проверки  типов,  налагаемые режимом Ideal,
позволяют Турбо Ассемблеру выявлять ошибки, которые  в  противном
случае вы обнаружили бы только при отладке вашей программы или ее
выполнении. Это аналогично тому, каким образом компиляторы языков
высокого уровня оказывают вам помощь,  отмечая сомнительные конс-
трукции и несоответствие размеров данных.

     Хотя в режиме Ideal Турбо Ассемблера в  некоторых выражениях
используется другой синтаксис,  вы,  тем не менее,  можете писать
программы,  которые будут одинаково хорошо ассемблироваться как в
режиме MASM,  так и в режиме Ideal. Вы можете также в одном и том
же исходном файле переключаться из режима MASM в  режим  Ideal  и
обратно так часто, насколько это необходимо. Это особенно полезно
при экспериментировании со средствами режима Ideal,  или при пре-
образовании имеющихся программ,  написанных в синтаксисе MASM. Вы
можете переключиться в режим Ideal в новых частях программы,  до-
бавляемых к имеющемуся исходному коду.  При этом в остальных час-
тях программы сохранится полная совместимость с MASM.

         Переключение в режим Ideal и выход из него
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для переключения  между  режимом  MASM и режимом Ideal можно
использовать директивы IDEAL и MASM. Турбо Ассемблер всегда начи-
нает ассемблирование исходного файла в режиме MASM.  Для переклю-
чения в режим Ideal перед использованием любых средств этого  ре-
жима  в  исходный  файл  нужно включить директиву IDEAL.  С этого
момента и до следующей директивы MASM все операторы  будут  вести
себя так, как описывается в данной главе. Вы можете переключаться
из режима MASM в режим Ideal в исходном файле столько раз, сколь-
ко потребуется в любом месте исходного файла. Приведем пример:

        DATA    SEGMENT         ; начало в режиме MASM
        abc     LABEL BYTE      ; abc адресуется к xyz,
                                ; как к байту
        xyz     DW      0       ; определить слово по
                                ; метке xyz
        DATA    ENDS            ; завершить сегмент
                                ; данных
                IDEAL           ; перейти в
                                ; режим Ideal
        SEGMENT CODE            ; ключевое слово SEGMENT
                                ; теперь следует первым
        PROC    MyProc          ; ключевое слово PROC
                                ; тоже следует первым
                .
                .               ; здесь можно программировать
                .               ; в режиме Ideal
        END     MyProc          ; повторение метки MyProc
                                ; необязательно
        ENDS                    ; повторение имени сегмента
                                ; не требуется
                MASM            ; переключение обратно в
                                ; режим MASM
        CODE    SEGMENT         ; перед ключевым словом SEGMENT
                                ; теперь требуется имя
        Func2   PROC            ; имя теперь также следует перед
                                ; ключевым словом PROC
                .
                .               ; программирование в режиме
                .               ; MASM
                IDEAL           ; переключение обратно в
                .               ; режим Ideal
                .               ; программирование в
                .               ; режиме Ideal
                MASM            ; возвращение в режим MASM
        Func2   ENDP            ; имя опять требуется указывать
                                ; перед ключевым словом
        CODE    ENDS            ; здесь также требуется имя

     Как вы можете заметить, в режиме Ideal ключевые слова дирек-
тив (например,  PROC или SEGMENT) указываются перед соответствую-
щими именами идентификаторов,  то есть в порядке,  обратном тому,
который принят в MASM.  Кроме того имеется возможность  повторить
имя процедуры или сегмента после директив ENDP или ENDS. Добавле-
ние этого имени идентифицирует сегмент или процедуру, которая за-
канчивается, и делает программу более понятной. Это хороший прак-
тический  прием,  особенно  в  программах,  содержащих  несколько
вложенных процедур и сегментов.  Однако указывать имя идентифика-
тора после ENDP или ENDS необязательно.

             Отличия режима Ideal и режима MASM
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В данном  разделе  мы опишем основные различия между режимом
Ideal и режимом MASM.  Если вы знакомы с MASM, то можете поэкспе-
риментировать с отдельными средствами, преобразуя небольшие части
имеющихся программ в режим Ideal.  Более подробно об отличиях ре-
жимов  рассказывается в Главе 5 "Использование выражений и значе-
ний идентификаторов".

                    Выражения и операнды
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Основное различие между выражениями режима  Ideal  и  режима
MASM  состоит в функции,  которую выполняют квадратные скобки.  В
режиме Ideal квадратные скобки  всегда  относятся  к  содержимому
заключаемой в них величины. Квадратные скобки никогда не приводят
в подразумеваемому сложению.  Однако многие стандартные конструк-
ции MASM в режиме Idealе не допускаются.

     В режиме Ideal квадратные скобки должны  использоваться  для
получения содержимого элемента. Например:

        mov     ax,wordptr

приводит к выводу предупреждающего сообщения,  если вы  пытаетесь
загрузить  указатель  (wordptr) в регистр (AX).  Корректной будет
следующая форма:

        mov     ax,[wordptr]

     Здесь ясно,  что вы загружаете содержимое ячейки, адресуемой
с помощью wordptr (в текущем сегменте данных DS) в регистр AX.

     Если вы  хотите  сослаться на смещение идентификатора в сег-
менте,  то вы должны явно использовать операцию OFFSET, например:

        mov     ax,OFFSET wordptr

                          Операции
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Изменения, внесенные  в  операции  выражений в режиме Ideal,
позволяют повысить мощность и гибкость некоторых операций,  оста-
вив без изменения общее поведение выражений.  Для того, чтобы со-
действовать некоторым комбинациям операций, изменен порядок стар-
шинства некоторых операций.

     Аккуратно задавайте точку (.) в элементах структуры,  на ко-
торые вы ссылаетесь.  Операция точки для элементов структур в ре-
жиме Ideal является более строгой. Выражение слева от точки долж-
но  представлять  собой имя элемента структуры.  Приведем примеры
загрузки регистров значениями конкретных элементов структур:

; Опишем переменные с помощью структурных типов
S_Stuff SomeStuff <>
O_Stuff OtherStuff <>
mov     ax,[S_Stuff.Amount]     ; загрузить значение размером в
                                ; слово
mov     bl,[O_Stuff.Amount]     ; загрузить значение размером в
                                ; байт

                  Подавление корректировок
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В режиме Ideal Турбо Ассемблер не генерирует сегментных кор-
ректировок для частных сегментов (private), которые выравниваются
на границу страницы или параграфа. Так как компоновщик не требует
подобных корректировок,  при  ассемблировании  программ  в режиме
Ideal может быть получен объектный код меньшего объема, компонов-
ку  которых  компоновщик  выполняет более быстро,  чем компоновку
объектных файлов,  сгенерированных в режиме MASM. Далее показыва-
ется,  каким  образом  такие  корректировки производятся в режиме
MASM (но не в режиме IDEAL):

        SEGMENT DATA PRIVATE PARA
        VAR1    DB      0
        VAR2    DW      0
        ENDS
        SEGMENT CODE
                ASSUME ds:DATA
                mov     ax,VAR2 ; корректировок не требуется
        ENDS

           Примечание: Это различие не влияет на код,  который вы
      пишете. Здесь об этом упоминается только для вашего  сведе-
      ния.

                  Операнд инструкции BOUND
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В инструкции BOUND требуется  указывать  операнд  типа  WORD
(слово), а не DWORD (двойное слово). Это позволяет вам определить
в нижнюю и верхнюю границу в виде двух констант размером в слово,
что устраняет необходимость преобразования операнда в DWORD явным
образом (с  помощью  DWORD PTR).  В режиме MASM вы должны записы-
вать:

        BOUNDS  DW      1,4        ; нижняя и верхняя границы
        BOUND   DWORD PTR BOUNDS   ; требуется в режиме MASM

     Однако в режиме Ideal требуется только записать:

        BOUNDS  DW      1,4        ; нижняя и верхняя границы
        BOUND   [BOUNDS]           ; допускается в
                                   ; режиме Ideal

                      Сегменты и группы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Способ, с помощью которого Турбо  Ассемблер  обрабатывает  в
режиме  Ideal сегменты и группы,  может внести большое различие в
формирование и выполнение программ. Как и большинству людей, вам,
вероятно,  не захочется ломать голову над ошибками,  возникающими
из-за взаимодействия сегментов и групп.

     Большинство трудностей в этом процессе возникает из-за  про-
извольного  характера предположений в MASM (и следовательно Турбо
Ассемблером в режиме MASM) о ссылках на данные или код в группах.
К счастью,  режим Ideal сглаживает некоторые наиболее явные проб-
лемы,  которые могут вызвать директивы  определения  сегментов  и
групп в MASM. Об этом мы и расскажем далее.

      Доступ к данным в сегменте, принадлежащем группе
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В режиме Ideal любой элемент данных в  сегменте,  являющемся
частью группы,  рассматривается  строго как элемент группы,  а не
сегмента.  В Турбо Ассемблере для распознавания элемента  данных,
как  элемента сегмента,  нужно использовать явное переопределение
сегмента.

     В режиме MASM это интерпретируется по-другому.  Иногда иден-
тификаторы считается частью сегмента, а не частью группы. В част-
ности,  в  режиме MASM идентификатор интерпретируется,  как часть
сегмента, когда он используется, как указатель на выделенные дан-
ные. Это может вызвать путаницу, так как когда вы непосредственно
обращаетесь к данным без операции OFFSET,  MASM некорректно гене-
рирует ссылку на сегмент вместо ссылки на группу.

     Пример поможет нам пояснить, как легко можно нажить неприят-
ности из-за специфики адресации в MASM.  Рассмотрим следующую не-
полную программу MASM, в которой описываются три сегмента данных:

     dseg1   SEGMENT para public 'data'
     v1      db      0
     dseg1   ENDS

     dseg2   SEGMENT para public 'data'
     v2      db      0
     dseg2   ENDS

     dseg3   SEGMENT para public 'data'
     v3      db      0
     dseg3   ENDS

     DGROUP  GROUP   dseg1,dseg2,dseg3
     cseg    SEGMENT para    public  'code'

             ASSUME  cs:cseg,ds:DGROUP

     start:
             mov     ax,OFFSET v1
             mov     bx,OFFSET v2
             mov     cx,OFFSET v3
     cseg    ENDS
             END     start

     Три сегмента  dseg1,  dseg2  и  dseg3 группируются под одним
именем DGROUP.  В результате все переменные  отдельных  сегментов
хранятся в памяти вместе. В исходном тексте программы в каждом из
отдельных сегментов описывается байтовая переменная (метки v1, v2
и v3).

     В коде данной программы MASM в регистры AX, BX и CX загружа-
ются смещения адресов этих переменных. В соответствии с предшест-
вующей директивой ASSUME и из-за того, что сегменты данных сгруп-
пированы  вместе,  вы  можете подумать,  что MASM будет вычислять
смещения переменных относительно всей группы,  в которой перемен-
ные очевидно хранятся в памяти.

     Но произойдет совсем не это!  Вопреки вашим намерениям  MASM
вычисляет  смещения  переменных  относительно отдельных сегментов
dseg1,  dseg2 и dseg3.  Он делает это несмотря на то, что все три
сегмента данных сгруппированы в памяти в один сегмент данных, ад-
ресуемый через регистр DS. Бессмысленно определять смещения пере-
менных относительно отдельных  сегментов в тексте программы, ког-
да  эти  сегменты  скомбинированы  в  памяти  в   один   сегмент.
Единственный  способ  ссылки на такие переменные состоит в ссылке
на их смещения относительно всей группы.

     Чтобы избавиться в MASM от этой  проблемы,  вам  потребуется
наряду с ключевым словом OFFSET задавать имя группы:

        mov     ax,OFFSET DGROUP:v1
        mov     bx,OFFSET DGROUP:v2
        mov     cx,OFFSET DGROUP:v3

     Хотя теперь  это ассемблируется корректно и загружаются сме-
щения переменных v1, v2 и v3 относительно DGROUP (где собраны от-
дельные  сегменты),  вы  можете  легко забыть задать квалификатор
DGROUP.  Если вы сделаете эту ошибку, значения смещений не позво-
лят корректно определить переменные в памяти,  и вы не получите в
MASM никакого указания,  что что-то произошло не так. Режим Ideal
позволяет избежать таких неприятностей:

             IDEAL
     SEGMENT dseg1 para public 'data'
     v1      db      0
     ENDS

     SEGMENT dseg2 para public 'data'
     v2      db      0
     ENDS

     SEGMENT dseg3 para public 'data'
     v3      db      0
     ENDS

     GROUP   DGROUP   dseg1, dseg2, dseg3
     SEGMENT cseg para public 'code'

             ASSUME  cs:cseg,ds:DGROUP

     start:
             mov     ax,OFFSET v1
             mov     bx,OFFSET v2
             mov     cx,OFFSET v3
     ENDS
             END     start

     Смещения переменных v1,  v2 и v3 корректно вычисляются отно-
сительно  группы,  в которой собраны отдельные сегменты,  которым
принадлежат переменные.  В  режиме  Ideal квалификатор DGROUP для
ссылки на переменные в сегментах группы не  требуется.  В  режиме
MASM этот квалификатор также не является необходимым, но, что ху-
же всего,  не выдается никаких предупреждений,  если вы забыли  в
конкретной ссылке определить имя группы.

                  Комментарии в программах
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Комментирование исходного кода позволяет вам (или  тому, кто
будет эти программы в последующем поддерживать) быстро разбирать-
ся в его работе.  Использование  комментариев  считается  хорошей
практикой программирования на любом языке. Они позволяют  описать
семантику (смысл), а не только синтаксис кода. Мы рекомендуем вам
широко использовать  комментарии в исходном коде Ассемблера,  и в
данном разделе описывается, как это можно сделать.

                 Комментарии в конце строки
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     Комментировать код  Ассемблера  можно несколькими способами.
Один из методов состоит в добавлении комментария в  конец строки,
используя точку с запятой, например:

     mov [bx],a1            ; записать измененный символ

     Другой способ  комментирования  исходного кода заключается в
использовании в качестве  символа комментария символа продолжения
строки (\). (См. ниже раздел "Продолжение строки").

                 Директива COMMENT
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     Директива COMMENT позволяет вам комментировать блок исходно-
го кода.  COMMENT  позволяет игнорировать весь текст,  начиная от
первого символа-ограничителя и до  строки,  содержащей  следующее
вхождение ограничителя.  В следующем примере в качестве ограничи-
теля используется символ *:

     COMMENT *
         здесь следуют замечания
     *
           Примечание: Директива COMMENT работает только в режиме
      MASM.

                  Продолжение строки
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     Для тех строк, длина которых превышает 80 символов,  в Турбо
Ассемблере предусмотрен символ продолжения \. Поскольку Турбо Ас-
семблер игнорирует любой символ, следующий за \ на данной строке,
используйте этот символ в конце строки.

     При использовании символа \ максимальная длина  строки  сос-
тавляет 1024 символа. Однако таблицы, записи и перечисления могут
содержать определения,  превышающие 1024 символа. В качестве аль-
тернативы, при  которой не накладывается ограничение в 1024  сим-
вола, можно использовать синтаксис с множественными  определения-
ми. Приведем пример такого синтаксиса (для определения enum):

     foo enum ( ;Множественная версия
          f1
          f2
          f3
          f4
          f5
          f6
          f7
          f8
          )

     Можно дать более компактную версию этого определения:

     foo enum f1,f2( ;Компактная версия
          f3,f4
          f5,f6
          f7,f8)

     При использовании  множественных определений нужно соблюдать
следующие правила:

     - левая скобка,  которая начинает определение,  должна  быть
       последней лексемой в начальной строке (однако,  это не оз-
       начает,  что она должна  предшествовать  первому  элементу
       списка);

     - в множественное определение нельзя включать такие директи-
       вы, как IF или INCLUDE.

     В режиме MASM продолжение строки можно использовать при  вы-
боре VERSION M51,M520. При это строки и другие лексемы можно раз-
мещать на нескольких строках,  используя  в  качестве  последнего
символа строки символ "\". Например:

     VERSION M51,M520
     DB 'Hello out there       \
     you guys'

     В любом  месте строки вы можете использовать стандартный ре-
жим продолжения строки Турбо Ассемблера (он всегда  доступен). Он
действует также, как комментарий, например:

     ARG    a1:word,             \ первый аргумент
            a2:word,             \ второй аргумент
            a3:word,             \ третий аргумент

              Использование включаемых файлов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Включаемые файлы позволяют вам использовать один  и  тот  же
блок кода  в  разных местах программы,  включать этот блок в нес-
кольких исходных модулях или уменьшить объем программы без  необ-
ходимости создания  нескольких компонуемых модулей. Использование
директивы INCLUDE указывает Турбо Ассемблеру, что нужно найти за-
данный файл  на  диске  и ассемблировать его,  как если бы он был
частью исходной программы.

           Примечание: Допускается вложенность  директив  INCLUDE
      на любую глубину.

     Синтаксис режима Ideal:

     INCLUDE "имя_файла"

     Синтаксис режима MASM:

     INCLUDE имя_файла

где в имени файла может задаваться дисковод, каталог или расшире-
ние. Если каталог или дисковод в имени файла не  указываются,  то
Турбо Ассемблер сначала ищет файлы в каталогах,  заданных в пара-
метре командной строки /i, а затем в текущем каталоге.

              Предопределенные идентификаторы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В Турбо  Ассемблере предусмотрено несколько предопределенных
идентификаторов, которые вы можете использовать в  программах.  В
разных местах этого кода эти идентификаторы могут иметь различное
значение.  Они аналогичны строковым присваиваниям, выполняемым по
директиве EQU. Когда Турбо Ассемблер обнаруживает в исходном фай-
ле один из этих идентификаторов, он заменяет его текущим значени-
ем данного предопределенного идентификатора.

     Некоторые из этих идентификаторов представляют собой тексто-
вые (строковые) присваивания,  другие - числовые присваивания,  а
третьи являются псевдонимами.  Строковые значения могут использо-
ваться в любом месте,  где  допускается  использование  текстовых
строк, например,  для  инициализации  последовательности байтовых
данных с помощью директивы DB:

     NOW       DB     ??time

     Числовые предопределенные значения можно использовать в  лю-
бом месте, где допустимо использование числа:

     IF   ??version GT 100h

     Значения-псевдонимы превращают  предопределенные идентифика-
торы в синоним представляемого значения,  что позволяет использо-
вать имя  предопределенного  идентификатора  в  любом месте,  где
можно использовать обычное имя идентификатора:

     ASSUME   cs:@code

     Все предопределенные идентификаторы могут использоваться как
в режиме MASM, так и в режиме Ideal.

     Если вы  при  ассемблировании используете параметр командной
строки /ml, то предопределенные идентификаторы нужно использовать
в точности так, как они описаны ниже (соблюдая регистр символов).

     К идентификаторам,  начинающимся с символа @, применимо сле-
дующее правило:  первая  буква каждого слова,  которое составляет
имя идентификатора,  указывается в верхнем регистре  (кроме  имен
сегментов), а остальная часть слова - в нижнем. Например:

     @FileName

     Заметим, что   @FileName   представляет  собой  присваивание
псевдонима для текущей ассемблируемой строки.

     Исключением являются переопределенные идентификаторы,  кото-
рые ссылаются на сегменты. Имена сегментов начинаются с символа @
и записываются символами в нижнем регистре. Например:

     @curseg
     @fardata

     У идентификаторов, начинающихся с двух вопросительных знаков
(??), все буквы должны быть в нижнем регистре, например:

     ??date
     ??version

     Заметим, что идентификатор ??date определяет текстовое прис-
ваивание, которое представляет текущую дату. Точный формат строки
даты определяется кодом страны,  установленным в DOS. Идентифика-
тор ??version позволяет вам писать исходные  файлы,  использующие
средства различных версий Турбо Ассемблера. Это присваивание поз-
воляет вам также определить,  ассемблируется ли исходный  файл  с
помощью MASM или с помощью Турбо Ассемблера,  поскольку идентифи-
катор ??version в MASM не определен. Аналогично, ??filename опре-
деляет строку  из  8 символов,  представляющую собой имя текущего
ассемблируемого файла.  Если имя файла содержит менее 8 символов,
то оно  дополняется  пробелами.  Идентификатор  ??time определяет
текстовое присваивание,  которое представляет текущее время. Точ-
ный формат строки времени определяется кодом страны,  установлен-
ным в DOS.

             Присваивание идентификаторам значений
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер предоставляет две директивы,  которые позво-
ляют присвоить идентификатору значение:  EQU и =.  Директива  EQU
определяет строковое  присваивание,  присваивание  псевдонима или
числовое присваивание. Она имеет следующий синтаксис:

     имя  EQU выражение

где "имени" присваивается результат вычисления  выражения.  "Имя"
должно быть новым идентификатором, который ранее подобным образом
не определялся.  Если первое определение представляло собой стро-
ковое присваивание,  в  режиме  MASM вы можете только переопреде-
лить идентификатор,  определенный по директиве EQU. В режиме MASM
EQU может генерировать любой из трех видов присваиваний:  строко-
вое, числовое или присваивание псевдонима.

     Директива = определяет  только  числовое  присваивание.  Она
имеет синтаксис:

     имя = выражение

где "имени" присваивается результат вычисления выражения, при вы-
числении которого должна получаться константа или адрес в сегмен-
те. "Имя"  может  быть новым идентификатором или идентификатором,
уже определенным ранее по директиве =. Поскольку директива = име-
ет намного более предсказуемое поведение, чем директива EQU в ре-
жиме MASM, по возможности используйте директиву EQU.

                 Общая структура модуля
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В Турбо Ассемблере имеется несколько директив, которые помо-
гают вам  работать  с модулями кода.  Эти директивы описываются в
оставшейся части данной главы.

                   Директива VERSION
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Использование директивы VERSION  позволяет  вам  определить,
для какой  версии  Турбо Ассемблера или MASM вы пишете конкретные
модули. Это полезно использовать для совместимости  (снизу  вверх
или наоборот) различных  версий TASM и  MASM.  Директива  VERSION
также переводит вас в режим работы заданной версии.

     Директиву VERSION  вы  можете указывать как в виде параметра
командной строки, так и в исходном коде программы.

     В исходном коде она имеет следующий синтаксис:

     VERSION <идентификатор_версии>

     Допускается задавать следующие идентификаторы версии:

           M400           MASM 4.0
           M500           MASM 5.0
           M510           MASM 5.1
           M520           MASM 5.2 (Quick ASM)
           T100           Турбо Ассемблер 1.0
           T101           Турбо Ассемблер 1.01
           T200           Турбо Ассемблер 2.0
           T250           Турбо Ассемблер 2.5
           T300           Турбо Ассемблер 3.0

     При использовании  данной  директивы  в командной строке ис-
пользуется следующий синтаксис:

     /U<номер_версии>

     Например, если вы хотите ассемблировать программу,  написан-
ную для  MASM 5.0,  то можно не изменять исходный код и указать в
командной строке параметр /uM510.

     Здесь действуют следующие правила:

     1. Директива VERSION  по  умолчанию  всегда  выбирает  режим
        MASM,  поскольку это начальный режим работы как для MASM,
        так и для Турбо Ассемблера.

     2. Директива VERSION ограничивает высокоприоритетные  ключе-
        вые  слова  теми словами,  которые доступны для заданного
        компилятора и версии,  В результате  некоторые  средства,
        которые были добавлены в последние версии,  будут вам не-
        доступны.

     3. Если в режиме Ideal вы выбираете версию < T300, то дирек-
        тива VERSION вам недоступна. В этом случае, чтобы исполь-
        зовать директиву VERSION, вы должны сначала переключиться
        в режим MASM.

     В предыдущих  версиях  Турбо Ассемблера совместимость с MASM
обеспечивалась с помощью таких директив,  как  MASM51,  MOMASM51,
QUIRKS, SMART и NOSMART. Вместо этих директив используется теперь
директива VERSION.  Полное описание ключевых  слов,  доступных  в
каждой предыдущей версии Турбо Ассемблера, можно найти в Приложе-
нии B.

                  Директива NAME
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Используйте директиву  NAME для задания имени модуля объект-
ного файла. Она имеет следующий синтаксис:

     NAME имя_модуля

           Примечание: Данная директива работает только  в режиме
      Ideal.

     Турбо Ассемблер  обычно  использует  в качестве имени модуля
имя исходного файла с дисководом,  каталогом и расширением.  Если
вы хотите изменить это используемое по умолчанию имя, укажите ди-
рективу NAME.  Новым именем модуля будет имя "имя_модуля", напри-
мер:

     NAME loader

                  Директива END
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Используйте директиву END,  чтобы отметить  конец  исходного
файла. При этом используется следующий синтаксис:

     END начальный_адрес:

где "начальный_адрес"  - это необязательный идентификатор или вы-
ражение, определяющий адрес в программе, с которого вы хотите на-
чать выполнение.  Если  ваша программа скомпонована из нескольких
исходных файлов,  начальный адрес может задаваться только в одном
из них.  Этот  адрес может представлять собой адрес в модуле.  Он
может быть также внешним идентификатором,  определенным в  другом
модуле, описанном по директиве EXTRN.

     Любой текст, указанный в исходном файле после директивы END,
Турбо Ассемблер игнорирует.

     Пример:

     .MODEL small
     .CODE
     ; тело программы
     END START               ; точка входа программы "START"
     THIS LINE IS IGNORED    ; эта строка игнорируется
     SO IS THIS ONE          ; эта строка тоже

           Вывод сообщения в процессе ассемблирования
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер обеспечивает две директивы, которые позволя-
ют вам  выводить  строку  на  консоль в процессе ассемблирования:
DISPLAY и %OUT.  Вы можете использовать эти директивы для сообще-
ний о ходе ассемблирования, о том, чтобы знать, насколько продви-
нулся процесс ассемблирования,  или чтобы определить, что достиг-
нута определенная часть кода.

     Эти две  директивы  практически представляют собой одно и то
же, но  директива DISPLAY выводит на экран строку,  заключенную в
кавычки, а %OUT - без кавычек.

     В режимах  Ideal  и  MASM  директива DISPLAY имеет следующий
синтаксис:

     DISPLAY "текст"

где "текст" - любое сообщение,  которое вы хотите вывести на  эк-
ран. Заметим,  что для вывода информации вместо экрана в файл  вы
можете использовать средство изменения направления вывода DOS.

     Директива %OUT в режимах Ideal и MASM имеет  следующий  син-
таксис:

     %OUT текст

где "текст" также представляет то, что вы хотите вывести.

              Вывод предупреждающих сообщений
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     Турбо Ассемблер предоставляет вам  выбирать  предупреждающие
сообщения (если они имеются),  которые будут выводиться в опреде-
ленных частях кода.  Каждое  предупреждающее  сообщение  содержит
трехбуквенный идентификатор,  который  вы  можете заранее задать,
чтобы Турбо Ассемблер знал,  хотите или нет вы просматривать пре-
дупреждающие сообщения этого класса.  Для разрешения предупрежда-
ющих сообщений вы можете использовать директиву WARN,  а  для  их
запрещения - NOWARN.

     Синтаксис директивы WARN следующий:

     WARN [класс_предупреждений]

где "класс_предупреждений" - это трехбуквенный идентификатор, за-
дающий конкретный тип сообщения. Допускается использовать следую-
щие классы предупреждений:

     ALN        Выравнивание сегмента
     BRK        Требуются скобки
     ICG        Неэффективная генерация кода
     LCO        Переполнение счетчика инструкций
     OPI        Открытие условного IF
     OPP        Открыть процедуру
     OPS        Открытие сегмента
     OVF        Арифметическое переполнение
     PDC        Конструкция, зависящая от прохода
     PRO        Запись в память в защищенном режиме с  исполь-
                зованием регистра CS
     PQK        Предположение  об  использовании  констант для
                [константа] предупреждение.
     RES        Предупреждение о зарезервированном слове.
     TPI        Недопустимое предупреждение Турбо Паскаля.

     Заметим, что  те  же идентификаторы используются в параметре
командной строки /W.

     Приведем пример использования директивы WARN:

     WARN  OVF       ; разрешается предупреждение о переполнении
     DW  1000-h * 123h  ; выводится предупреждение о переполнении

           Примечание: Директива  WARN  без класса предупреждений
      разрешает все предупреждения.  Директива WARN с идентифика-
      тором разрешает только указанные предупреждения.

     Для запрещения  конкретного класса предупреждающих сообщений
(или их всех) используйте директиву NOWARN. Эта директива исполь-
зует те  же  идентификаторы,  что  и описанные выше для директивы
WARN. Приведем примеры использования директивы NOWARN:

     NOWARN  OVF     ; запрещается предупреждение о переполнении
     DW  1000-h * 123h  ; не выводится предупреждение о
                        ; переполнении

            Вывод нескольких сообщений об ошибках
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     По умолчанию  Турбо  Ассемблер  допускает  вывод  для каждой
строки исходного кода только одного  сообщения  об  ошибке.  Если
строка исходного кода содержит несколько ошибок, то Турбо Ассемб-
лер сообщает сначала о наиболее существенной из  них.  С  помощью
директив MULTERRS  и NOMUTERRS вы можете управлять числом сообще-
ний об ошибках, получаемых для каждой строки исходного кода.

     Директива MULTERRS позволяет Ассемблеру сообщать  для каждой
строки исходного кода о более чем одно ошибке. Иногда это полезно
использовать для обнаружения трудноуловимой ошибки, или когда ис-
ходная строка содержит более одной ошибки.

     Заметим, что  иногда дополнительные сообщения об ошибках мо-
гут вызвать "цепную реакцию",  к которой приводит первая  ошибка.
После исправления  первой  ошибки в этом случае исчезает вся "це-
почка" ошибок.

     Приведем пример директивы MULTERRS:

     MULTERRS
     mov  ax,[bp+abc          ; порождает две ошибки:
                              ; 1) неопределенный идентификатор
                              ;    abc
                              ; 2) нужна правая квадратная
                              ;    скобка

     Директива NOMULTERRS  позволяет  выводить  для каждой строки
исходного кода только одно сообщение об ошибке или  предупреждаю-
щее сообщение.  Когда  вы  исправите эту ошибку,  могут исчезнуть
также другие сообщения об ошибках.  Однако если вы хотите опреде-
лить вывод  сообщений о самых серьезных ошибках,  нужно использо-
вать директиву MULTERRS, чтобы увидеть все сообщения об ошибках.

     Приведем пример использования директивы NOMULTERRS:

     NOMULTERRS
     mov  ax,[bp+abc          ; порождает одну ошибку:
                              ; 1) неопределенный идентификатор
                              ;    abc

      Глава 4. Объектно-ориентированное программирование
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Объектно-ориентированное программирование  -  это  подход  к
разработке программного обеспечения, основанный на объектах, а не
на процедурах. Этот подход позволяет максимизировать принципы мо-
дульности и "сокрытия информации". Объектно-ориентированное прог-
раммирование базируется на связывании или  инкапсуляции  структур
данных и процедуры, которая работает с данными в структуре, с мо-
дулем.

     Объектно-ориентированный принцип разработки дает много преи-
муществ. Например, каждый объект инкапсулирует его структуру дан-
ных с процедурой, используемой для работы с экземплярами структу-
ры данных.  Это  позволяет  устранить в коде программы внутренние
зависимости,  которые могут быстро привести  к тому, что этот код
будет трудно обслуживать.  Объекты могут также наследовать из по-
рождающего объекта структуры данных и другие  характеристики, что
позволяет сэкономить усилия и обеспечить прозрачное использование
для многих целей больших фрагментов кода.

     Если вы не имеете большого опыта работы с Турбо Ассемблером,
то можете  пропустить  данную главу,  но вернитесь к ней позднее,
после того,  как прочтете другие главы руководства.  Мы  включили
здесь эту главу, чтобы вы имели представление о данных средствах,
на объектно-ориентированное представление в Турбо  Ассемблере  на
самом деле  представляет  собой достаточно продвинутую тему.  Она
будет иметь больший смысл, когда вы изучите остальные главы руко-
водства.

                        Терминология
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для различных  единиц объектно-ориентированного программиро-
вания в C++ и Паскале  используются  различные  термины.  В  этом
смысле Турбо Ассемблер более близок к Паскалю, хотя не все терми-
ны здесь совпадают.  Различия между языками описываются в следую-
щей таблице:

     Терминология объектно-ориентированного программирования
                                                      Таблица 4.1
ЪДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДї
іТурбо Ассемблер        і   Borland C++        і Турбо Паскаль  і
ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДґ
іметод                  і   функция-элемент    і метод          і
і                       і                      і                і
іпроцедура метода       і                      і                і
і                       і                      і                і
іобъект                 і   класс              і объект         і
і                       і                      і                і
ібазовый объект         і   базовый класс      і базовый объект і
і                       і                      і                і
іпорождающий объект     і   порождающий класс  і порождающий    і
і                       і                      і  объект        і
і                       і                      і                і
іпорожденный объект     і   порожденный класс  і порожденный    і
і                       і                      і  объект        і
і                       і                      і                і
іполе порожденного      і   элемент данных     і поле           і
і объекта               і                      і                і
АДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДЩ

           Примечание: Эти термины подробнее поясняются  в данной
      главе ниже.

     Для чего в Турбо Ассемблере используются объекты?
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Большинство рассматривают  язык  Турбо Ассемблера,  как язык
низкого уровня. Однако Турбо Ассемблер обеспечивает многие средс-
тва языка  высокого  уровня  (такие как абстрактные типы данных и
простой интерфейс с другими языками).  Дополнение Ассемблера объ-
ектно-ориентированными структурами  данных  дает  ему возможность
создавать объектно-ориентированные программы так  же  легко,  как
это делается на языках высокого уровня,  с сохранением скорости и
гибкости языка Ассемблера.

                    Что такое объект?
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Объект состоит  из структуры данных и связанных с ней проце-
дур (которые называются методами),  которые работают  с  данными,
записанными в экземплярах структуры данных.

     Объект может  наследовать характеристики порождающего объек-
та. Это означает,  что структура данных нового  объекта  включает
структуру данных порождающего объекта, а также новые данные. Кро-
ме того,  новый объект может вызывать все процедуры  порождающего
объекта, а также те процедуры методов, которые в нем описываются.

           Примечание: Для объектно-ориентированного программиро-
      вания  мы  настоятельно  рекомендуем вам использовать режим
      Ideal Турбо Ассемблера,  поскольку область действия иденти-
      фикаторов в MASM является глобальной,  и вы не сможете раз-
      личить различные расположения показанных методов.

     Объект, не имеющий наследования,  называется базовым  объек-
том.  Объект, наследующий характеристики других объектов, называ-
ется порожденным или производным объектом.

     В Турбо Ассемблере определено несколько идентификаторов, ко-
торые вы можете использовать при описании объектов.  Они перечис-
лены в следующей таблице:

     Идентификаторы, определенные для объектов        Таблица 4.2
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Идентификатор              і Значение                         і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДі
і @Object                    і Текстовая макрокоманда, содержа- і
і                            і щая имя текущего  объекта  (пос- і
і                            і леднего описанного объекта).     і
і                            і                                  і
і <имя_объекта>              і Тип  данных  STRUC,  описывающий і
і                            і структуру данных объекта.        і
і                            і                                  і
і @Table_<имя_объекта>       і Тип   данных  TABLE,  содержащий і
і                            і таблицу методов объекта. Это  не і
і                            і то же самое, что экземпляр  таб- і
і                            і лицы виртуальных методов.        і
і                            і                                  і
і @TableAddr_<имя_объекта>   і Метка, описывающая адрес экземп- і
і                            і ляра  таблицы  виртуальных мето- і
і                            і дов объекта (если она есть).     і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

                       Пример объекта
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     В качестве примера использования объектов  рассмотрим  прог-
рамму, работающую со связанными списками.  Мы будем рассматривать
связанных список как объект, содержащий связанный список данных и
операций (методов), которые вы можете с ними выполнять.

     Связанный список  данных  состоит  из  указателей  на начало
("голову") и конец ("хвост") связанного списка (в  нашем  примере
из-за его  гибкости  используется  двунаправленный связанный спи-
сок).  Каждый элемент связанного списка представляет собой реали-
зацию отдельного объекта.

     Возможности, необходимые  для использования связанного спис-
ка, предоставляют следующие операции:

     - создание связанного списка (выделение для него памяти);
     - уничтожение связанного списка  (освобождение  используемой
       памяти);
     - инициализация связанного списка;
     - деинициализация связанного списка;
     - вставка элемента в середину списка перед существующим эле-
       ментом;
     - присоединение элемента к концу связанного списка;
     - удаление элемента из связанного списка;
     - возвращение первого элемента связанного списка;

     - возвращение последнего элемента связанного списка.

     Имейте в виду, что создание и инициализация, а также уничто-
жение и деинициализация методов - это не синонимы. При создании и
уничтожении методы create и destroy выделяют и освобождают память
для объекта (связанного списка),  а методы инициализации и деини-
циализации initialize и deinitialize только инициализируют и деи-
нициализируют ранее выделенные экземпляры объекта.

     Вы можете  видеть,  как объект связанного списка наследуется
объектами стека или очереди,  поскольку очередь и стек можно реа-
лизовать как  связанный  список  с  ограниченным числом операций.
Например, можно реализовать очередь в виде связанного  списка,  в
котором элементы могут добавляться к концу и извлекаться из нача-
ла. Если вы таким образом реализуете очередь,  то нужно запретить
наследуемые методы  связанного списка,  которые для очереди недо-
пустимы (например, вставку в середину списка).

                      Описание объектов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Описание объекта состоит из описаний структур данных объекта
и описаний процедур метода, которые вы можете вызывать для данно-
го объекта. Описание объекта не означает создание экземпляра объ-
екта. Как это сделать, вы узнаете позднее.

                  Описание базового объекта
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Когда вы описываете объект, Турбо Ассемблер создает структу-
ру STRUC и описывает данные для этого объекта,  и таблицу  TABLE,
которая описывает методы объекта.  Описания данных объекта предс-
тавляет собой структуру с тем же именем,  что и объект.  Описания
методов объектов записывается в типе данных TABLE с именем @Table
_<имя_объекта>.

          Примечание: Более подробно о применении к описанию объ-
     ектов директивы STRUC рассказывается в Главе 8.

     Например, для  объекта  списка  два  типа данных описываются
следующим образом:

     list          STRUC описывает следующие элементы:

                   list_head    указатель dword на начало списка
                   list_tail    указатель dword на конец списка

     @Table_list   TABLE описывает следующие методы:

                   construct    указатель dword на процедуру
                                 list_construct
                   destroy      указатель dword на процедуру
                                 list_destroy
                   и т.д.

     Директива STRUC описывает данные для объекта, которые созда-
ются каждый раз,  когда вы создаете экземпляр объекта.  Директива
TABLE  описывает  таблицу  используемых  по умолчанию для данного
описания процедур метода.  Турбо Ассемблер поддерживает этот  тип
данных,  он  не создает экземпляр таблицы где-либо в памяти прог-
раммы.  Однако позднее вы увидите,  что экземпляр  таблицы  нужно
включить для любого объекта, использующего виртуальные методы.

     Приведем пример определений объекта для связанного списка:

     list STRUC GLOBAL METHOD {
        destroy:dword = list_construct  ; процедура-конструктор
                                        ; списка
        init:dword = list_init          ; процедура-инициализа-
                                        ; тор списка
        deinit:dword = list_deinit      ; процедура-деинициали-
                                        ; затор списка
        virtual insert:word = list_insert ; процедура вставки
                                        ; узла списка
        virtual append:word = list_append ; процедура добавле-
                                        ; ния узла списка
        virtual remove:word = list_delete ; процедура удале-
                                        ; ния узла списка
        virtual first:word = list_first ; процедура первого
                                        ; узла списка
        virtual last:word = list_last   ; процедура последне-
                                        ; го узла списка
        }
        list_head     dd ?              ; указатель начала
                                        ; списка
        list_tail     dd ?              ; указатель конца
                                        ; списка

     ENDS

           Примечание: Ключевое  слово METHOD показывает,  что вы
      используете расширенную форму директивы STRUC и определяете
      объект с именем list (список).

           Примечание: Каждая  запись  состоит  из  имени метода,
      двоеточия, размера указателя на процедуру метода  (WORD для
      ближних процедур, DWORD для дальних процедур). Далее следу-
      ет символ равенства, имя процедуры и вызов этого метода.

     Давайте возьмем данный пример и посмотрим, что происходит.

     Ключевое слово METHOD указывает на вызов метода. За ним сле-
дует описаний процедур метода для данного объекта. Поскольку спи-
сок методов занимает более одной строки,  описания заключаются  в
фигурные скобки ({ }).

     Каждое описание метода сообщает Турбо Ассемблеру, какую про-
цедуру ему следует использовать для работы с объектом  при вызове
имени данного метода.

     Например, первое описание процедуры метода:

     construct:dword = list_construct

объявляет метод с именем consrtruct,  которая является процедурой
дальнего  типа  (указатель  в нее записывает DWORD).  Фактическим
именем процедуры метода является list_construct,  что следует оп-
ределить где-либо еще в исходном коде. Турбо Ассемблер рассматри-
вает метод как виртуальный,  если ему предшествует ключевое слово
VIRTUAL.  Когда  вы вызываете такой метод,  Турбо Ассемблер будет
искать адрес процедуры метода,  извлекая его из таблицы,  которая
присутствует в памяти во время загрузки. В противном случае метод
является статическим методом.  Это означает,  что Турбо Ассемблер
может определить его адрес на этапе компиляции.  Например,  метод
construct является статическим методом, а метод insert описывает-
ся как  виртуальный метод.  Позднее в этой главе мы поясним,  для
чего может понадобиться выбирать виртуальные или статические  ме-
тоды.

     Далее за  разделом описания процедуры метода непосредственно
следует структура данных.  Это определение  использует  синтаксис
стандартной директивы STRUC.  Данный пример содержит описания на-
чала и конца списка.

     В части описания метода в описании объекта, пока вы  не  ис-
пользуете виртуальные  методы,  никаких данных в структуру данных
объекта не заносится. Эти описания приводят к тому, что Турбо Ас-
семблер будет строить отдельную таблицу структуры данных, которая
содержит в качестве используемых по умолчанию значений адреса за-
данных процедур  метода.  Для каждого объекта вы должны иметь эк-
земпляр данной таблицы,  и должны явно поместить таблицу. Как это
сделать, мы поясним в данной главе позднее.

     Так как  описание должно присутствовать в модуле, содержащем
процедуры метода для объекта (а также включаться в любой  исполь-
зующий объекты исходный код),  вы должны описать сам объект в от-
дельном файле,  который может включаться (INCLUDE) в ваш исходный
код.

     Мы рекомендуем  вам использовать имя файла в виде имя_объек-
та.ASO (что означает ассемблируемый объект).  В этот файл следует
включать  только описание объекта.  Методы объекта следует разме-
щать в другом исходном файле,  благодаря чему вы можете  включать
описание  объекта там,  где это потребуется.  Например,  описание
объекта связанного списка в предыдущем примере можно было бы раз-
местить в файле LIST.ASO. Для определения процедур метода объекта
можно использовать файл LIST.ASM. В любую программу, использующую
объекты, можно было бы включить LIST.ASO, но не LIST.ASM.

     Ключевое слово  GLOBAL  в  описании объекта приводит к тому,
что Турбо Ассемблер делает эту информацию общедоступной. Это поз-
воляет вам использовать объект в модуле, отличном от того модуля,
в котором он определен.  Во все использующие объект модули должно
включаться описание объекта.

                Описание порожденного объекта
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Объект, который  наследует  методы и данные другого объекта,
называется порожденным (производным) объектом. Вы не можете пере-
определить элементы структуры данных порождающего объекта, но мо-
жете переопределить отдельные методы, задавая их в списке методов
нового объекта.

     Независимо от того, является ли объект базовым или порожден-
ным от другого объекта, его может наследовать другой объект. Нас-
ледуемый  объект  называется порождающим (родительским) объектом.
Порожденный объект наследует данные и методы порождающего  объек-
та,  поэтому  вам  следует использовать наследование только в тех
случаях, когда эти методы и данные полезны для нового объекта.

     Например, вы можете определить объект очереди,  который нас-
ледует объект связанного списка (поскольку очередь можно реализо-
вать в виде связанного списка).  Приведем пример такого порожден-
ного объекта:

     queue STRUC GLOBAL list METHOD {
        init:DWORD=queue_init
        virtual insert:word = queue_insert ; (процедура вставки
                                           ; узла очереди)
        virtual remove:word = queue_delete ; (процедура удаления
                                           ; узла очереди)
        virtual first:word = queue_first   ; (процедура первого
                                           ; узла очереди)
        virtual last:word = queue_last     ; (процедура послед-
                                           ; него узла очереди)
        virtual enqueue:word = list_append ; процедура постановки
                                           ; в очередь
        virtual dequeue:word = queue_dequeue ; процедура удаления
                                           ; из очереди

     Размещение перед ключевым словом  METHOD  объекта  с  именем
list (список) указывает Турбо Ассемблеру,  что новый объект queue
(очередь) наследует методы и данные объекта list.  Размещенный  в
этом  месте объект с любым именем будет наследоваться описываемым
объектом. Допускается использовать только одно имя (поддерживает-
ся только одиночное наследование).

     Новый объект  queue  наследует  все  данные и методы объекта
списка list (если вы их не переопределяете). Заметим, что в queue
для установки указателя на таблицу виртуальных методов для очере-
дей требуется своя собственная процедура init.

     Наследуемые для очереди  описания  методов  insert,  remove,
first и last вновь специфицируются в описании, поэтому данные ме-
тоды заменяются указанными процедурами.

     Для очереди описываются два новых метода: enqueue и dequeue.
Заметим,  что  процедура  метода  для enqueue (добавление в конец
очереди) представляет собой то же самое, что присоединение к кон-
цу списка.  Однако для извлечения из очереди (отмены постановки в
очередь) нужна новая процедура, которая называется queue_dequeue.

     Объект queue не содержит дополнительных данных,  отличных от
тех,  которые наследуются из списка list.  Он наследует указатели
начала и конца связанного списка,  которые для очереди также нуж-
ны,  поскольку методы связанного списка используются для обслужи-
вания очереди.

                   Описание процедуры методa
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

     Процедуры метода для объекта должны обеспечивать исчерпываю-
щее обслуживание объектов, то есть, они должны быть единственными
процедурами,  для который разрешен непосредственный доступ к объ-
ектам.  Кроме  того,  при построении методов следует использовать
принципы абстрактных данных: вы должны иметь  возможность  вызова
процедур метода без необходимости знать о том, как они работают и
какую имеют внутреннюю организацию.

     Что касается всех других аспектов,  то вы можете писать про-
цедуры методов на любом известном вам языке или  интерфейсе, хотя
обычно  используются соглашения по вызову C++ или Паскаля.  Аргу-
менты процедур также выбираются по вашему усмотрению.  Обычно не-
обходимым  является один аргумент - указатель на экземпляр объек-
та.  Некоторые процедуры методов могут потребовать дополнительных
параметров.  Например,  инициализация  метода  для объекта списка
требует просто указатель на объект списка,  в то время как  метод
включения в список требует указатель на список,  указатель на но-
вый узел для вставки и указатель на узел,  включаемый после него.

     В использовании статических и виртуальных методов  есть свои
достоинства и недостатки. Статические методы определяются на эта-
пе компиляции,  а результатом будет непосредственный вызов проце-
дуры  метода.  Это позволяет выполнить вызов быстрее и не требует
использования промежуточных регистров (как при использовании вир-
туальных методов).  Однако,  поскольку эти вызовы определяются на
этапе компиляции,  вызовы статических методов  не  обладают  гиб-
костью вызовов виртуальных методов.

     Вызовы виртуальных методов выполняются непосредственно через
реализацию таблицы виртуальных методов объекта. Тот факт, что вы-
зов является косвенным,  приводит к тому недостатку,  что при вы-
полнении вызова требуется использование  промежуточных  регистров
(что может усложнить код программы). Однако большим преимуществом
является то, что вызовы виртуальных методов определяются на этапе
выполнения. Таким образом, вы можете выполнять вызовы виртуальных
методов для порожденного объекта с помощью вызова  метода  общего
объекта-"предка".  При этом не требуется точно знать, с каким ви-
дом объекта-потомка вы имеете дело.

     Описание процедур статических и виртуальных методов  в  точ-
ности  совпадает  с описанием любой другой процедуры,  но имеется
следующее исключение:  если для виртуального метода вы  опускаете
имя процедуры,  то в таблице виртуальных методов создается пустая
неинициализированная ячейка, и Турбо Ассемблер не выводит вам ни-
каких предупреждений. Если метод не является виртуальным, то про-
пуск имени процедуры является ошибкой,  поскольку не  виртуальные
методы не включаются в таблицу.

     Приведем пример процедуры метода:

     ; Построение объекта связанного списка.
     ; Это метод-"конструктор".
     ; Этот метод должен быть статическим.
     ; При возврате DX:AX указывают на объект связанного списка,
     ; в противном случае это ноль.
     ; Объект выделяется, но пока не инициализируется.
     list_construct PROC PASCAL FAR
     USES ds
         ; -- Выделение объекта связанного списка --
         ;; << выполнение выделения >>
         ret
     ENDP

               Таблица виртуальных методов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Таблица виртуальных  методов (ТВМ) представляет собой табли-
цу адресов процедур, которые выполняют виртуальные методы. Обычно
данная  таблица  размещается  в сегменте данных программы.  Любой
объект,  содержащий виртуальные методы, требует, чтобы где-либо в
программе находился экземпляр таблицы виртуальных методов.

     Для создания  экземпляра таблицы виртуальных методов объекта
используется директива TBLINST.  Поскольку эта директива  создает
таблицу  для  последнего описанного объекта,  ее следует помещать
непосредственно после описания объекта, например:

     INCLUDE list.aso
     DATASEG
     TBLINST

           Инициализация таблицы виртуальных методов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Чтобы вы могли вызывать виртуальные методы, простой реализа-
ции таблицы виртуальных методов  недостаточно.  Каждый  объект  с
виртуальными  методами включает в свои структуры данных указатель
на таблицу виртуальных методов.  Когда вы создаете экземпляр объ-
екта этот  указатель нужно инициализировать.  Для этой цели можно
использовать директиву TBLINST.

     Инициализируйте указатель таблицы виртуальных методов в  ме-
тоде init следующим образом:

     ; Инициализация объекта связанного списка
     ; Это метод "init"
     ; Этот метод должен быть статическим.
     list_init PROC PASCAL FAR
     ARG @@list:dword
     USES dx,bx
          lds bx,@@list
          ; -- По адресу ds:bx инициализировать таблицу виртуаль-
          ;    ных методов.
          TBLINIT ds:bx
          ; -- Инициализировать данные объекта
          ;; << Здесь инициализируются все данные объекта >>
          ret
     ENDP

           Примечание: Заметим, что метод init должен быть стати-
      ческим, так как виртуальный метод экземпляра объекта вы вы-
      зывать не можете, пока не инициализирован указатель таблицы
      виртуальных методов.

                    Вызов метода объекта
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для вызова метода объекта используйте инструкцию  CALL.  Для
вызова  процедур  методов Турбо Ассемблер обеспечивает расширение
стандартной инструкции CALL - CALL...METHOD.

           Примечание: Синтаксис инструкции CALL для вызова  ста-
      тических и виртуальных методов совпадает.

                Вызов статического метода
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     При вызове процедуры метода,  даже если вы знаете, что вызы-
вается   статический   метод,   следует   записывать   инструкцию
CALL...METHOD,  как  если  бы вы вызывали виртуальный метод.  Это
позволит при вызове статических  методов  избежать  нежелательных
эффектов и предоставляет вам гибкость - возможность изменять ста-
тические методы на виртуальные и обратно без необходимости измене-
ния вызова метода. По этой же причине имеет смысл выбирать проме-
жуточные регистры вызова,  даже если вы  знаете,  что  вызываемый
вами метод является статическим.

     Вызовы статических методов определяются на  этапе компиляции
и  преобразуются в непосредственный вызов нужной процедуры метода
объекта.  Однако при выполнении вызова не следует вызывать проце-
дуру метода непосредственно. Вместо этого используйте расширенную
инструкцию CALL...METHOD.

     В следующей таблице показан пример вызова статического мето-
да init для объекта связанного списка:

     CALL foolist METHOD list:init pascal,ds offset foolist
     CALL es:di METHOD list:init pascal,es di

     Сам адрес вызова является адресом экземпляра  объекта.  Этот
адрес  используется только по синтаксическим причинам. Фактически
генерируемым адресом является  непосредственный  вызов  процедуры
метода.

     В данном  примере  первым вызовом является вызов метода init
объекта list. Так как это статический метод, вы выполняете непос-
редственный вызов процедуры метода list_init. Турбо Ассемблер иг-
норирует экземпляр объекта foolist (он только  передается  в  ка-
честве аргумента процедуре метода).

     За именем  вызова следует обычный расширенный параметр языка
и список параметров. Язык и параметры зависят от вызываемого вами
метода.  Один из параметров обычно является указателем на экземп-
ляр объекта.  В данном примере метод воспринимает один  параметр,
являющийся указателем на экземпляр объекта.

                  Вызов виртуального метода
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Любой вызов  виртуального  метода  требует косвенного вызова
процедуры метода.  Для этого используйте  расширенную  инструкцию
CALL...METHOD.  Для  выполнения вызова Турбо Ассемблер генерирует
следующие инструкции:

     1. Загружает промежуточные регистры указателем на ТВМ из эк-
        земпляра объекта.

     2. Выполняет косвенный вызов соответствующего элемента  таб-
        лицы.

     Таким образом, когда вы задаете:

     CALL <экземпляр> METHOD <объект>:<метод> USES :
     <вызов_проц>

то генерируются следующие инструкции:

     MOV <рег>, [<экземпляр>.<указатель_ТВМ>]
     CALL [(<сегм><рег>).<метод>] <вызыв_проц>

     Первая инструкция  загружает выбранный регистр <рег> адресом
таблицы виртуальных методов из поля указателя ТВМ структуры  объ-
екта. Вторая инструкция выполняет косвенный вызов соответствующе-
го метода в таблице.

     Например, вызов в виде:

     CALL es:di method list:insert uses ds:bx pascal,es di,es
            dx,es cx

генерирует последовательность вида:

     mov bx,[es:di.@Mptr_list]
     CALL [ds:bx.insert] pascal,es di,es dx,es cx

     Заметим, для объектов,  описанных с таблицами NEAR, инструк-
цией  CALL...METHOD  будет  загружаться  только регистр смещения.
Сегментный регистр всегда должен содержать корректное значение. В
следующем  примере показано,  как обеспечить правильную установку
сегментного регистра:

     ; Добавить узел к концу объекта связанного списка.
     ; Это виртуальный метод "list_append".
     list_append PROC PASCAL NEAR
     ARG     @@list:dword,\
             @@new:dword
     USES  dx,bx, es,di
             mov ax,@Data
             mov ds,ax
             les di,@@list
             sub ax,ax
             CALL es:di method list:insert uses DS:bx pascal, es
     di,@@new,ax ax
             ret
     ENDP

          Примечание: Пока вы не инициализируете в данных объекта
      указатель таблицы виртуальных методов,  ни один виртуальный
      метод вызвать нельзя. Это вызвано тем, что указатель загру-
      жает адрес ТВМ (из которой извлекается адрес нужной  проце-
      дуры виртуального метода). Таким образом, если вы не иници-
      ализировали указатель на таблицу виртуальных методов, любой
      вызов  виртуального  метода приведет к вызову по некоторому
      случайному адресу.

     В качестве другого примера рассмотрим  базовый  объект  node
(узел),  который вы можете включить в любой объект,  помещенный в
связанный список или очередь.

     node STRUC GLOBAL METHOD {
        construct:dword = node_construct  ; подпрограмма
                                          ; конструктора узла
        destroy:dword = node_destroy      ; подпрограмма
                                          ; деструктора узла
        init:dword = node_init            ; подпрограмма
                                          ; инициализации узла
        deinit:dword = node_deinit        ; подпрограмма
                                          ; деинициализации узла
     routine
        virtual next:word = node_adv      ; подпрограмма
                                          ; следующего узла
        virtual prev:word = node_back     ; подпрограмма
                                          ; предыдущего узла
        virtual print:word = node_print   ; подпрограмма
                                          ; содержимого узла
        }
        node_next     dd ?                ; указатель следующего
                                          ; узла
        node_prev     dd ?                ; указатель
                                          ; предыдущего узла
     ends

     Чтобы можно  было использовать связанный список или очередь,
вы можете определить любое  число  объектов,  наследующих  объект
node. Приведем два примера:

     mlabel STRUC GLOBAL node METHOD {
         virtual print:word = label_print
         }
         label_name       db 80   dup (?)
         label_addr       db 80*2 dup (?)
         label_city       db 80   dup (?)
         label_state      db 2    dup (?)
         label_zip        db 10   dup (?)
     ENDS

     book STRUC GLOBAL node METHOD {
         virtual print:word = book_print
         }
         book_title       db 80 dup (?)
         book_author      db 80 dup (?)
     ENDS

     В следующем примере вы для объектов label  и  book  вызываем
методы  путем  вызова printit.  Если "предком" является node,  не
важно,  какой объект передается printit.  Так как метод печати  -
это виртуальный метод,  вызов выполняется косвенно через ТВМ объ-
екта.  При первом вызове printit,  так как мы передаем  экземпляр
объекта label,  вызывается процедура метода label_print. При вто-
ром вызове printit вызывается процедура метода  book_print,  пос-
кольку мы передаем экземпляр объекта book.  Заметим,  что если бы
метод print был статическим,  то при вызове node_print всегда вы-
зывалась бы процедура node_print (что нежелательно).

     call printit pascal,<<адрес экземпляра объекта label>>
     call printit pascal,<<адрес экземпляра объекта book>>
     .
     .
     .
     printit proc pascal near
     arg @@obj:dword
     uses ds,si,es,bx
          mov  ax,@data
          mov  es,ax
          lds  si@@obj
          call ds:si method node:print uses es:bx pascal,ds si
          ret
     endp

             Вызов виртуальных методов "предков"
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Благодаря тому,  что вы повторно сможете использовать исход-
ный код,  применение виртуальных методов "предков"  может  помочь
вам записывать методы порожденных классов.  Например,  пока вы не
зададите, является элемент очередью или списком, для очереди мож-
но использовать те же методы вывода,  что и для списка.  В классе
списка вы можете записать:

     virtual show:word  =  list_show

а в классе очереди:

     virtual show:word  =  queue_show

     Подпрограмма list_show может печатать LIST SHOW: с последую-
щим  выводом  отдельных  элементов  списка.  Однако в порожденном
классе, если queue_show использует подпрограмму печати, она долж-
на печатать собственный заголовок QUEUE SHOW: и использовать list
_show только как механизм последовательного прохода по  списку  и
печати отдельных элементов. list_show может определить передавае-
мый ей тип структуры и в зависимости от этого  печатать заголовок
списка.  Если  подпрограмма  для list_show посмотрит на указатель
таблицы виртуальных методов передаваемой ей структуры, она сможет
определить,  совпадает ли указатель с указателем, установленным в
подпрограмме list_init для списков (или они различны).  Если ука-
затель  ТВМ в структуре не указывает на таблицу виртуальных мето-
дов для списков,  то вероятно структура является порожденным  ти-
пом.  list_show  может выполнить эту проверку с помощью следующих
операторов:

     cmp     [([es:di]).@mptr_list],offset @TableAddr_LIST
     jne     @@not_a_list  ; пропустить печать заголовка списка

             ; Если мы попали сюда, то это список, и следует
             ; распечатать его заголовок.
         ...
     @@not_a_list:
             ; Теперь вывести отдельные элементы списка.

     Как можно вызвать класс списка и метод вывода из подпрограм-
мы queue_show? Если бы вы вызвали list_show непосредственно, то в
подпрограмме могла бы возникнуть проблема, если имя используемого
для вывода метода изменилось. (Вы можете не помнить об изменениях
в  вызове  queue_show.)  Если в queue_show вы поместите следующий
оператор:

     call(es:di) method list:show

то получите бесконечный цикл,  поскольку,  хотя список задан  как
класс, для которого вызывается метод вывода, так как метод вывода
является виртуальным, будет использоваться ТВМ. Поскольку ТВМ для
структуры  указывала  бы на queue_show,  вы вернулись бы к той же
подпрограмме.

     Наилучшим способом вызова метода класса является следующий:

     call +@table_list | show

     Поскольку при описании класса list_show было задано как зна-
чение элемента вывода @table_list,  Турбо Ассемблер автоматически
транслирует данный оператор в непосредственный  вызов  list_show.
Заметим, что хотя в списке метод вывода описывается как виртуаль-
ный, задание вызова приводит к тому, что Турбо Ассемблер выполня-
ет непосредственный вызов без просмотра ТВМ.

           Примечание: Виртуальные подпрограммы обычно вызываются
      косвенным образом через просмотр ТВМ.

     В том случае, если вам нужно использовать для вывода элемен-
тов  класса  ТВМ (например,  некоторые подпрограммы инициализации
могут изменить элемент вывода в таблице,  и, в зависимости от то-
го, какое устройство используется для вывода всех элементов клас-
са,  он будет указывать на другую подпрограмму),  можно использо-
вать  следующие  операторы (которые работают для вывода элементов
класса с таблицей виртуальных методов):

     mov     bx,offset @TABLEADDR_LIST
     call    [(@table_list ptr es:bx).SHOW]

     Это аналогично последовательности инструкций,  которые Турбо
Ассемблер использует для выполнения косвенного вызова  через ТВМ.

                 Кое-что еще о вызове методов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Часто может встречаться ситуация,  когда необходимо  вызвать
метод  порождающего объекта из процедуры метода порожденного объ-
екта.  Для этого также можно использовать оператор CALL...METHOD.

     Аналогично инструкции  CALL...METHOD  вы можете использовать
расширение инструкции JMP с ключевым словом METHOD.  Эта инструк-
ция обеспечивает оптимальную рекурсию.  См. Главу 13, где об инс-
трукциях CALL...METHOD и JMP...METHOD рассказывается подробнее.

                 Создание экземпляра объекта
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Чтобы создать  экземпляр  объекта,  вы  можете вызвать метод
конструктора объекта (который выделяет память для экземпляра объ-
екта), или распределить экземпляр объекта в предопределенном сег-
менте данных.

     Вы можете создать экземпляр объекта точно также, как вы соз-
даете экземпляр структуры.  Рассмотрите,  например, следующие эк-
земпляры объектов:

     foolist   list ()                ; экземпляр списка
     fooqueue  label queue
               queue ()               ; экземпляр очереди
               queue (list_head=mynode,list_tail=mynode)
                                      ; экземпляр очереди

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

                Программирование с объектами
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Хорошо хранить  процедуры метода отдельно от описаний метода
(в отдельном файле) и отдельно от кода, использующего данный объ-
ект.  Мы  рекомендуем  помещать процедуры метода в файл с именем,
совпадающим с именем объекта,  и расширением .ASM. Например, про-
цедуры  метода  для  объекта  связанного списка можно поместить в
файл LIST.ASM.  Файл процедур метода должен включать  (с  помощью
INCLUDE) описания метода из файла .ASO.

     В конце  данной главы показан пример процедур метода объекта
списка.  Чтобы показать общую структуру файла,  приведем фрагмент
файла LIST.ASM (его можно найти в примерах на дистрибутивном дис-
ке):

      ;----------------------------------------------------
      ;-- Определение объекта связанного списка -----------
      ;----------------------------------------------------
      MODEL SMALL
      LOCALS

      ;** Определить объект связанного списка **

      INCLUSE node.aso

      ;** Создать экземпляр таблицы виртуальных методов **
      ;** связанного списка                             **

      DATASEG

      TBLINST

      ;** Методы связанного списка **

      CODESEG

      ;;<<все процедуры методов>>

     В общем случае следует использовать следующую форму объектно
-ориентированного программирования в Турбо Ассемблере

ЪДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Файл     і                     Содержимое                  і
ГДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і<объект>.ASO і INCLUDE <порождающий_объект>.ASO (если он есть),і
і             і GLOBAL описание объекта и директива  GLOBAL  дляі
і             і каждой процедуры методов.                       і
і             і                                                 і
і<объект>.ASM і INCLUDE <объект>.ASO содержит директиву  TBLINSTі
і             і и описание процедур методов, содержит метод initі
і             і c TBLINIT.                                      і
АДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Заметим, что вы  можете  использовать  директивы  TBLINST  и
TBLINIT, даже если в объекте нет виртуальных методов. В этом слу-
чае никаких действий не выполняется. Таким образом, мы рекоменду-
ем вам использовать директивы TBLINST и TBLINIT независимо от на-
личия в объекте виртуальных методов.  Поместите директиву TBLINST
в соответствующий сегмент данных, а TBLINIT - в метод инициализа-
ции объекта (который должен быть статическим). Вы должны вызывать
этот метод перед использованием всех других методов объекта.

              Пример из области программирования
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     На диске с примерами содержится исчерпывающий пример объект-
но-ориентированного программирования, в котором используются опи-
санные ранее объекты list и queue,  а также объект stack. Описан-
ный объект   node  является  базовым  объектом  для  всех  данных
пользователя, записанных в связанном списке,  очереди или  стеке.
Список соответствующих файлов примера приведен в следующей табли-
це:

     Файлы примера объектно-ориентированного программирования
                                                      Таблица 4.3
ЪДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Файл        і                    Содержимое                і
ГДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    NODE.ASO    і Описывает объект node и методы.              і
і    NODE.ASM    і Содержит методы объекта node и экземпляр таб-і
і                і лицы виртуальных методов.                    і
і                і                                              і
і    LIST.ASO    і Описывает объект list и его методы.          і
і    LIST.ASM    і Содержит методы объекта list и экземпляр таб-і
і                і лицы виртуальных методов.                    і
і                і                                              і
і    QUEUE.ASO   і Описывает объект queue и его методы.         і
і    QUEUE.ASM   і Содержит методы  объекта  queue  и  экземплярі
і                і таблицы виртуальных методов.                 і
і                і                                              і
і    STACK.ASO   і Описывает объект stack и его методы.         і
і    STACK.ASM   і Содержит методы  объекта  stack  и  экземплярі
і                і таблицы виртуальных методов.                 і
і                і                                              і
і    OOP.ASM     і Содержит пример использования этих объектов. і
АДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

 Глава 5. Использование выражений и значений идентификаторов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Выражение и идентификаторы - это основные  компоненты  прог-
раммы на языка Ассемблера.  Выражения используются для вычисления
значений и адресов в памяти.  Идентификаторы представляют различ-
ные виды значений. В данной главе описываются различные типы этих
компонентов языка и рассказывается о том, как их использовать.

                        Константы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

                     Числовые константы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Числовые константы  в  Турбо  Ассемблере всегда начинаются с
цифры (0-9) и  содержат  произвольное  число  алфавитно-цифровых
символов. Фактическое  значение  константы  зависит от основания,
которое вы выбираете для ее  интерпретации.  В  Турбо  Ассемблере
можно использовать двоичное,  восьмеричное,  десятичное или шест-
надцатиричное основание, что показано в приведенной ниже таблице:

                            Основания                 Таблица 5.1
ЪДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Основание             і   Допустимые цифры                    і
ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
ідвоичное               і   0 1                                 і
івосьмеричное           і   0 1 2 3 4 5 6 7                     і
ідесятичное             і   0 1 2 3 4 5 6 7 8 9                 і
ішестнадцатиричное      і   0 1 2 3 4 5 6 7 8 9 A B C D E F     і
АДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Заметим, что в шестнадцатиричных константах  вы  можете  ис-
пользовать буквы как в верхнем, так и в нижнем регистре.

     Турбо Ассемблер  определяет  основание  числовой  константы,
проверяя сначала последний ее символ.  Символы,  используемые для
задания основания при интерпретации константы, приведены в следу-
ющей таблице:

           Символы, определяющие основания           Таблица 5.2
ЪДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Символ          і      Основание                           і
ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і      B             і      двоичное                            і
і      O             і      восьмеричное                        і
і      Q             і      восьмеричное                        і
і      D             і      десятичное                          і
і      H             і      шестнадцатиричное                   і
АДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Для задания  основания  числа можно использовать символы как
верхнего, так и нижнего  регистра.  Последним  символом  числовой
константы должно быть одно из этих значений.  Если последним сим-
волом числовой константы не является один из  этих символов, Тур-
бо Ассемблер будет для интерпретации константы использовать теку-
щее назначенное по умолчанию основание.  Доступные числовые конс-
танты и их значения приведены в следующей таблице:

               Числовые константы                     Таблица 5.3
ЪДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
іЧисловая константа    і  Значение                              і
ГДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і      77d             і  77 десятичное                         і
і      77h             і  77 шестнадцатиричное                  і
і      ffffh           і  недопустимо, не начинается с цифры    і
і      0ffffh          і  FFFF шестнадцатиричное                і
і      88              і  интерпретация зависит от текущего ис- і
і                      і  пользуемого по умолчанию основания    і
АДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

       Изменение используемого по умолчанию основания
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для изменения  текущего используемого по умолчанию основания
вы можете использовать  директивы  RADIX  или  .RADIX.  В  режиме
Ideal используется следующий синтаксис:

     RADIX выражение

а в режиме MASM:

     .RADIX выражение

где "выражение" должно принимать значение 2 (двоичное),  8 (вось-
меричное), 10 (десятичное) или 16 (шестнадцатиричное).  Турбо Ас-
семблер предполагает,  что во время обработки директивы RADIX те-
кущим основанием по умолчанию является основание 10.

                     Строковые константы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Строковые константы  всегда начинаются с одиночной или двой-
ной кавычки и завершаются соответствующей кавычкой. Турбо Ассемб-
лер преобразует заключенные в кавычки символы в значения ASCII.

     Иногда желательно  использовать  кавычку  в  самой строковой
константе. Для этого в качестве одной  кавычки  используйте  пару
совпадающих символов кавычек, например:

     'It''s represent' It's

                     Идентификаторы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Идентификатор представляет значение,  которое может быть пе-
ременной, меткой адреса или операндом ассемблируемой инструкции и
директивы.

                  Имена идентификаторов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Имена идентификаторов  представляют  собой сочетание букв (в
верхнем и нижнем регистре),  цифр и специальных  символов.  Имена
идентификаторов не могут начинаться с цифры. Турбо Ассемблер  мо-
жет интерпретировать имена идентификаторов с  различием  регистра
символов или без него.  Различимостью регистра символов можно уп-
равлять с  помощью  параметров  командной строки Турбо Ассемблера
/ML, /MU и /MX.

     Имена идентификаторов могут иметь в длину до  255  символов.
По умолчанию  имена идентификаторов являются значащими до 32 сим-
волов. Для изменения числа значащих символов в имени  идентифика-
тора вы можете использовать параметр командной строки /MV.

           Примечание: Об   использовании   параметров  командной
      строки рассказывается в Главе 2.

     В имени идентификатора можно использовать символ подчеркива-
ния (_),  знак вопроса (?), знак доллара ($) и символ @. В режиме
MASM (и только в нем) в качестве первого символа имени  вы можете
использовать точку (.). Однако легко спутать точку в начале иден-
тификатора с операцией точки (которая используется  для выделения
элемента структуры),  поэтому  лучше  не использовать ее в именах
идентификаторов.

                   Типы идентификаторов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Каждый идентификатор имеет тип, который описывает его харак-
теристики и связанную с ним информацию. Тип задается способом оп-
ределения идентификатора.  Например, вы можете определить иденти-
фикатор, представляющий числовое выражение, текстовую строку, имя
процедуры или  переменную.  Типы идентификаторов,  поддерживаемых
Турбо Ассемблером, перечислены в Таблице 5.4.

                      Типы идентификаторов            Таблица 5.4
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і  Тип идентификатора       і Описание                           і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    адрес                  і Адрес. Подтипами  данных  являются і
і                           і типы UNKNOWN,  BYTE,  WORD, DWORD, і
і                           і PWORD, QWORD, TBYTE и адрес струк- і
і                           і туры  или таблицы с указанным име- і
і                           і нем.   Подтипами   кода   являются і
і                           і SHORT, NEAR, FAR.                  і
і                           і                                    і
і                           і                                    і
і    текстовая макрокоманда і Текстовая строка.                  і
і                           і                                    і
і    псевдоним              і Эквивалентный идентификатор.       і
і                           і                                    і
і    числовое выражение     і Значение числового выражения.      і
і                           і                                    і
і    макрокоманда из        і Несколько текстовых  строк  с пус- і
і    нескольких строк       і тыми аргументами.                  і
і                           і                                    і
і    структура/объединение  і Тип данных структуры  или  объеди- і
і                           і нения.                             і
і                           і                                    і
і    таблица                і Табличный тип данных.              і
і                           і                                    і
і    элемент структуры/     і Элемент структуры или таблицы.     і
і    таблицы                і                                    і
і                           і                                    і
і    запись                 і Данные типа записи.                і
і                           і                                    і
і    поле записи            і Поле записи.                       і
і                           і                                    і
і    перечисление           і Перечислимый тип данных.           і
і                           і                                    і
і    сегмент                і Сегмент.                           і
і                           і                                    і
і    группа                 і Группа.                            і
і                           і                                    і
і    тип                    і Названный тип.                     і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

                   Адресные подтипы данных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     Подтипы идентификаторов описывают идентификатор, представля-
ющий адрес байта,  слова и т.д. Простые адресные подтипы, которые
предусмотрены в Турбо Ассемблере, приведены в Таблице 5.5.

                        Адресные подтипы              Таблица 5.5
ЪДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і  Выражение типа   і Значение                                  і
ГДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і  UNKNOWN          і Неизвестный или  неопределенный  адресный і
і                   і подтип.                                   і
і                   і                                           і
і  BYTE             і Адрес, описывающий байт.                  і
і                   і                                           і
і  WORD             і Адрес, описывающий слово.                 і
і                   і                                           і
і  DWORD            і Адрес, описывающий 4-байтовую величину.   і
і                   і                                           і
і  PWORD или FWORD  і Адрес, описывающий 6-байтовую величину.   і
і                   і                                           і
і  QWORD            і Адрес, описывающий 8-байтовую величину.   і
і                   і                                           і
і  TBYTE            і Адрес, описывающий 10-байтовую величину.  і
і                   і                                           і
і  SHORT            і Адрес, описывающий короткий адрес  метки/ і
і                   і процедуры.                                і
і                   і                                           і
і  NEAR             і Адрес, описывающий ближний  адрес  метки/ і
і                   і процедуры.                                і
і                   і                                           і
і  FAR              і Адрес, описывающий дальний  адрес  метки/ і
і                   і процедуры.                                і
і                   і                                           і
і  PROC             і Адрес, описывающий  ближний  или  дальний і
і                   і адрес метки/процедуры, в  зависимости  от і
і                   і текущей модели.                           і
і                   і                                           і
і  DATAPTR          і Адрес, описывающий слово,  двойное  слово і
і                   і или величину pword, в зависимости от  те- і
і                   і кущей выбранной модели.                   і
і                   і                                           і
і  CODEPTR          і Адрес, описывающий слово,  двойное  слово і
і                   і или величину pword, в зависимости от  те- і
і                   і кущей выбранной модели.                   і
і                   і                                           і
і  имя структуры/   і Адрес,  описывающий  экземпляр  названной і
і  объединения      і структуры или объединения.                і
і                   і                                           і
і  имя таблицы      і Адрес,  описывающий  экземпляр  указанной і
і                   і таблицы.                                  і
і                   і                                           і
і  имя записи       і Адрес,  описывающий  экземпляр  указанной і
і                   і записи (байт, слово или двойное слово).   і
і                   і                                           і
і  имя перечисления і Адрес, описывающий экземпляр перечислимо- і
і                   і го типа данных.                           і
і                   і                                           і
і  имя типа         і Адрес, описывающий  экземпляр  указанного і
і                   і типа.                                     і
і                   і                                           і
і  TYPE выражение   і Адрес, описывающий  элемент, подтип кото- і
і                   і рого является адресом  подтипа  выражения і
і                   і (только для режима Ideal).                і
АДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

           Описание сложного адресного подтипа
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

     PTR WORD

представляет указатель на слово.  (Размер  указателя  зависит  от
размера модели сегментации, которую вы выбираете с помощью дирек-
тивы MODEL.)

     Сводный синтаксис сложных адресных подтипов приведен в  Таб-
лице 5.6.

                    Сложные адресные подтипы          Таблица 5.6
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Синтаксис                          і Значение                 і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і простой_адресный_подтип            і Подтип заданного адреса. і
і                                    і                          і
і  [раст]PTR[сложный_адресный_подтип]і Указатель   на  заданный і
і                                    і сложный адресный подтип, і
і                                    і размер которого  опреде- і
і                                    і ляется текущей  директи- і
і                                    і вой  MODEL  или заданным і
і                                    і расстоянием  (если   они і
і                                    і присутствуют).           і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Необязательный параметр расстояния вы можете описать следую-
щим путем:

                      Синтаксис расстояния           Таблица 5.7
ЪДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Синтаксис         і                  Значение                 і
ГДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і NEAR              і Используется ближний  указатель,  который і
і                   і может быть 16 или 32-разрядным, в зависи- і
і                   і мости от текущей модели.                  і
і                   і                                           і
і FAR               і Используется дальний  указатель,  который і
і                   і может быть 32 или 48-разрядным, в зависи- і
і                   і мости от текущей модели.                  і
і                   і                                           і
і SMALL NEAR        і Используется    16-разрядный    указатель і
і                   і (только для процессоров 80386 и 80486).   і
і                   і                                           і
і LARGE NEAR        і Используется    32-разрядный    указатель і
і                   і (только для процессоров 80386 и 80486).   і
і                   і                                           і
і SMALL FAR         і Используется  32-разрядный дальний указа- і
і                   і тель (только  для  процессоров  80386   и і
і                   і 80486).                                   і
і                   і                                           і
і LARGE FAR         і Используется  48-разрядный дальний указа- і
і                   і тель (только  для  процессоров  80386   и і
і                   і 80486).                                   і
АДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Тип указываемого объекта в комплексных  ссылочных  типах  не
является строго обязательным. Турбо Ассемблеру нужно знать только
размер типа.  Таким образом,  в сложных  ссылочных типах (но не в
простых типах) допускаются опережающие ссылки.

                      Выражения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Использование выражений  позволяет  вам  получать  модульный
код, поскольку  вы  можете  символически представлять в программе
значения. Турбо Ассемблер выполняет все повторные вычисления, не-
обходимые при изменениях (и не требует этого от вас).

     В присваиваниях  Турбо  Ассемблер использует стандартное ин-
фиксное обозначение. Выражения могут содержать операнды и унарные
или бинарные операции.  Унарная операция помещается перед одиноч-
ным операндом; бинарные операции помещаются между двумя операнда-
ми. Примеры простых операций показаны в Таблице 5.8.

                        Простые выражения             Таблица 5.8
ЪДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Выражение       і   Что получается при вычислении          і
ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    5               і   константа 5                            і
і    -5              і   константа -5                           і
і    4+3             і   константа 7                            і
і    4*3             і   константа 12                           і
і    4*3+2*1         і   константа 14                           і
і    4*(3+2)*1       і   константа 21                           і
АДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     В Приложении  B  содержится  полная грамматика в форме Бэку-
са-Наура, используемая при  синтаксическом  анализе  выражений  в
режимах MASM  и  Ideal.  Эта грамматика последовательно описывает
синтаксис выражений Турбо Ассемблера,  а также старшинство опера-
ций.

                    Точность в выражениях
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер в режиме Ideal всегда использует  32-разряд-
ную арифметику.  В режиме MASM Турбо Ассемблер использует 16- или
32-разрядную  арифметику,  в  зависимости  от  выбора  процессора
80386. Таким образом, некоторые выражения, в зависимости от того,
какой процессор выбирается,  могут давать разные результаты. Нап-
ример, при вычислении:

     (1000h * 1000h) / 1000h

получается 1000h  при  выборе  процессора  80386 или 0 при выборе
процессоров 8086, 80186 или 80286.

                   Константы в выражениях
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В качестве  операндов  в  выражениях  вы можете использовать
константы, например:

     mov   ax,5          ; "5" - это операнд-константа

                Идентификаторы в выражениях
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

                          Регистры
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Имена регистров  представляют регистры процессоров семейства
89086 и могут использоваться в составе выражения, например:

     5+ax+7

     При вычислении данного выражения получается  значение ax+12,
так как  AX - это зарезервированный  в Турбо Ассемблере идентифи-
катор регистра.  Идентификаторы регистров перечислены в следующем
списке:

     8086          AX, BX. CX, DX, SI, DI, DP, CS, DS, ES, SS

     80186,80286   то же, что и для 8086

     80386         регистры 8086, плюс EAX, EBX, ECX, EDX, ESI
                   EDI, EBP, PS, GS, CR0, CR3, CR3, DR0, DR1,
                   DR@, DR#, DR6, DR7

     80486         регистры процессора 80386, плюс TR3, TR4, TR5

            Стандартные значения идентификаторов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Некоторые идентификаторы всегда представляют конкретные зна-
чения, и для того, чтобы их использовать, определения не требует-
ся. Эти  идентификаторы  и  их  значения  перечислены в следующей
таблице:

                   Стандартные идентификаторы         Таблица 5.9
ЪДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Идентификатор      і      Значение                         і
ГДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    $                  і      Значение текущего счетчика адре- і
і                       і      са программы.                    і
і    NOTHING            і      0                                і
і    ?                  і      0                                і
і    UNKNOWN            і      0                                і
і    BYTE               і      1                                і
і    WORD               і      2                                і
і    DWORD              і      4                                і
і    PWORD              і      6                                і
і    FWORD              і      6                                і
і    QWORD              і      8                                і
і    TBYTE              і      10                               і
і                       і                                       і
і    NEAR               і      0ffffh                           і
і    FAR                і      0fffeh                           і
і    PROC               і      0ffffh или 0fffeh, в зависимос-  і
і                       і      ти от текущей модели.            і
і                       і                                       і
і    CODEPTR            і      2 или 4, в зависимости от теку-  і
і                       і      щей модели.                      і
і    DATAPTR            і      2 или 4, в зависимости от теку-  і
і                       і      щей модели.                      і
АДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

              Значения простых идентификаторов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер возвращает для идентификаторов,  которые ис-
пользуются сами по себе, следующие значения:

     Значения идентификаторов, используемых непосредственно

                                                     Таблица 5.10
ЪДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Выражение               і      Значение                       і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і имя_адреса              і Возвращает адрес.                   і
і                         і                                     і
і имя_числового_выражения і Возвращает значение числового выра- і
і                         і жения.                              і
і                         і                                     і
і имя_таблицы |           і Возвращает  значение  по  умолчанию і
і  имя_элемента_таблицы   і элемента таблицы, заданное в  опре- і
і                         і делении таблицы.                    і
і                         і                                     і
і структура/              і Возвращает смещение элемента в таб- і
і  имя_элемента_таблицы   і лице или структуре (только в  режи- і
і                         і ме MASM).                           і
і                         і                                     і
і имя_записи              і Возвращает маску, в  которой  биты, і
і                         і зарезервированные для представления і
і                         і битовых полей в определении записи, і
і                         і равны 1, а остальные равны 0.       і
і                         і                                     і
і имя_записи <...>        і Возвращает начальное  значение  эк- і
і                         і земпляра записи, которое  имела  бы і
і                         і эта запись, если бы она описывалась і
і                         і с текстом,  заключенном  в  угловые і
і                         і скобки  (подробности  содержатся  в і
і                         і Главе 12).                          і
і                         і                                     і
і имя_записи [...]        і Аналогично предыдущему.             і
і                         і                                     і
і имя_поля_записи         і Возвращает число  бит,  на  которое і
і                         і смещена запись от младшего бита за- і
і                         і писи (значение сдвига).             і
і                         і                                     і
і имя_перечисления        і Возвращает маску, в  которой  биты, і
і                         і требуемые для представления  макси- і
і                         і мального значения в определении пе- і
і                         і речисления  равны  1,  а  остальные і
і                         і равны 0.                            і
і                         і                                     і
і имя_сегмента            і Возвращает значение сегмента.       і
і                         і                                     і
і имя_группы              і Возвращает значение группы.         і
і                         і                                     і
і имя_структуры/          і Возвращает размер в байтах структу- і
і  объединения            і ры или объединения, но только в том і
і                         і случае, если этот размер равен 1, 2 і
і                         і или 4; в противном случае возвраща- і
і                         і ется 0.                             і
і                         і                                     і
і имя_типа                і Если тип определяется  как  синоним і
і                         і структуры или объединения, то возв- і
і                         і ращаемое значение то  же,  что и  у і
і                         і структуры или объединения.  В  про- і
і                         і тивном случае  возвращается  размер і
і                         і типа (с 0ffffh для меток   short  и і
і                         і near и 0fffeh для меток far).       і
АДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Все другие типы идентификаторов возвращают значение 0.

     Заметим, что когда в выражении вы используете  имя текстовой
макрокоманды, Турбо  Ассемблер  подставляет вместо идентификатора
текстовой макрокоманды значение текстовой макрокоманды. Аналогич-
но, когда вы используете имя псевдонима, Турбо Ассемблер подстав-
ляет вместо идентификатора  псевдонима  значение  идентификатора,
которое представляет псевдоним.

                   Унарная операция LENGTH
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Унарная операция LENGTH возвращает информацию о счетчике или
числе величин,  представляющих идентификатор. Возвращаемое факти-
ческое значение  зависит  от типа идентификатора,  что показано в
приведенной ниже таблице:

            Значения, возвращаемые операцией LENGTH  Таблица 5.11
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Выражение                     і          Значение             і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і LENGTH имя_адреса             і Возвращает счетчик элементов, і
і                               і выделяемых при    определении і
і                               і имени адреса.                 і
і                               і                               і
і LENGTH имя_элемента_структуры/і Возвращает счетчик элементов, і
і  объединения                  і выделенных   при  определении і
і                               і элемента (только режим MASM). і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     При применении  ее ко всем другим типам идентификаторов опе-
рация LENGTH возвращает значение 1.  Приведем  некоторые  примеры
использования операции LENGTH:

     MSG       DB "Hello"
     array     DW 10 DUP (4 DUP (1),0)
     numbrs    DD 1,2,3,4
     lmsg = LENGTHG msg            ; =1, нет операции DUP
     larray = LENGTH nsg           ; =10, счетчик повторения DUP
     lnumbrs = LENGTH numbrs       ; =1, нет операции DUP

     Унарная операция SIZE

     Унарная операция SIZE возвращает информацию о размере  выде-
ленного элемента  данных.  Возвращаемое  значение зависит от типа
заданного идентификатора. Список доступных для операции SIZE зна-
чений приведен в следующей таблице:
            Значения, возвращаемые операцией SZIE    Таблица 5.12
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Выражение                   і  Значение                       і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і SIZE имя_адреса             і  В  режиме  Ideal  возвращается і
і                             і  фактическое число байт,  выде- і
і                             і  ленных для переменных  данных. і
і                             і  В   режиме  MASM  возвращается і
і                             і  размер   подтипа    имя_адреса і
і                             і  (UNKNOWN=0,   BYTE=1,  WORD=2, і
і                             і  DWORD=4, PWORD=FWORD=6,  QWORD і
і                             і  =8,   TBYTE=10,    SHORT=NEAR= і
і                             і  0ffffh,   FAR=0fffeh,    адрес і
і                             і  структуры = размеру   структу- і
і                             і  ры),  умноженный  на  значение і
і                             і  LENGTH имя_адреса.             і
і SIZE имя_структуры/         і  Возвращает число байт,  требу- і
і  объединения                і  емых для представления  струк- і
і                             і  туры или объединения.          і
і SIZE имя_таблицы            і  Возвращает  число  байт, необ- і
і                             і  ходимых    для   представления і
і                             і  таблицы.                       і
і SIZE имя_элемента_таблицы/  і  Возвращает  величину  TYPE имя і
і  структуры                  і  _элемента_таблицы/структуры*   і
і                             і  LENGTH   имя_элемента_таблицы/ і
і                             і  объединения  (только  для  ре- і
і                             і  жима MASM).                    і
і SIZE имя_записи             і  Возвращает  число  байт,   не- і
і                             і  обходимых   для  представления і
і                             і  общего числа  бит,  зарезерви- і
і                             і  рованных в  определении  запи- і
і                             і  си: 1, 2 или 4.                і
і SIZE имя_перечисления       і  Возвращает  число  байт, необ- і
і                             і  ходимых    для   представления і
і                             і  максимального  значения,  при- і
і                             і  сутствующего  в  перечислении: і
і                             і  1, 2 или 4.                    і
і SIZE имя_сегмента           і  Возвращает   размер   сегмента і
і                             і  в байтах.                      і
і SIZE имя_типа               і  Возвращает  число  байт, необ- і
і                             і  ходимых   для    представления і
і                             і  названного   типа,   при  этом і
і                             і  ближние и дальние  метки  воз- і
і                             і  вращают  значение   0ffffh,  а і
і                             і  дальние - 0fffeh.              і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     При применении ко всем другим типам идентификаторов операция
SIZE возвращает значение 0.

                   Унарная операция WIDTH
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Унарная операция WIDTH возвращает размер в битах поля  запи-
си. Это значение зависит от типа идентификатора. Эти типы иденти-
фикаторов показаны в приведенной ниже таблице.  Для  всех  других
типов операцию WIDTH использовать не допускается.

                         Значения WIDTH              Таблица 5.13
ЪДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і  Выражение              і  Значение                           і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і  WIDTH имя_записи       і  Возвращает общее число  бит,  заре-і
і                         і  зервированных в определении записи.і
і                         і                                     і
і  WIDTH имя_поля_записи  і  Возвращает число бит,  зарезервиро-і
і                         і  ванных для поля в определении запи-і
і                         і  си.                                і
і                         і                                     і
і  WIDTH имя_перечисления і  Возвращает число бит,  необходимых і
і                         і  для   представления  максимального і
і                         і  значения в определении enum.       і
АДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

                    Унарная операция MASK
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Унарная операция MASK создает маску на основе битового поля,
в котором биты в возвращаемом значении устанавливаются в 1 и  со-
ответствуют битам  в  поле,  которое  представляет идентификатор.
Возвращаемое значение зависит от типа идентификатора, что показа-
но в приведенной ниже таблице. Заметим, что для всех других иден-
тификаторов использовать операцию MASK не разрешается.

               Значения, возвращаемые MASK           Таблица 5.14
ЪДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Выражение               і Значение                            і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і MASK имя_записи         і Возвращает  маску, в  которой биты, і
і                         і резервированные для представления   і
і                         і битовых полей в определении записи, і
і                         і равны 1, а остальные равны 0.       і
і                         і                                     і
і MASK имя_поля_записи    і Возвращает  маску, в  которой биты, і
і                         і резервированные для поля в определе-і
і                         і нии  записи,  равны 1,  а остальные і
і                         і равны 0.                            і
і                         і                                     і
і MASK имя_перечисления   і Возвращает  маску, в  которой биты, і
і                         і резервированные для  представления  і
і                         і максимального значения в  определе- і
і                         і нии перечисления,  равны  1,  а ос- і
і                         і тальные равны 0.                    і
АДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

              Общие арифметические операции
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

               Простые арифметические операции
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер  поддерживает  простые арифметические опера-
ции. которые приведены в следующей таблице:

               Простые арифметические операции       Таблица 5.15
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і  Выражение                   і Значение                       і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і  +выражение                  і Выражение.                     і
і                              і                                і
і  -выражение                  і Отрицание выражения.           і
і                              і                                і
і  выражение_1 + выражение_2   і Выражение_1 плюс выражение_2.  і
і                              і                                і
і  выражение_1 - выражение_2   і Выражение_1 минус выражение_2. і
і                              і                                і
і  выражение_1 * выражение_2   і Выражение_1, умноженное на вы- і
і                              і ражение_2.                     і
і                              і                                і
і  выражение_1 / выражение_2   і Выражение_1, деленное на выра- і
і                              і жение_2   (используются  целые і
і                              і числа со знаком).  Выражение_2 і
і                              і не может быть нулевым или пре- і
і                              і вышать по размеру 16 бит.      і
і                              і                                і
і  выражение_1 MOD выражение_2 і Остаток от деления выражения_1 і
і                              і на выражение_2. Применяются те і
і                              і же правила, что и при делении. і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

             Логические арифметические операции
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

            Логические арифметические операции       Таблица 5.16
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Выражение                   і Значение                        і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і NOT выражение               і Поразрядное дополнение  выраже- і
і                             і ния.                            і
і                             і                                 і
і выражение_1 AND выражение_2 і Поразрядная операция "И".       і
і                             і                                 і
і выражение_1 OR выражение_2  і Поразрядная операция "ИЛИ".     і
і                             і                                 і
і выражение_1 XOR выражение_2 і Поразрядная  операция "исключа- і
і                             і ющее ИЛИ".                      і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

                 Поразрядные операции сдвига
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Поразрядные операции  сдвига  смещают  значения  вправо  или
влево на  фиксированное число бит.  Вы можете использовать их для
быстрого выполнения операций умножения или деления или для досту-
па к битовому полю в значении.  В следующей таблице приведен спи-
сок операций сдвига.

                 Логические операции сдвига          Таблица 5.17
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Выражение                   і Значение                        і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і выражение_1 SHL выражение_2 і Выражение_1 сдвигается влево на і
і                             і число бит, заданных выражением_ і
і                             і 2 (при  отрицательном  значении і
і                             і выражения_2  выполняется  сдвиг і
і                             і вправо).                        і
і                             і                                 і
і выражение_1 SHR выражение_2 і Выражение_1  сдвигается  вправо і
і                             і на число бит,  заданных выраже- і
і                             і нием_2 (при отрицательном  зна- і
і                             і чении  выражения_2  выполняется і
і                             і сдвиг влево).                   і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

                     Операции сравнения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Операции сравнения позволяют сравнить два выражение и прове-
рить их равенство или неравенство или что одно из них больше  или
меньше другого.  Эти  операции  равны  -1,  если  условие истинно
(True), или 0 в противном случае.  Следующая таблица  показывает,
как можно использовать эти операции.

                 Операции сравнения                  Таблица 5.18
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і  Выражение                  і Значение                        і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і  выражение_1 EQ выражение_2 і -1, если выражение_1 равно вы-  і
і                             і ражению_2, в противном  случае  і
і                             і 0.                              і
і  выражение_1 NE выражение_2 і -1, если  выражение_ 1 не равно і
і                             і выражению_2, в противном случае і
і                             і 0.                              і
і                             і                                 і
і  выражение_1 GT выражение_2 і -1, если выражение_1 больше вы- і
і                             і ражения_2,  в  противном случае і
і                             і 0.                              і
і                             і                                 і
і  выражение_1 GE выражение_2 і -1, если выражение_1 больше или і
і                             і равно выражению_2, в  противном і
і                             і случае 0.                       і
і                             і                                 і
і  выражение_1 LT выражение_2 і -1, если выражение_1 меньше вы- і
і                             і ражения_2,  в  противном случае і
і                             і 0.                              і
і                             і                                 і
і  выражение_1 LE выражение_2 і -1, если выражение_1 меньше или і
і                             і равно выражения_2,  в противном і
і                             і случае 0.                       і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Операции EQ  или NE интерпретируют выражения,  как числа без
знака. Например,  -1 EQ 0ffffh имеет значение -1 (если только  вы
не выбрали процессор 80386 или не используете режим Ideal; в пос-
леднем случае значение -1 имеет выражение -1 EQ 0ffffffffh).

     Операции Gt, GE, LT и LE интерпретируют выражения, как числа
со знаком.  Например,  1 GE -1 имеет значение -1,  но 1 GE 0ffffh
имеет значение 0.

             Задание адресного подтипа выражения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер обеспечивает операции, которые позволяют вам
изменить или переопределить тип выражений.  Эти операции перечис-
лены в следующей таблице:

             Операции переопределения типа           Таблица 5.19
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і     Выражение             іЗначение                           і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
івыражение_1 PTR выражение_2іПреобразует выражение_2 к типу, оп-і
і                           іределяемому выражением_1.  При этомі
і                           і0=UNKNOWN, 1=BYTE, 2=WORD, 4=DWORD,і
і                           і6=PWORD, 8=QWORD, 10=TBYTE, 0ffffh=і
і                           іNEAR,    0fffeh=FAR,    все    про-і
і                           ічие=UNKNOWN   (только   для  режимаі
і                           іMASM).                             і
і                           і                                   і
ітип PTR выражение_2        іПреобразует  выражение  к заданномуі
і или тип выражение         іадресному подтипу (только для режи-і
і                           іма Ideal).                         і
і                           і                                   і
ітип LOW выражение          іПреобразует выражение  к  заданномуі
і                           іадресному подтипу.   Описанный  типі
і                           ідолжен быть меньше по  размеру, чемі
і                           ітип  выражения  ( только для режимаі
і                           іIdeal).                            і
і                           і                                   і
ітип HIGH выражение         іПреобразует выражение  к  заданномуі
і                           іадресному подтипу.   Описанный  типі
і                           ідолжен быть меньше по  размеру, чемі
і                           ітип  выражения.  Возвращаемый адресі
і                           інастраивается на старшую часть объ-і
і                           іекта, описанного адресным выражени-і
і                           іем ( только для режима Ideal).     і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Приведем некоторые примеры:

     IDEAL
     big DD 12345678h
     MOV ax,[WORD big]               ; ax = 5678h
     MOV al,[BYTE PTR big]           ; al = 78h
     MOV ax,[WORD HIGH big]          ; ax = 1234h
     MOV ax,[WORD LOW big]           ; ax = 5678h
     MOV al,[BYTE LOW WORD HIGH big] ; al = третьему байту big
                                     ; = 34h
     MASM:
     MOV ax,2 PTR big                ; ax = 5678h
     MOV ax,WORD PTR big             ; ax = 5678h (WORD имеет
                                     ; значение 2)

                  Получение типа выражения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В режиме MASM вы можете получить числовое значение типа  вы-
ражения путем  использования операции TYPE.  (В режиме MASM этого
сделать нельзя, поскольку типы не описываются числовыми значения-
ми.) Операция TYPE имеет следующий синтаксис:

     TYPE выражение

     Операция TYPE возвращает размер объекта,  описанный адресным
выражением:

                       Значение TYPE                 Таблица 5.20
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Выражение             і Значение                           і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    byte                  і 1                                  і
і    word                  і 2                                  і
і    dword                 і 4                                  і
і    pword                 і 6                                  і
і    qword                 і 8                                  і
і    tbyte                 і 10                                 і
і    short                 і 0ffffh                             і
і    near                  і 0ffffh                             і
і    far                   і 0fffeh                             і
і    структура/объединение і Размер  экземпляра  структуры  или і
і                          і объединения.                       і
і    таблица               і Размер экземпляра таблицы.         і
АДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Приведем пример:

     avar = 5
     darray dd 10 dup (1)
     x    struc
          dw ?
          dt ?
          ends
     fp label far
     tavar = TYPE avar                   ;  = 0
     tbvar = TYPE davar                  ;  = 4
     tx = TYPE x                         ;  = 12
     tfp = TYPE fp                       ;  = 0FFFFh

    Переопределение сегментной части адресного выражения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Адресные выражения имеют значения,  состоящие из сегмента  и
смещения. Вы  можете задавать сегмент явно в виде сегментного ре-
гистра. (Если вы задаете его,  как значение группы, Турбо Ассемб-
лер определяет,  какой  сегментный  регистр  нужно   использовать,
на   основе   предполагаемых   значение   сегментных   регистров
(ASSUME)). Для изменения сегментной части адресного выражения ис-
пользуется следующий синтаксис:

     выражение_1 : выражение_2

     Данная операция возвращает адресное  выражение, использующее
в качестве смещения выражение_2, а в качестве сегмента или значе-
ния группы - выражение_1. Например:

     VarPtr   dd  dgroup:memvar       ; dgrout - это группа
              mov cl,es[si+4]         ; переопределение сегмента
     :                                ; ES

      Получение сегмента и смещения адресного выражения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для получения сегмента и смещения адресного выражения вы мо-
жете использовать операции SEG и OFFSET.  Операция SEG возвращает
сегментную часть адресного выражения.  Она имеет  следующий  син-
таксис:

     SEG выражение

     Приведем пример исходного кода:

     DATASEG
     temp   DW 0
     CODESEG
     mov ax,SEG temp
     mov ds,ax
     ASSUME  ds:SEG temp

     Операция OFFSET возвращает смещение  адресного  выражения  и
имеет следующий синтаксис:

     OFFSET выражение

     Заметим, что когда вы используете операцию смещения,  убеди-
тесь, что выражение ссылается на  корректный  сегмент.  Например,
если вы используете режим MASM и не используете упрощенные дирек-
тивы, выражение:

     OFFSET BUFFER             ; буфер - это адрес в памяти

что не тоже самое, что:

     OFFSET DGROUP:BUFFER     ; Dgroup - это группа, содержащая
                              ; сегмент, который содержит BUFFER

(если содержащий BUFFER  сегмент  не  является  первым  сегментом
группы).

     Если вы  не переопределяете сегмент с помощью операции :,  в
режиме Ideal адреса автоматически вычисляются  относительно любой
группы, которой принадлежит сегмент. В режиме MASM это имеет мес-
то при использовании упрощенных сегментных директив.  В противном
случае адреса вычисляются относительно сегмента,  в котором нахо-
дится объект, а не какой-либо группы.

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

     Для создание адресного выражения, которое указывает на теку-
щий сегмент и счетчик  инструкций,  можно  использовать  операцию
THIS. В режиме Ideal можно использовать следующий синтаксис:

     THIS тип

     Синтаксис режима  Ideal позволяет вам строить адресное выра-
жение на основе текущего сегмента и счетчика инструкций  для  за-
данного типа.

     В режиме MASM используется следующий синтаксис:

     THIS выражение

     Синтаксис режима  MASM работает аналогично режиму Ideal,  но
для определения типа использует числовое значение  выражения. Это
следующие значения:  0=UNKNOWN, 1=BYTE, 2=WORD, 4=DWORD, 6=PWORD,
8=QQORD, 10=TBYTE, 0ffffh=NEAR, 0fffeh. Например:

     ptr1 LABEL WORD
     ptr2 EQU THIS WORD           ; аналогично ptr1

             Определение характеристик выражения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Иногда (например,  в макрокоманде) бывает полезно определить
характеристики заданного  выражения.  Для  этого  служат операции
SYMTYPE и .TYPE.

     В режиме Ideal используется следующий синтаксис:

     SYMTYPE выражение

     В режиме MASM используется следующий синтаксис:

     .TYPE выражение

     Операции SYMTYPE и .TYPE  возвращают  описывающее  выражение
значение-константу. Это значение разбивается на битовые поля, по-
казанные в следующей таблице:

            Битовые поля операций SYMTYPE и .TYPE    Таблица 5.21
ЪДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Бит   і             Значение                                  і
ГДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і 0     і  Выражение является относительным указателем памяти в і
і       і  программе.                                           і
і       і                                                       і
і 1     і  Выражение является  относительным указателем на дан- і
і       і  ные в программе.                                     і
і       і                                                       і
і 2     і  Выражение представляет собой значение-константу.     і
і       і                                                       і
і 3     і  Выражение использует прямой режим адресации.         і
і       і                                                       і
і 4     і  Выражение содержит регистр.                          і
і       і                                                       і
і 5     і  Идентификатор определен.                             і
і       і                                                       і
і 7     і  Выражение содержит идентификатор, определенный извне.і
АДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Если биты 2 и 3 равны нулю,  то выражение содержит косвенный
регистр ([BX]).

     Если Турбо Ассемблер не может вычислить выражение, то опера-
ция SYMTYPE  возвращает  соответствующие ошибки.  Однако операция
.TYPE в этих случаях будет возвращать значение (обычно 0).

Ссылки на структуры,  объединения и смещения элементов в таблице
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Элементы структур, объединений и таблиц являются глобальными
переменными, значения которых представляют собой  в  режиме  MASM
смещения в  структуре,  объединении или таблице.  Однако в режиме
Ideal элементы этих типов данных рассматриваются,  как  локальные
по отношению к типам данных. Операция точки (.) позволяет вам по-
лучить смещения элементов.  В режиме Ideal используется следующий
синтаксис:

     выражение.идентификатор

где "выражение" представляет адрес структуры, объединения или эк-
земпляра таблицы.  "Идентификатор" должен быть элементом структу-
ры, объединения  или таблицы.  Операция точки возвращает смещение
элемента в структуре.

     В режиме MASM также имеется версия операции точки. Однако ее
функция аналогична операции + и имеет следующий синтаксис:
     выражение_1 + выражение_2

                 Описание содержимого адреса
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Многие инструкции позволяют вам различать адрес и содержимое
адреса. Вы можете делать это, используя квадратные скобки. Напри-
мер:
     MOV  AX,BX           ; переместить BX в AX
     MOV  AX,[BX]         ; переместить в AX содержимое по
                          ; адресу BX

     Приведем общий синтаксис,  в котором используются квадратные
скобки:

     [выражение]

     В режиме  MASM  квадратные скобки для выражений,  являющихся
адресами, не обязательны.  В качестве операнда инструкции процес-
соров 80х86  не  может использоваться полный адрес.  Вместо этого
используется только сегмент (полученный с помощью  операции  SEG)
или смещение (полученное с помощью операции OFFSET).

     Если ясно,  что  выражение  является  адресом,  а квадратные
скобки не используются, то в режиме Ideal выводится предупреждаю-
щее сообщение. Это предупреждение можно запретить (см. Главу 12).
Однако хорошей практикой программирования  является использование
скобок.

                  Подразумеваемое сложение
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В режиме MASM сложение выражений можно выполнять несколькими
способами: с  помощью  операции сложения (+),  с помощью операции
точки (.),  или с помощью  подразумеваемого  (неявного)  сложения
(когда  выражения  разделяются  квадратными и круглыми скобками).
Например:

     MOV AX,5[BX]           ; содержимое по адресу BX+5
     MOV AX,5[XYZ]          ; содержимое по адресу XYZ+5

     Неявная операция сложения имеет следующий общий синтаксис:

     выражение_1 [выражение_2]
или
     выражение_1 (выражение_2)

  Получение значения старшего или младшего байта выражения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     Для возврата значения старшего или младшего  байта выражения
можно использовать операции HIGH и LOW.  Это обстоятельство может
быть полезно,  например, в ситуации, когда требуются только стар-
шие 8 бит смещения адреса.

     Приведем пример операций HIGH и LOW:

     HIGH выражение
     LOW выражение

     Например:

     magic equ  1234h
     mov  cl,HIGH magic                ; cl = 12h
     mov  cl,LOW magic                 ; cl = 34h

           Задание 16- или 32-разрядных выражений
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Если текущим  выбранным процессором является процессор 80386
или старше,  то Турбо Ассемблер предоставляет две операции, кото-
рые определяют, будет выражение интерпретироваться как 16- или 32
-разрядное  значение.  Это операции SMALL и LARGE. Они имеют сле-
дующий синтаксис:

     SMALL выражение
     LARGE выражение

     Операция SMALL  помечает   выражение,   как   представляющее
16-разрядное значение. Операция LARGE помечает его как 32-разряд-
ное значение. Эти операции особенно важны в программах, при рабо-
те  которой  в  операционной  среде  некоторые  сегменты являются
32-битовыми, а другие - 16-битовыми. Например, инструкция:

     JMP [DWORD PTR ABC]

представляет собой косвенный переход на содержимое  переменной  в
памяти ABC.  Если у вас разрешено использование процессора 80386,
то данная инструкция может интерпретироваться  либо  как  дальний
переход с  использованием сегмента и 16-разрядного смещения, либо
как ближний переход  по 32-разрядному  смещению.  Для  устранения
неоднозначности вы можете использовать операции LARGE и SMALL:

     JMP SMALL [DWORD PTR ABC]

     Данная инструкция приводит к ассемблированию Турбо Ассембле-
ром инструкции перехода таким  образом, что значение, считываемое
из ABC,  интерпретируется как 16-разрядный сегмент и 16-разрядное
смещение. При этом Турбо Ассемблер  выполняет  косвенный  переход
типа FAR (дальний переход).

     При использовании  операций SMALL или LARGE в адресной части
смещения, эти операции указывают,  что адрес является  32-разряд-
ным, например:

     JMP SMALL [LARGE DWORD PTR ABC]

указывает, что переменную в памяти ABC описывает 32-разрядный ад-
рес, но ее содержимое интерпретируется как 16-разрядный сегмент и
16-разрядное смещение.

Глава 6. Директивы выбора процессора и идентификаторы процессора
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Процессор 8086 представляет собой на самом деле  только один
из процессоров семейства iAPx86. Это семейство включает в себя:

     - процессор 8088 (который содержит 8-разрядную шину данных),
       8086 (содержит 16-разрядную шину данных);

     - процессоры 80186 и 80188 (аналогичны  процессорам  8086  и
       8088,  но  содержат  дополнительные  инструкции и работают
       быстрее своих предшественников);

     - процессор 80286 (который содержит  инструкции  защищенного
       режима);

     - процессор  80386 (который может обрабатывать 16- и 32-раз-
       рядные данные);

     - процессор 80486 (улучшенная версия процессора 80386, кото-
       рая отличается более высокой скоростью работы).

     Математические сопроцессоры,  такие как 8087, 80287 и 80387,
работающие с процессорами семейства iAPx86,  позволяют  выполнять
операции с плавающей точкой.

     В Турбо  Ассемблере предусмотрены директивы и предопределен-
ные идентификаторы, которые позволяют вам использовать инструкции
конкретного процессора. Эти директивы и идентификаторы описывают-
ся в данной главе.

                 Директивы процессоров iAPx86
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Процессоры семейства  iAPx86  предусматривают  использование
множества директив. Заметим, что директивы, начинающиеся с точки,
доступны только в режиме MASM.

           Примечание: Список инструкций, допустимых для конкрет-
      ных процессоров, можно найти в Главе 1.

           Директивы выбора процессоров iAPx86        Таблица 6.1
ЪДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Директива      і  Значение                                    і
ГДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і P8086          і  Разрешает ассемблирование только инструкций і
і                і  процессора 8086.                            і
і                і                                              і
і .8086          і  Разрешает ассемблирование инструкций проце- і
і                і  ссора 8086 и запрещает все инструкции, дос- і
і                і  тупные только на процессорах 80186, 80286 и і
і                і  386. Разрешает также ассемблирование  инст- і
і                і  рукций сопроцессора 8087, так же как  инст- і
і                і  рукции .8087 или 8087.                      і
і                і                                              і
і P186           і  Разрешает  ассемблирования  инструкций про- і
і                і  цессора 80186.                              і
і                і                                              і
і .186           і  Разрешает  ассемблирования  инструкций про- і
і                і  цессора 80186.                              і
і                і                                              і
і P286           і  Разрешает ассемблирование  всех  инструкций і
і                і  процессора 80286.                           і
і                і                                              і
і P286N          і  Разрешает ассемблирование непривилегирован- і
і                і  ных (реальный  режим) инструкций процессора і
і                і  80286 и инструкций  арифметического  сопро- і
і                і  цессора 80287.                              і
і                і                                              і
і P286P          і  Разрешает  ассемблирование   всех  (включая і
і                і  защищенный режим)   инструкций   процессора і
і                і  80286  и  инструкций арифметического сопро- і
і                і  цессора 80287.                              і
і                і                                              і
і .286           і  Разрешает ассемблирование непривилегирован- і
і                і  ных инструкций  процессора  80286 (реальный і
і                і  режим) и инструкций арифметического  сопро- і
і                і  цессора 80287, так же как директива P287.   і
і                і                                              і
і .286C          і  Разрешает ассемблирование непривилегирован- і
і                і  ных инструкций процессора  80286  (реальный і
і                і  режим)  и инструкций арифметического сопро- і
і                і  цессора 80287.                              і
і                і                                              і
і .286P          і  Разрешает  ассемблирование  всех инструкций і
і                і  процессора 80286 (включая защищенный режим) і
і                і  и инструкций  арифметического  сопроцессора і
і                і  80287, как директивы .287 или .P287.        і
і                і                                              і
і P386           і  Разрешает  ассемблирование  всех инструкций і
і                і  процессора 386.                             і
і                і                                              і
і P386N          і  Разрешает ассемблирование непривилегирован- і
і                і  ных (реальный  режим) инструкций процессора і
і                і  386.                                        і
і                і                                              і
і P386P          і  Разрешает ассемблирование всех (включая за- і
і                і  щищенный режим) инструкций процессора 386.  і
і                і                                              і
і                і                                              і
і .386           і  Разрешает ассемблирование непривилегирован- і
і                і  ных инструкций  процессора  80386 (реальный і
і                і  режим), включая все дополнительные инструк- і
і                і  ции, и инструкций арифметического сопроцес- і
і                і  сора 80387е, как директивы .387 и P387.     і
і                і                                              і
і .386C          і  Разрешает ассемблирование инструкций проце- і
і                і  ссора 80386.                                і
і                і                                              і
і .386P          і  Разрешает ассемблирование  всех  инструкций і
і                і  процессора 80386 (включая защищенный режим) і
і                і  и инструкций  арифметического  сопроцессора і
і                і  80387, как директивы .387 и P387.           і
і                і                                              і
і P486           і  Разрешает ассемблирование  всех  инструкций і
і                і  процессора i486 (включая защищенный режим). і
і                і                                              і
і P486N          і  Разрешает ассемблирование непривилегирован- і
і                і  ных инструкций  процессора  i486  (реальный і
і                і  режим).                                     і
і                і                                              і
і .486           і  Pазрешает   ассемблирование  дополнительных і
і                і  инструкций   процессора,     поддерживаемых і
і                і  процессором 80486 в непривилегированном ре- і
і                і  жиме.  Разрешает также инструкции сопроцес- і
і                і  сора 3867, как директивы .387 и P387.       і
і                і                                              і
і .486C          і  Разрешает ассемблирование  всех  инструкций і
і                і  процессора i486.                            і
і                і                                              і
і .486P          і  Разрешает ассемблирование  всех  инструкций і
і                і  процессора 80486 (включая защищенный режим) і
і                і  и инструкций  арифметического  сопроцессора і
і                і  80487, как директивы .487 и P487.           і
АДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

               Предопределенные идентификаторы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Два предопределенных   идентификатора   @Cpu   и   @WordSize
позволяют вам получить информацию о типе используемого процессора
или размере текущего сегмента. Приведем описание этих идентифика-
торов.

                     Идентификатор @Cpu
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Числовое значение,  возвращающее информацию о теку-
щем процессоре.

     Замечания: Значение, возвращаемое @Cpu, дает в битовых полях
информацию о типе процессора:

        ЪДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
        і  Бит      і    Описание                          і
        ГДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
        і   0       і    Разрешены инструкции процессора   і
        і           і    8086.                             і
        і           і                                      і
        і   1       і    Разрешены инструкции процессора   і
        і           і    80186.                            і
        і           і                                      і
        і   2       і    Разрешены инструкции процессора   і
        і           і    80286.                            і
        і           і                                      і
        і           і                                      і
        і   3       і    Разрешены инструкции процессора   і
        і           і    80386.                            і
        і           і                                      і
        і   4       і    Разрешены инструкции процессора   і
        і           і    i486.                             і
        і           і                                      і
        і   7       і    Разрешены привилегированные       і
        і           і    инструкции процессоров (80286,    і
        і           і    386, 486).                        і
        і           і                                      і
        і   8       і    Разрешены инструкции математи-    і
        і           і    ческого сопроцессора 8087.        і
        і           і                                      і
        і           і                                      і
        і   10      і    Разрешены инструкции математи-    і
        і           і    ческого сопроцессора 80287.       і
        і           і                                      і
        і   11      і    Разрешены инструкции математи-    і
        і           і    ческого сопроцессора 80387.       і
        АДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Не определенные здесь биты зарезервированы для будущего  ис-
пользования.  При  использовании идентификатора @Cpu замаскируйте
их, это обеспечит совместимость вашей программы с будущими верси-
ями Турбо Ассемблера.

     Так как семейство процессоров 8086  совместимо  снизу-вверх,
то когда вы разрешаете тип процессора по директиве .286,  автома-
тически разрешаются  также  младшие  типы  сопроцессоров   (8086,
80186).

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

     Пример:

     IPUSH = @Cpu AND 2       ; разрешает непосредственную
                              ; инструкцию push процессора
                              ; 186 и старше
     IF IPUSH
     PUSH  1234
     ELSE
           mov  ax,1234
           push ax
     ENDIF

                   Идентификатор @WordSize
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Функция: Числовое значение, указывающее 16- или 32-разрядные
сегменты.

     Примечания: @WordSize возвращает значение  2,  если  текущим
сегментом является 16-разрядный сегмент, и 4, если это 32-разряд-
ный сегмент.

     Пример:

     IF @WordSize EQ 4
         mov esp,0100h
     ELSE
        mov sp,0100h
     ENDIF

                 Директивы сопроцессора 8087
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Имеющиеся директивы  задания сопроцессора перечислены в сле-
дующей таблице.  Заметим,  что директивы,  начинающиеся с  точки,
доступны только в режиме MASM.

                  Директивы сопроцессора 8087         Таблица 6.2
ЪДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Директива      і  Значение                                    і
ГДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і .287           і  Разрешает ассемблирование  всех  инструкций і
і                і  арифметического сопроцессора 80287. Исполь- і
і                і  зуйте данную директиву, если вы знаете, что і
і                і  вам не потребуется запускать  программы  на і
і                і  машине с сопроцессором 8087.  Данная дирек- і
і                і  тива приводит к оптимизации инструкций. При і
і                і  этом они становятся несовместимыми с сопро- і
і                і  цессором 8087.  Поэтому не используйте дан- і
і                і  ную  директиву,  если ваши программы должны і
і                і  работать на сопроцессоре 8087.              і
і                і                                              і
і .387           і  Разрешает ассемблирование  всех  инструкций і
і                і  арифметического сопроцессора 80387. Исполь- і
і                і  зуйте данную директиву, если вы знаете, что і
і                і  вам не потребуется запускать  программы  на і
і                і  машине с сопроцессором 8087.  Данная дирек- і
і                і  тива приводит к оптимизации инструкций. При і
і                і  этом они становятся несовместимыми с сопро- і
і                і  цессором 8087.  Поэтому не используйте дан- і
і                і  ную  директиву,  если ваши программы должны і
і                і  работать на сопроцессоре 8087.              і
і                і                                              і
і .8087          і  Разрешает  ассемблирование инструкций ариф- і
і                і  метического сопроцессора  и  запрещает  все і
і                і  инструкции,   доступные  для  сопроцессоров і
і                і  80287 и 80387. Этот режим инструкций сопро- і
і                і  цессора  используется  Турбо Ассемблером по і
і                і  умолчанию.                                  і
і                і                                              і
і P287           і  Разрешает  ассемблирование инструкций ариф- і
і                і  метического сопроцессора 80287.             і
і                і                                              і
і P387           і  Разрешает  ассемблирование инструкций ариф- і
і                і  метического сопроцессора 80287.             і
і                і                                              і
і P8087          і  Разрешает  ассемблирование только  инструк- і
і                і  ций арифметического  сопроцессора  8087.  В і
і                і  Турбо Ассемблере этот режим  назначается по і
і                і  умолчанию.                                  і
АДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

                 Директивы эмуляции сопроцессора
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Если вам  нужны  реальные инструкции с плавающей точкой,  то
нужно использовать сопроцессор 8087.  Если у вас установлен пакет
программной эмуляции  инструкций  с плавающей точкой,  то для его
использования можно указать директиву EMUL. (Директива EMUL рабо-
тает аналогично параметру /e).

           Примечание: Директивы EMUL и NOEMUL работают как в ре-
      жиме MASM, так и в режиме Ideal.

     Например:

     Finit                  ; реальные инструкции сопроцессора
                            ; 8087
     EMUL
     Fsave BUF              ; эмулируемая инструкция

     При использовании  сопроцессора 8087 вы можете либо эмулиро-
вать инструкции с плавающей точкой с помощью директивы EMUL, либо
принудительно использовать  инструкции  с  плавающей точкой с по-
мощью директивы NOEMUL.  Заметим, что вы можете использовать инс-
трукции EMUL  и  NOEMUL,  когда  хотите генерировать инструкции с
плавающей точкой для одной части файла и  эмулируемые  инструкции
для другой.

     Приведем пример использования инструкции NOEMUL:

     NOEMUL            ; ассемблировать реальные инструкции
                       ; с плавающей точкой
     finit
     EMUL              ; вернуться к эмуляции

Глава 7. Использование моделей памяти программы и сегментации
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Каждый процессор семейства 80х86 имеет не менее 4 сегментных
регистров (CS,  DS, ES и SS). Эти регистры содержат значение сег-
мента,  которое описывает физический блок памяти объемом  до  64К
(или  до 4 гигабайт в процессоре 80386 и старше).  Все адреса вы-
числяются с использованием в качестве базового значения одного из
сегментных регистров.

     Смысл значения записанного в сегментном регистре бывает раз-
личным и зависит от используемого в процессоре режиме адресации -
реального (это единственный режим, который может использоваться в
процессорах 8086 и 80186), когда сегментное значение представляет
собой фактический номер параграфа,  или защищенного режима, когда
сегментный регистр содержит селектор (не имеющий числового значе-
ния).

     Операционная система или среда программы определяет, работа-
ет программа в реальном или защищенном режиме. Если вы используе-
те защищенный режим процессоров 80386 или 80486,  то операционная
система определяет также, допустимы ли большие сегменты (до 4 ги-
габайт). Турбо  Ассемблер  в  одинаковой степени поддерживает все
эти операционные среды.

     В случае общей модели 80х86 программы состоят из  одного или
более сегментов,  где каждый сегмент представляет собой физически
различные части кода или данных (или код  и  данные),  к  которым
можно обращаться  через сегментный регистр.  На основе этой общей
схемы можно построить много производных схем.  Чтобы  упорядочить
их, разработаны стандартные схемы памяти. Так как этих соглашений
придерживаются многие языки высокого уровня,  в программах на Ас-
семблере также следует это делать.

     Один из  очевидных способов состоит в разбиении программы на
инструкции программы и ее данные. Каждый фрагмент данных програм-
мы можно  определить как инициализированный (содержащий начальные
значения, например,  текстовое сообщение) и  неинициализированный
(не содержащий начального значения). Турбо Ассемблер обычно прис-
ваивает неинициализированным данным  отдельный  сегмент,  который
можно разместить  в  конце программы,  уменьшив объем выполняемой
программы.

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

     Можно также комбинировать сегменты  в  группы.  Преимущество
использования групп состоит в том,  что вы можете задать сегмент-
ное значение для всех сегментов группы.  Например,  инициализиро-
ванные данные, неинициализированные данные и сегменты стека часто
комбинируются в группы таким образом,  что для всех данных  прог-
раммы можно использовать одно и то же значение сегмента.

     В данной  главе описывается,  как использовать в вашей прог-
рамме модели и сегменты, и какие директивы позволяют это делать.

                       Директива MODEL
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Директива MODEL позволяет вам задать для программы несколько
стандартных моделей сегментации.  Вы можете также использовать ее
для задания языка для процедур программы.

     Директива MODEL имеет следующий синтаксис:

     MODEL [модификатор_модели] модель_памяти
        [имя_сегмента_кода] [,[модификатор_языка] язык]
           [, модификатор_модели]

     В режиме  MASM  используется тот же синтаксис,  но директива
имеет вид .MODEL.

     "Модель_памяти" и  "модификатор_модели"  определяют   модель
сегментации памяти, используемую в программе.

     В применяемых  в  Турбо Ассемблере стандартных моделях можно
использовать специальные сегменты для:

     - кода;

     - инициализированных данных;

     - неинициализированных данных;

     - инициализированных данных дальнего типа;

     - неинициализированных данных дальнего типа;

     - констант;

     - стека.

     Сегмент кода содержит обычно код модуля (но при необходимос-
ти может также содержать данные). В целях совместимости с языками
высокого уровня инициализированные данные и константы интерпрети-
руются по-разному. Они содержат такие данные, как сообщения, ког-
да важно начальное значение.  Неинициализированные данные и  стек
содержат данные,  начальные значения которых не существенны. Ини-
циализированные данные дальнего типа (far) - это  неинициализиро-
ванные данные,  которые  не являются частью стандартного сегмента
данных, и которые доступны только при изменении значения сегмент-
ного регистра.  Это  же  относится  к неинициализированным данным
дальнего типа,  только вместо инициализированных данных здесь со-
держатся неинициализированные данные.

     Специальные модели памяти задают, как можно ссылаться на эти
сегменты с помощью сегментных регистров, и как они объединяются в
группы (если это имеет место).  При написании программы вы должны
хранить эти сегменты отдельно,  независимо от размера  программы.
Затем  для объединения сегментов в группы вы можете выбрать соот-
ветствующую модель. Если вы храните эти сегменты раздельно, и ва-
ша  программа  увеличивается  в  размере,  вы можете использовать
большую модель.

     Единственным обязательным параметром директивы MODEL являет-
ся модель памяти.  Каждая стандартная модель памяти описывается в
Таблице 7.1.

     Поле "модификатор_модели" позволяет вам  изменить  отдельные
аспекты модели.  Вы  можете  задавать при необходимости несколько
модификаторов модели.  Доступные модификаторы модели приведены  в
Таблице 7.2.

     Заметим, что  в целях совместимости с MASM 5.2 вы можете за-
давать спецификатор модели в двух местах.  Если вы не используете
спецификатор модели,  Турбо  Ассемблер подразумевает спецификатор
NEARSTACK и USE32 (при выборе процессоров 80386 или  80486). Если
не задано обратное, то основой считается DOS.

     В больших  моделях кода для переопределения используемого по
умолчанию имени сегмента кода  используется  необязательное  поле
"имя_сегмента_кода". Обычно  это  имя  модуля  с присоединенным к
нему именем _TEXT.

                    Стандартные модели памяти         Таблица 7.1
ЪДДДДДДДДДВДДДДДДДДДВДДДДДДДДВДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДї
іМодель   і Код     іДанные  іПредполагаемыеіОписание           і
і         і         і        ірегистры      і                   і
ГДДДДДДДДДЕДДДДДДДДДЕДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДґ
іTINY     і ближний іближний іcs=dgroup     іВесь код и все дан-і
і         і         і        іds=ss=dgroup  іные   комбинируютсяі
і         і         і        і              ів одну   группу   сі
і         і         і        і              іименем  DGROUP. Этаі
і         і         і        і              імодель используетсяі
і         і         і        і              ідля  программ,  ас-і
і         і         і        і              ісемблируемых в фор-і
і         і         і        і              імат .COM. Некоторыеі
і         і         і        і              іязыки эту модель неі
і         і         і        і              іподдерживают.      і
і         і         і        і              і                   і
ГДДДДДДДДДЕДДДДДДДДДЕДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДґ
іSMALL    і ближний іближний іcs=_text      іКод    представляеті
і         і         і        іds=ss=dgroup  ісобой один сегмент.і
і         і         і        і              іВсе данные комбини-і
і         і         і        і              іруются  в  группу сі
і         і         і        і              іименем  DGROUP. Этоі
і         і         і        і              інаиболее  общая мо-і
і         і         і        і              ідель, использующая-і
і         і         і        і              іся  для  автономныхі
і         і         і        і              іпрограмм на Ассемб-і
і         і         і        і              ілере.              і
і         і         і        і              і                   і
ГДДДДДДДДДЕДДДДДДДДДЕДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДґ
іMEDIUM   і дальний іближний іcs=           іДля кода  использу-і
і         і         і        і<модуль>_text іется несколько сег-і
і         і         і        іds=ss=dgroup  іментов,  по  одномуі
і         і         і        і              іна модуль.   Данныеі
і         і         і        і              інаходится  в группеі
і         і         і        і              іс именем DGROUP.   і
і         і         і        і              і                   і
ГДДДДДДДДДЕДДДДДДДДДЕДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДґ
іCOMPACT  і ближний ідальний іcs=_text      іКод находится в од-і
і         і         і        іds=ss=dgroup  іном  сегменте.  Всеі
і         і         і        і              іближние данные  на-і
і         і         і        і              іходятся  в группе сі
і         і         і        і              іименем  DGROUP. Дляі
і         і         і        і              іссылки на    данныеі
і         і         і        і              іиспользуются  даль-і
і         і         і        і              іние указатели.     і
і         і         і        і              і                   і
ГДДДДДДДДДЕДДДДДДДДДЕДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДґ
іLARGE    і дальний ідальний іcs=           іДля кода  использу-і
і         і         і        і<модуль>_text іется несколько сег-і
і         і         і        іds=ss=dgroup  іментов,  по  одномуі
і         і         і        і              іна модуль.      Всеі
і         і         і        і              іближние  данные на-і
і         і         і        і              іходятся в  группе сі
і         і         і        і              іименем  DGROUP. Дляі
і         і         і        і              іссылки  на   данныеі
і         і         і        і              іиспользуются  даль-і
і         і         і        і              іние указатели.     і
і         і         і        і              і                   і
ГДДДДДДДДДЕДДДДДДДДДЕДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДґ
іHUGE     і дальний ідальний іcs=           іТо же,  что  модельі
і         і         і        і<модуль>_text іLARGE (что касаетсяі
і         і         і        іds=ss=dgroup  іТурбо Ассемблера). і
і         і         і        і              і                   і
ГДДДДДДДДДЕДДДДДДДДДЕДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДґ
іTCHUGE   і дальний ідальний іcs=           іЭто    эквивалентноі
і         і         і        і<модуль>_text імодели LARGE,  но сі
і         і         і        іds=nothing    ідругими предположе-і
і         і         і        іss=nothing    іниями о  сегментныхі
і         і         і        і              ірегистрах.         і
і         і         і        і              і                   і
ГДДДДДДДДДЕДДДДДДДДДЕДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДґ
іTPASCAL  і ближний ідальний іcs=code, ds   іЭта модель поддер- і
і         і         і        і=data, ss=    іживается    раннимиі
і         і         і        іnothing       іверсиями Турбо Пас-і
і         і         і        і              ікаля. В более позд-і
і         і         і        і              іних версиях не тре-і
і         і         і        і              ібуется.            і
і         і         і        і              і                   і
ГДДДДДДДДДЕДДДДДДДДДЕДДДДДДДДЕДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДґ
іFLAT     і ближний іближний іcs=_text      іТо же, что и модельі
і         і         і        іds=ss=flat    іSMALL, но  подходиті
і         і         і        і              ідля использования ві
і         і         і        і              іOS/2.              і
АДДДДДДДДДБДДДДДДДДДБДДДДДДДДБДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДЩ

                       Модификаторы модели            Таблица 7.2
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Модификатор модели      і Функция                          і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    NEARSTACK               і Указывает, что сегмент стека дол-і
і                            і жен включаться   в   DROUP  (еслиі
і                            і группа DGROUP присутствует), а SSі
і                            і должен указывать на DGROUP.      і
і                            і                                  і
і    FARSTACK                і Указывает, что сегмент  стека  неі
і                            і должен включаться в  DGROUP, а SSі
і                            і должен указывать  не  nothing (неі
і                            і определен).                      і
і                            і                                  і
і    USE16                   і Задает,    что   все  сегменты  ві
і                            і выбранной модели должны быть  16-і
і                            і разрядными (при выборе процессораі
і                            і 80386 или 80486).                і
і                            і                                  і
і    USE32                   і Задает,    что   все  сегменты  ві
і                            і выбранной модели должны быть  32-і
і                            і разрядными (при выборе процессораі
і                            і 80386 или 80486).                і
і                            і                                  і
і    DOS, OS_DOS             і Задает, что прикладная  программаі
і                            і ориентируется на DOS.            і
і                            і                                  і
і    OS2, OS_OS2             і Задает, что прикладная  программаі
і                            і ориентируется на DOS.            і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     "Язык" и  "модификатор_языка"  вместе определяют соглашения,
используемые при вызове процедуры,  а также используемый по умол-
чанию характер начала и завершения кода каждой процедуры. Они оп-
ределяют также как будут объявляться  общедоступные идентификато-
ры (которые   использует   компоновщик).  Турбо  Ассемблер  будет
автоматически генерировать код входа и выхода для каждой процеду-
ры, используя одно из следующих языковых соглашений:  PASCAL,  C,
CPP (C++),  SYSCALL, BASIC, FORTRAN, PROLOG и NOLANGUAGE (язык не
задан). Если вы не задаете язык,  то Турбо Ассемблер предполагает
использование NOLANGUAGE.

     Используйте "модификатор_языка" для задания  кода  начала  и
завершения процедур  для WIndows или оверлейного загрузчика фирмы
Borland. Можно задавать  параметры  NORMAL,  WINDOWS,  ODDNEAR  и
ODDFAR. Если вы не задаете параметр,  то Турбо Ассемблер по умол-
чанию подразумевает NORMAL.

           Примечание: Более подробно об  этом  рассказывается  в
      Главе 16.

     Кроме того, вы можете переопределить используемый по умолча-
нию язык  и модификатор языка при определении процедуры.  Подроб-
ности можно узнать в Главе 10.

     При объявлении общедоступного идентификатора вы можете также
переопределить язык.

        Идентификаторы, генерируемые директивой MODEL
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Когда вы используете директиву MODEL, Турбо Ассемблер созда-
ет и инициализирует отдельные переменные,  отражающие детали выб-
ранной модели.  Эти переменные путем использования операторов ус-
ловного ассемблирования могут вам помочь написать  код, зависящий
от модели. О том, как можно использовать эти переменные для изме-
нения процесса ассемблирования, рассказывается в Главе 15.

                    Идентификатор @Model
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Идентификатор @Model содержит числовое значение, представля-
ющее текущую используемую модель.  Вы  можете  задавать  его  как
текстовую макрокоманду с одним из следующих значений:

     1  =  действует модель tiny (крошечная)
     2  =  действует модель small (малая) или flat
     3  =  модель compact (компактная)
     4  =  medium (средняя)
     5  =  large (большая)
     6  =  huge (огромная)
     7  =  tchuge  (Турбо Си)
     0  =  tpascal (Турбо Паскаль)

                    Идентификатор @32Bit
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Идентификатор @32Bit содержит значение,  определяющее, явля-
ются ли сегменты в текущей модели 16- или 32-разрядными.  Если вы
задали в модели MODEL 16-разрядные сегменты, то это значение рав-
но 0, а если 32-разрядные - то 1.

                   Идентификатор @CodeSize
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Идентификатор @CodeSize  указывает используемый по умолчанию
размер указателя кода в текущей модели памяти. Если он установлен
в 0, то модели памяти используют ближние указатели кода типа NEAR
(модeли TINY, SMALL, FLAT, COMPACT, TPASCAL), а значение 1 указы-
вает, что  модели  памяти  используют  дальние указатели FAR (все
другие модели).

                   Идентификатор @DataSize
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Идентификатор @DataSize указывает используемый по умолчанию
размер указателя данных в текущей модели памяти. Если он установ-
лен в 0, то модели памяти используют ближние указатели данных ти-
па NEAR (модeли TINY,  SMALL, FLAT, COMPACT, TPASCAL), а значение
1  указывает,  что модели памяти используют дальние указатели FAR
(все другие модели).

                  Идентификатор @Interface
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Идентификатор @Interface  дает информацию о языке и операци-
онной системе,  которые выбраны в операторе MODEL. Данная тексто-
вая макрокоманда содержит число,  биты которого представляют сле-
дующие значения:

                       Модификаторы модели            Таблицы 7.3
ЪДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і Биты 0-7       і  Значение                                    і
ГДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    0           і  NOLANGUAGE                                  і
і    1           і  C                                           і
і    2           і  SYSCALL                                     і
і    4           і  PASCAL                                      і
і    5           і  FORTRAN                                     і
і    6           і  BASIC                                       і
і    7           і  PROLOG                                      і
і    8           і  CPP                                         і
АДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Бит 8 имеет нулевое значение для DOS и равен 1 для OS/2.

     Например, значение идентификатора @Interface показывает, что
вы выбрали операционную систему OS/2 и язык Си.

               Упрощенные сегментные директивы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     После выбора модели памяти вы можете использовать упрощенные
сегментные директивы для того, чтобы начинать отдельные сегменты.
Эти упрощенные директивы вы можете использовать только после  ди-
рективы MODEL,  которая задает для модуля модель памяти. В модуле
допускается указывать столько директив сегментации, сколько необ-
ходимо. Турбо Ассемблер для получения одного сегмента комбинирует
все части с одинаковыми именами (как если бы  вы  ввели  все  эти
фрагменты  после одной директивы сегментации).  Перечень директив
содержится в Таблице 7.4.

ЪДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Директива            і Описание                            і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    CODESEG [имя]        і Начинает или продолжает сегмент кодаі
і                         і модуля.  Для моделей с дальним типомі
і                         і кода вы можете задать имя, являющее-і
і                         і ся фактическим именем сегмента.  За-і
і                         і метим,  что  таким образом вы можетеі
і                         і генерировать для модуля более одногоі
і                         і сегмента кода.                      і
і                         і                                     і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    .CODE [имя]          і Эквивалентна директиве  CODESEG. До-і
і    DATASEG              і пускается только  для  режима  MASM.і
і                         і Начинает  или продолжает ближний илиі
і                         і инициализируемый по  умолчанию  сег-і
і                         і мент данных.                        і
і                         і                                     і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    .DATA                і Эквивалентна директиве  DATASEG. До-і
і    CONST                і пускается только  для  режима  MASM.і
і                         і Начинает или    продолжает   сегменті
і                         і констант модуля.  Постоянные  данныеі
і                         і всегда  являются  ближними  (NEAR) иі
і                         і эквивалентны инициализированным дан-і
і                         і ным.                                і
і                         і                                     і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    .CONST               і Эквивалентна  директиве  CONST.  До-і
і    UDATASEG             і пускается только  для  режима  MASM.і
і                         і Начинает или  продолжает ближний илиі
і                         і не  инициализируемый  по   умолчаниюі
і                         і сегмент данных.  Соблюдайте осторож-і
і                         і ность и  включайте  в  этот  сегменті
і                         і только  неинициализированные данные,і
і                         і в противном случае получаемая выпол-і
і                         і няемая программа будет иметь большийі
і                         і чем нужно размер. Описание распреде-і
і                         і ления   неинициализированных  данныхі
і                         і можно найти в Главе 12.             і
і                         і                                     і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    .DATA?               і Эквивалентна   директиве   UDATASEG.і
і                         і Действует только для режима MASM.   і
і                         і                                     і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    STACK [размер]       і Начинает  или   продолжает  сегмент і
і                         і стека модуля.  Необязательный  пара-і
і                         і метр "размер" определяет  объем  ре-і
і                         і зервируемой для стека памяти (в сло-і
і                         і вах).  Если вы  не  задаете  размер,і
і                         і Турбо Ассемблер резервирует по умол-і
і                         і чанию 200h слов (1 килобайт).       і
і                         і                                     і
і                         і В режиме MASM  все  метки,  код  илиі
і                         і данные,   следующие   за  операторомі
і                         і STACK,  не будут рассматриваться какі
і                         і часть сегмента стека. Однако в режи-і
і                         і ме Ideal  резервируется  специальнаяі
і                         і область,  и  сегмент  стека остаетсяі
і                         і открытым,  благодаря чему вы  можетеі
і                         і добавлять метки и другие неинициали-і
і                         і зированные данные.                  і
і                         і                                     і
і                         і Директивы стека обычно требуется ис-і
і                         і пользовать,  если вы пишете на языкеі
і                         і Ассемблера   автономную   программу.і
і                         і Большинство  языков  высокого уровняі
і                         і сами создают для вас стек.          і
і                         і                                     і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    .STACK [размер]      і Эквивалентна директиве  STACK.  Дей-і
і                         і ствует в режиме MASM.               і
і                         і                                     і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    FARDATE [имя]        і Начинает или продолжает  дальний не-і
і                         і инициализированный сегмент    данныхі
і                         і (FAR) с заданным именем.  Если вы неі
і                         і задаете имя, Турбо Ассемблер исполь-і
і                         і зует сегментное имя FAR_DATA.  В мо-і
і                         і дуле может содержаться  более одногоі
і                         і неинициализированного  сегмента дан-і
і                         і ных типа FAR.                       і
і                         і                                     і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    .FARDATA [имя]       і Эквивалентна  FARDATA.  Действует  ві
і                         і режиме MASM.                        і
і                         і                                     і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    UFARDATA             і Начинает или продолжает дальний  не-і
і                         і инициализированный сегмент  данных сі
і                         і заданным именем.  Если вы не задаетеі
і                         і имя, то Турбо  Ассемблер  используеті
і                         і имя сегмента FAR_BSS. В модуле у васі
і                         і может быть несколько неинициализиро-і
і                         і ванных сегментов данных типа FAR.   і
і                         і                                     і
ГДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    .FARDATA? [имя]      і Эквивалентна   UFARDATA.   Действуеті
і                         і только в режиме MASM.               і
АДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

           Примечание: Если  вам требуется знать фактические име-
      на,  имена классов и выравнивание сегментов, создаваемых по
      упрощенным директивам сегментации, см. Приложение A.

Идентификаторы, создаваемые упрощенными директивами сегментации
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Когда вы используете упрощенные директивы  определения  сег-
ментов, они  создают переменные,  отражающие детали распределения
сегмента (аналогично тому,  как это делает директива MODEL). Под-
робнее об этом рассказывается в Главе 15.

     Идентификаторы упрощенных директив сегментации   Таблица 7.5
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Идентификатор          і Значение                          і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    @code                  і Сегмент или группа, которые подра-і
і                           і зумеваются для сегмента CS.       і
і                           і                                   і
і    @data                  і Сегмент или группа, которые подра-і
і                           і зумеваются для сегмента DS.       і
і                           і                                   і
і    @fardata               і Имя текущего сегмента FARDATA.    і
і                           і                                   і
і    @fardata?              і Имя текущего сегмента UFARDATA.   і
і                           і                                   і
і    @curseg                і Имя текущего сегмента.            і
і                           і                                   і
і    @stack                 і Сегмент или группа, которые подра-і
і                           і зумеваются для сегмента SS.       і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

                    Директива STARTUPCODE
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Директива STARTUPCODE обеспечивает код инициализации,  соот-
ветствующий текущей  модели и операционной системе.  Она отмечает
также начало программы. Эта директива имеет следующий синтаксис:

     STARTUPCODE

или

     .STARTUP            ; (только для режима MASM)

     Директива STARTUPCODE инициализирует регистры DS,  SS и  SP.
Для моделей SMALL,  MEDUIUM, COMPACT, LARGE, HUGE и TPASCAL Турбо
Ассемблер устанавливает DS и SS в @data,  а SP - в  конец  стека.
Для моделей  TINY и TCHUGE директива STARTUPCODE не изменяет сег-
ментных регистров.

                   Идентификатор @Startup
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Идентификатор @Startup  помещается в начало кода инициализа-
ции,  который генерируется по директиве STARTUPCODE. Он представ-
ляет собой ближнюю метку, отмечающую начало программы.

                     Директива EXITCODE
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Директива EXITCODE используется для генерации кода  заверше-
ния, соответствующего  текущей  операционной  системе.  Вы можете
использовать ее в модуле несколько раз (для каждой  точки входа).
Эта директива имеет следующий синтаксис:

     EXITCODE [возвращаемое_значение]

     В режиме MASM вы можете использовать следующий синтаксис:

     .EXIT [возвращаемое_значение]

     Необязательное "возвращаемое_значение" описывает число,  ко-
торое должно возвращаться в операционную систему.  Если вы не за-
даете возвращаемое  значение,  Турбо Ассемблер предполагает,  что
это значение содержится в регистре AX.

             Определение общих сегментов и групп
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

                   Директива SEGMENT
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Директива SEGMENT открывает сегмент. Все последующие код или
данные до директивы ENDS,  которая закрывает сегмент, будут вклю-
чены в этот сегмент.

     В режиме Ideal директива SEGMENT имеет следующий синтаксис:

     SEGMENT имя [атрибуты]

     В режиме MASM директива SEGMENT имеет следующий синтаксис:

     имя SEGMENT [атрибуты]

где "имя" - это имя сегмента.  Назначать сегментам имена нужно  в
соответствии с  их  использованием.  Примеры имен сегментов можно
найти в Приложении A.

     В одном сегменте вы можете несколько раз открыть  и  закрыть
сегмент с одним и тем же именем. Турбо Ассемблер выполняет конка-
тенацию всех частей сегмента.  Атрибуты сегмента  нужно  задавать
только при первом его открытии.

     Атрибуты могут  включать  в  себя все или некоторые значения
атрибутов сегмента, которые определяют следующее:

     - атрибут комбинирования сегмента;

     - атрибут класса сегмента:

     - атрибут выравнивания сегмента;

     - атрибут размера сегмента;

     - атрибут доступа к сегменту.

           Примечание: Заметим,  что Турбо Ассемблер обрабатывает
      значения атрибутов слева-направо.

              Атрибут комбинирования сегментов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

      Атрибут комбинирования сегментов сообщает компоновщику, как
нужно комбинировать сегменты различных модулей, имеющих одно и то
же имя.  Допустимые значения атрибута комбинирования сегмента пе-
речисляются в следующем списке. Заметим, что если вы не указывае-
те этот атрибут, Турбо Ассемблер предполагает PRIVATE.

                 Атрибут комбинирования сегмента      Таблица 7.6
ЪДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і   Атрибут         і Значение                                  і
ГДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і   PRIVATE         і Сегмент не будет комбинироваться с други- і
і                   і ми сегментами с тем же именем вне данного і
і                   і модуля.  Будет  выполняться  конкатенация і
і                   і сегмента с сегментами с тем же именем вне і
і                   і данного  модуля  для  образования  одного і
і                   і непрерывного сегмента.                    і
і                   і                                           і
ГДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і   MEMORY          і То же, что PUBLIC. Будет выполняться кон- і
і                   і катенация  сегмента  с другими сегментами і
і                   і с тем же  именем вне данного модуля   для і
і                   і образования одного непрерывного сегмента, і
і                   і используемого как сегмент  стека.  Компо- і
і                   і новщик  инициализирует регистры SS SP на- і
і                   і чальными значениями,  так что  они указы- і
і                   і вают на конец данного сегмента.           і
і                   і                                           і
ГДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і   COMMON          і Располагает данный сегмент и  все  другие і
і                   і сегменты с тем же именем по одному  адре- і
і                   і су.  Все  сегменты  с данным именем будут і
і                   і перекрываться  и  совместно  использовать і
і                   і общую  память.  Размер  полученного в ре- і
і                   і зультате сегмента будет равен размеру са- і
і                   і мого большого сегмента модуля.            і
і                   і                                           і
ГДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і   VIRTUAL         і Определяет специальный  вид сегмента, ко- і
і                   і торый должен описываться внутри охватыва- і
і                   і ющего сегмента. Компоновщик интерпретиру- і
і                   і ет его как общую область  и  присоединяет і
і                   і его к охватывающему сегменту. Виртуальный і
і                   і сегмент наследует свои атрибуты из  охва- і
і                   і тывающего   сегмента.   Директива  ASSUME і
і                   і рассматривает  виртуальный  сегмент   как і
і                   і часть порождающего сегмента. Во всех дру- і
і                   і гих отношениях виртуальный сегмент предс- і
і                   і тавляет собой общую область памяти, кото- і
і                   і рая используется разными  сегментами. Это і
і                   і позволяет организовать совместное исполь- і
і                   і зование статических данных,  которые  бе- і
і                   і рутся  различными  модулями из включаемых і
і                   і файлов.                                   і
і                   і                                           і
ГДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і   AT xxx          і Располагает сегмент по абсолютному адресу і
і                   і параграфа. Адрес задается параметром xxx. і
і                   і Компоновщик для сегмента AT  не порождает і
і                   і никаких данных или кода.  Используйте ди- і
і                   і рективу AT  для  организации  доступа  по і
і                   і идентификатору  к  фиксированным  адресам і
і                   і памяти (например,  экран дисплея или  об- і
і                   і ласти ПЗУ).                               і
АДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

                   Атрибут класса сегмента
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Атрибут класса  сегмента - это заключенная в кавычки строка,
которая помогает компоновщику определить  соответствующий порядок
сегментов при  собирании  их в программу из модулей.  Компоновщик
объединяет вместе в памяти все сегменты с одним и тем  же  именем
класса. Типичным  примером  использования  имени  класса является
объединение в группу всех сегментов кода  программы  (обычно  для
этого используется класс CODE).  С помощью механизма класса груп-
пируются также данные и неинициализированные данные.

                Атрибут выравнивания сегмента
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Атрибут выравнивания  сегмента  сообщает  компоновщику,  что
нужно обеспечить размещение начала сегмента на  заданной границе.
Это важно,  поскольку при правильном выравнивании доступ к данным
в процессорах 80х86 выполняется быстрее. Допустимые значения это-
го атрибута приведены в следующей таблице:

                  Атрибут выравнивания сегмента       Таблица 7.7
ЪДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і     Атрибут          і Значение                               і
ГДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і     BYTE             і Выравнивание не  выполняется.  Сегмент і
і                      і начинается с границы следующего байта. і
і                      і                                        і
і     WORD             і Начинает сегмент на границе следующего і
і                      і слова.                                 і
і                      і                                        і
і     DWORD            і Начинает сегмент на границе следующего і
і                      і двойного слова.                        і
і                      і                                        і
і     PARA             і Начинает сегмент на границе следующего і
і                      і параграфа (выравнивание на 16 байт).   і
і                      і                                        і
і     PAGE             і Начинает сегмент на границе  следующей і
і                      і страницы (выравнивание на 256 байт).   і
і                      і                                        і
і     MEMPAGE          і Начинает сегмент на границе  следующей і
і                      і страницы памяти (выравнивание на 4 ки- і
і                      і лобайта).                              і
АДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Если вы не задаете тип выравнивания,  Турбо Ассемблер подра-
зумевает PARA.

                  Атрибут размера сегмента
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Если текущим   выбранным   процессором   является  процессор
80386, то сегменты могут быть 16- или 32-разрядными. Размер атри-
бута сегмента  сообщает компоновщику,  какой размер вы хотите за-
дать для конкретного сегмента.  Допустимые значения атрибута при-
ведены в следующей таблице:

               Значения атрибута размера сегмента     Таблица 7.8
ЪДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Атрибут    і Значение                                      і
ГДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    USE16      і Сегмент будет 16-разрядным. Такой сегмент мо- і
і               і жет содержать до 64К кода или данных.         і
і               і                                               і
і    USE32      і Сегмент будет 32-разрядным. Такой сегмент мо- і
і               і жет содержать до 4 гигабайт кода или данных.  і
АДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Если в режиме MASM вы выбираете процессор  80386,  то  Турбо
Ассемблер предполагает использование USE32.  В режиме Ideal Турбо
Ассемблер по умолчанию предполагает использование USE32.

                 Атрибут доступа к сегменту
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В защищенном режиме для любого сегмента вы  можете управлять
доступом к определенным операциям с памятью,  запрещая их. (Заме-
тим,  что данное средство поддерживается в настоящее время только
компоновщиком Phar Lap.  Если требуется использовать атрибут дос-
тупа к сегменту, вы должны компилировать совместимый с ним объек-
тный  код с помощью параметра командной строки /op.) Атрибут дос-
тупа к сегменту  сообщает  компоновщику,  что  к  сегменту  нужно
применить специальные ограничения доступа.

     Допустимые значения данного атрибута приведены  в  следующей
таблице:

               Значения атрибута доступа к сегменту   Таблица 7.9
ЪДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Атрибут    і Значение                                      і
ГДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    EXECONLY   і Сегмент доступен только для выполнения.       і
і               і                                               і
і    EXECREAD   і Сегмент доступен только для чтения и выполне- і
і               і ния.                                          і
і               і                                               і
і    READONLY   і Сегмент доступен только для чтения.           і
і               і                                               і
і    READWRITE  і Сегмент доступен только для чтения и записи.  і
АДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Если вы  выбираете  один  из  этих атрибутов или используете
USE32, компоновщик Phar Lap предполагает,  что сегмент предназна-
чен для выполнения в защищенном режиме.  Если вы выбираете USE32,
но не задаете одно из этих значений, Турбо Ассемблер предполагает
использование атрибута READONLY.

                     Директива ENDS
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Вы можете использовать директиву ENDS для закрытия сегмента,
после чего  данные  в него больше включаться не будут.  Директиву
ENDS следует использовать для закрытия любого сегмента, открытого
по директиве SEGMENT. Сегменты, открытые с помощью упрощенных ди-
ректив определения сегментов, не требуют директивы ENDS.

     Директива ENDS имеет следующий синтаксис:

     ENDS [имя]

     В режиме MASM вы можете использовать следующий синтаксис:

     имя ENDS

где "имя" задает имя сегмента,  который должен быть закрыт.  Если
имя не  согласуется  с именем текущего открытого сегмента,  Турбо
Ассемблер будет выводить сообщение об ошибке. Если имя не задает-
ся, Турбо Ассемблер подразумевает текущий сегмент.

                     Директива GROUP
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Директива GROUP может использоваться для  присваивания  сег-
ментов группам.  Группы позволяют вам для доступа ко всем сегмен-
там группы задавать один сегмент.

     В режиме Ideal директива GROUP имеет следующий синтаксис:

     GROUP имя имя_сегмента [, имя_сегмента...]

     В режиме MASM вы можете использовать следующий синтаксис:

     имя GROUP имя_сегмента [, имя_сегмента...]

где "имя" представляет собой имя группы,  а "имя_сегмента" -  это
имя сегмента, которое вы хотите присвоить группе.

                     Директива ASSUME
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Если вы хотите получить доступ к данным сегмента, сегментный
регистр должен  загружаться корректным значением сегмента.  Часто
это нужно делать вам самим.  Например,  для загрузки в регистр DS
адреса текущего сегмента данных дальнего типа вы можете использо-
вать команды:

     MOV   AX,@fardata
     MOV   DS,AX

     Когда программа загружает в сегментный регистр значение сег-
мента, вы можете использовать этот сегментный регистр для доступа
к данным в сегменте. Это быстро утомляет, и вы начинаете забывать
каждый раз при обработке данных в памяти задавать сегментный  ре-
гистр (или у вас недостаточно практики в программировании).

     Чтобы указать Турбо Ассемблеру, что нужно связать сегментный
регистр с  именем  сегмента  или  группы,  используйте  директиву
ASSUME. Это  позволяет Турбо Ассемблеру быть "достаточно проница-
тельным" и использовать при доступе к данным конкретный сегмент.

     Фактически, Турбо Ассемблер использует  также  информацию  о
связи между  сегментным  регистром  и именем сегмента также и для
других целей: в режиме MASM значение, которое подразумевается для
регистра CS, используется для определения сегмента или группы,  к
которому принадлежит метка. Таким образом, регистр CS должен кор-
ректно задаваться  в  директиве ASSUME,  в противном случае Турбо
Ассемблер при каждом определении метки или процедуры будет  сооб-
щать об ошибке.

     Директива ASSUME имеет следующий синтаксис:

     ASSUME сегм_регистр : выражение [, сегм_регистр : выражение]

или
     ASSUME nothing

где "сегм_регистр" - это один из регистров CS, DS, ES или SS. Ес-
ли вы  задаете процессор 80386 или 80486,  то можете использовать
регистры FS и GS.  "Выражение" может быть любым  выражением,  при
вычислении которого получается имя сегмента или группы. В против-
ном случае может использоваться ключевое слово NOTHING.  Это клю-
чевое слово  отменяет  связь  между  сегментным регистром и любым
сегментом или именем группы.

     Директива ASSUME NOTHING отменяет связь между всеми сегмент-
ными регистрами и сегментом или именем группы.

     Вы можете использовать директиву ASSUME при модификации сег-
ментного регистра или в начале процедуры для задания в этой точке
предположений о сегментных регистрах.  На практике ASSUME исполь-
зуется обычно в начале модуля и иногда внутри него.  Если вы  ис-
пользуете оператор MODEL,  то Турбо Ассемблер назначает директиву
ASSUME по умолчанию.

     Если вы не задаете в директиве ASSUME значение, то ранее за-
данное в ней значение не изменяется.

     Например, в следующем фрагменте программы показано, как мож-
но загрузить текущий инициализированный сегмент  данных  дальнего
типа в регистр DS, обратиться через этот регистр к памяти и восс-
тановить регистр DS в значение сегмента данных:

     MOV  AX,@fardata
     MOV  DS,AX
     ASSUME  DS:@fardata:
     MOV  BX,<переменная_данных_дальнего_типа>
     MOV  AX,@data
     MOV  DS,AX
     ASSUME DS:@data

                  Переопределение сегмента
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Компоновщик организует и упорядочивает все сегменты, опреде-
ленные в модулях программы.  В общем случае компоновщих  начинает
размещение сегментов  в том порядке,  в котором они встречаются в
модулях программы. С помощью такого механизма, как комбинирование
сегментов и  назначение сегментам классов вы можете изменять этот
порядок.

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

         Изменение упорядочивания сегментов в модуле
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Порядок сегментов  в каждом модуле определяет начальное раз-
мещение сегментов в программе компоновщиком.  В MASM  1.0  и  2.0
сегменты передавались компоновщику в алфавитном порядке.  В Турбо
Ассемблере предусмотрены директивы (только в режиме MASM),  кото-
рые позволяют воспроизвести это поведение.

     Заметим, что данные директивы действуют так же, как парамет-
ры командной строки /A и /S.

                      Директива .ALPHA
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

      Директива .ALPHA определяет упорядочивание сегментов по ал-
фавиту.  Данная директива сообщает Турбо Ассемблеру, что сегменты
в  объектном файле нужно разместить в алфавитном порядке (в соот-
ветствии с именами сегментов). Она имеет синтаксис:

     .ALPHA

                       Директива .SEQ
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

      Директива .SEQ  определяет  последовательное упорядочивание
сегментов и сообщает Турбо Ассемблеру,  что сегменты нужно  поме-
щать в объектный файл в том порядке,  в котором они встречаются в
исходном файле.  Поскольку это поведение предполагается Турбо Ас-
семблером по  умолчанию,  директиву .SEQ используют обычно только
для переопределения предыдущей директивы .ALPHA. Данная директива
имеет следующий синтаксис:

     .SEQ

  Директива DOSSEG: упорядочивание сегментов в порядке DOS
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Обычно компоновщик упорядочивает сегменты в последовательном
порядке - в том порядке, в котором он их обрабатывает при генера-
ции программы.  Если вы включаете в любой модуль программу дирек-
тиву DOSSEG,  то  это  указывает  компоновщику,  что вместо этого
упорядочивания нужно использовать порядок сегментов,  принятый  в
DOS. Компоновщик при этом выполняет в получаемой программе следу-
ющее упорядочивание:

     - сначала идут сегменты с именем класса CODE (обычно сегмен-
       ты кода);

     - затем следуют сегменты,  не имеющие имени класса CODE и не
       являющиеся частью DGROUP;

     - сегменты, являющиеся частью DGROUP в следующем порядке:

           1. сегменты, не являющиеся классами BSS и STACK (обыч-
              но неинициализированные данные);

          2. сегменты  класса BSS (обычно инициализированные дан-
             ные);

          3. сегменты класса STACK (область стека).

           Примечание: Не используйте директиву DOSSEG,  в  прог-
      раммах,  не являющихся автономными программами на Ассембле-
      ре.

     Сегменты в группе DGROUP располагаются в том порядке,  в ко-
тором они  определены  в  исходных  модулях.  Приведем  синтаксис
DOSSEG:

     DOSSEG

                   Изменение размера стека
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Начальный и  завершающий код процедур работает с регистрами,
указывающими на стек. В процессоре 80386 или 80486 сегменты могут
быть 16- или 32-разрядными.  Таким образом, перед генерацией кор-
ректного начального и завершающего кода  Турбо  Ассемблеру  нужно
знать корректный размер стека.

     Если вы  выбираете  стандартную  модель  с помощью директивы
MODEL, размер стека выбирается автоматически.

     В Турбо Ассемблере предусмотрены  директивы,  которые  могут
установить или переопределить используемый по умолчанию при гене-
рации начального и завершающего  кода размер стека.  Список  этих
директив приведен в следующей таблице:

            Директивы модификации размера стека      Таблица 7.10
ЪДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Директива         і  Значение                              і
ГДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    SMALLSTACK        і  Указывает, что стек 16-разрядный.     і
і                      і                                        і
і    LARGESTACK        і  Указывает, что стек 32-разрядный.     і
АДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

            Глава 8. Определение типов данных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Символьное определение типов данных помогает вам писать  мо-
дульный код.  Отделяя определения типа данных от того кода, в ко-
тором он используется,  вы можете легко  изменять  или  расширять
структуры данных без необходимости переписывать код. Это позволя-
ет также организовать символьный доступ к типу данных и его  ком-
понентам.

     Турбо Ассемблер определяет  столько же символьных типов дан-
ных,  сколько поддерживается в языках высокого уровня.  В  данной
главе описывается, как можно определить различные типы данных.

             Определение перечислимых типов данных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Перечислимые типы данных представляют набор значений,  кото-
рые можно сохранять в определенном числе бит.  Максимальное запи-
санное значение определяет фактически необходимое число бит.

     Приведем пример синтаксиса режима Ideal определения перечис-
лимого типа данных:

ENUM имя [переменная_перечисления [, переменная_перечисления...]]

     В режиме MASM вы можете использовать следующий синтаксис:

имя ENUM [переменная_перечисления [, переменная_перечисления...]]

     Каждая "переменная_перечисления" имеет следующий синтаксис:

     имя_переменной [=значение]

     Когда вы присваиваете переменной "имя_переменной" конкретное
значение, Турбо Ассемблер,  если поле "значение" отсутствует, бу-
дет присваивает ей значение,  равное значению последней перемен-
ной в списке, плюс единица. Значения не могут быть относительными
или иметь опережающие ссылки.  Переменные, создаваемые перечисли-
мым типом (ENUM),  представляют собой переопределяемые переменные
с глобальной областью действия.

           Предупреждение: Если  вы используете в двух перечисли-
      мых типах данных одно и то же  имя  переменной,  то  первое
      значение переменной будет потеряно,  и в результате возник-
      нет ошибка.

     "Имя" -  это  имя типа данных ENUM.  Для получения различной
информации о присваивании значений переменным вы можете затем ис-
пользовать это имя. О присваивании имен перечислимым типам данных
в Турбо Ассемблере рассказывается в Главе 5.

     Имена перечислимых типов данных можно также использовать для
создания переменных и выделения памяти.  Подробности см.  в Главе
12.

     Перечислимые типы данных являются переопределяемыми. В моду-
ле вы можете несколько раз определить одно и то же имя перечисли-
мого типа данных.

     Кроме того,  Турбо  Ассемблер  для определения перечислимого
типа данных с большим числом переменных использует  синтаксис,  в
котором  указывается  несколько строк.  Начало такого определения
отмечается символом {, а конец - символом }.

     В режиме Ideal этот синтаксис имеет следующий вид:

ENUM имя [переменная_перечисления [, переменная_перечисления...]]
     {переменная_перечисления [,переменная_перечисления]...]
     .
     .
     .
     {переменная_перечисления [,переменная_перечисления]...] }

     В режиме MASM используется следующий синтаксис:

имя ENUM [переменная_перечисления [, переменная_перечисления...]]
     {переменная_перечисления [,переменная_перечисления]...]
     .
     .
     .
     {переменная_перечисления [,переменная_перечисления]...] }

     Например, все  приведенные ниже перечислимые типы данных эк-
вивалентны:

     foo ENUM f1, f2, f3, f4     ; исходная версия

     foo ENUM {                  ; версия из нескольких строк
       f1,
       f2,
       f3,
       f4
       }

     foo ENUM f1, f2, {
         f3, f4 }                ; более компактная версия

           Примечание: Турбо  Ассемблер не распознает в определе-
      нии перечислимого типа данных из нескольких  строк  никаких
      псевдоопераций.

             Определение записей с битовыми полями
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Данные типа  записи  представляют собой набор битовых полей.
Каждое битовое поле имеет заданную длину (в  битах)  и  начальное
значение. Размер данных типа записи равен сумме длин всех полей.

     Вы можете  использовать  данные  типа записи для максимально
компактного представления  данных.  Например,  можно  представить
группу из 16 флагов (каждый из которых может быть либо установлен
(ON),  либо  сброшен  (OFF))  как 16 отдельных бит,  16 отдельных
слов, или как запись, содержащую 16 1-битовых полей (наиболее эф-
фективный метод).

     Приведем синтаксис описания данных типа записи режима Ideal:

     RECORD имя [поле_записи [,поле_записи...]]

     В режиме MASM этот синтаксис имеет вид:

     имя RECORD [поле_записи [,поле_записи...]]

     Каждое "поле_записи" имеет следующий синтаксис:

     имя_поля : размер_выражения [=значение]

где "имя_поля" - это имя поля записи. Турбо Ассемблер будет выде-
лять для  него битовое поле размером "размер_выражения".  "Значе-
ние" и размер выражений не могут быть  относительными  или  иметь
опережающие ссылки.  Имена  поля  записи имеют глобальную область
действия и переопределяться не могут.

     "Имя" - это имя типа записи.  Далее вы  можете  использовать
его в модуле для получения различной информации о данных типа за-
писи. Вы можете также использовать имена для этого имена  отдель-
ных полей записи.  Значения и выражения размера не могут быть от-
носительными и  иметь  опережающие  ссылки.  Имена  полей  записи
являются по  области  действия  глобальными и переопределяться не
могут.

     Вы можете переопределить тип записи и  определить  в  модуле
одно и то  же имя, как данные типа записи, несколько раз.

     Вы можете также использовать имена типов записи для создания
переменных и выделения памяти.  Подробности можно найти  в  Главе
12.

     Турбо Ассемблер  обеспечивает  для  полей записи специальную
поддержку, которая представляет флаги и данные перечислимого  ти-
па. Более  эффективный  доступ к полям записи обеспечивают расши-
ренные и дополнительные инструкции.  Эта концепция описывается  в
Главе 13.

     Для определений данных типа записи, требующих большого числа
полей, в Турбо  Ассемблере  предусмотрен  расширенный  синтаксис,
аналогичный синтаксису перечислимого типа данных.  Например,  все
следующие определения типа данных эквивалентны:

     foo RECORD f1:1,f2:2,f3:3,f4:4   ; исходная версия

     foo RECORD {                     ; версия, использующая
        f1:1,                         ; несколько строк
        f2:2,
        f3:3,
        f4:4
        }

     foo RECORD f1:1,f2:2, {          ; более компактная версия
         f3:3,f4:4  }

             Определение структур и объединений
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Структуры и  объединения  позволяют вам совмещать и наклады-
вать друг на друга данные различного типа.  Структура в Турбо Ас-
семблер представляет собой тип данных,  который содержит один или
более элементов структуры.  Структуры отличаются от записей, пос-
кольку элементы структуры занимают всегда целое число байт, а за-
писи описывают поля с произвольным числом бит.  Размер  структуры
равен общему размеру всех входящих в нее элементов.

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

     Турбо Ассемблер позволяет вам полностью вкладывать структуры
и объединения друг в друга,  но это может привести  в  чрезмерной
сложности.  Например, вы можете получить элемент структуры, кото-
рый на самом деле является объединением. В качестве элемента объ-
единения можно также использовать структуры.

       Открытие определения структуры или объединения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В режиме Ideal для открытия определения данных типа структу-
ры или объединения используется следующий синтаксис:

     STRUC имя   или  UNION имя

     В режиме MASM то же самое можно сделать с помощью следующего
синтаксиса:

     имя STRUC   или  имя UNION

     Турбо Ассемблер  рассматривает все данные или код между отк-
рытым определением структуры и  соответствующей  директивой  ENDS
как часть данного типа структуры или объединения.

     Турбо Ассемблер  интерпретирует имена типов данных структуры
или объединения как глобальные,  но переопределяемые. В модуле вы
можете несколько раз определить структурный тип или тип объедине-
ния с одни и тем же именем.

          Задание элементов структуры и объединения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер включает данные в структуры  или объединения
построчно.  Для  выделения памяти для данных и создания элементов
при определении структуры и объединения используются те же дирек-
тивы, что и для выделения данных и создания меток в открытом сег-
менте. Например, директива:

     member1        DW  1

одинаково допустима в сегменте и в определении структуры.  В сег-
менте данный оператор означает "зарезервировать слово со значени-
ем 1  и именем member1".  В определении структуры или объединения
это означает "зарезервировать слово с  начальным  значением  1  и
именем элемента member1".

     Если в сегменте или структуре выделяется экземпляр структуры
или объединения,  вы можете использовать начальное значение  эле-
мента структуры. Если вы не распределять элементы структуры таким
образом, для указания этого используйте в качестве значения  дан-
ных символ ? (символ неинициализированных данных).

     Турбо Ассемблер позволяет использовать в определении  струк-
туры  все  методы  выделения  данных,  включая  экземпляры других
структур, объединений, записей, перечислимых типов данных, таблиц
и  объектов.  Более  подробно о выделении данных рассказывается в
Главе 12.

     В режимах  MASM и Ideal имена элементов структур интерпрети-
руются по-разному. В режиме MASM имена элементов структур являют-
ся глобальными и не могут переопределяться.  В режиме Ideal имена
элементов структур считаются локальными для структуры или объеди-
нения.

Определение меток элементов структур с помощью директивы LABEL
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Директива LABEL позволяет вам  создавать  элементы  структур
без выделения данных. Обычно LABEL задает метку с именем или мар-
кер в той точке,  где она обнаруживается  в  сегменте.  Директива
LABEL внутри   определения  структуры  определяет  элементы  этой
структуры. Приведем синтаксис директивы LABEL:

     LABEL имя сложный_тип

     В режиме MASM вы можете использовать следующий синтаксис:

     имя LABEL сложный_тип

где "имя" - это имя элемента структуры.  "Тип" - это желаемый тип
элемента структуры.  Он может представлять собой любое допустимое
имя типа.  Описание имеющихся спецификаторов типов можно найти  в
Главе 5.

              Выравнивание элементов структуры
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В определения структуры для выравнивания  элементов структур
на соответствующие  границы  можно  использовать директиву ALIGN.
Например:

             ALIGN 4     ; выравнивание на границу двойного слова
     member  dd  ?       ; member будет выравниваться на DWORD

       Закрытие определения структуры или объединения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     После того,  как вы определите все  элементы  структуры  или
объединения, нужно закрыть определение структуры или объединения.
Для этого используется директива ENDS.

     В режиме Ideal директива ENDS имеет следующий синтаксис:

     ENDS [имя]

     В режиме MASM вы можете использовать синтаксис:

     имя ENDS

где "имя" (если оно присутствует) соответствует  имени  открытого
определения структуры  или объединения.  Если имя не указано,  то
закрывается открытая в данный момент структура или объединение.

     Вы можете также использовать  директиву  ENDS  для  закрытия
сегментов. Это  не приводит к конфликту,  поскольку открытие сег-
мента внутри структуры или объединения не допускается.

              Вложенные структуры и объединения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер позволяется для управления смещениями, прис-
ваевыми  элементам структуры,  использовать  вложенные  директивы
STRUC,  UNION  и  ENDS  внутри  открытого определения данных типа
структуры или объединения.

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

                  Директивы STRUC, UNION и ENDS       Таблица 8.1
ЪДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і    Директива   і Смысл                                        і
ГДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    STRUC       і При использовании внутри открытой  структуры і
і                і или объединения  данная  директива  начинает і
і                і блок элементов,  который внешняя (охватываю- і
і                і щая) структура  или объединение рассматрива- і
і                і ет,  как один элемент.  Смещения элементам в і
і                і блоке  присваиваются в возрастающем порядке. і
і                і Размер блока представляет собой сумму разме- і
і                і ров всех элементов в нем.                    і
і                і                                              і
ГДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    UNION       і При использовании внутри открытой  структуры і
і                і или объединения  данная  директива  начинает і
і                і блок элементов,  который охватывающая струк- і
і                і тура или объединение рассматривает  как один і
і                і элемент.  Элементам блока присваивается одно і
і                і и то же смещение. Размер блока равен размеру і
і                і наибольшего элемента в нем.                  і
і                і                                              і
ГДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    ENDS        і Завершает блок элементов, начинающихся  пре- і
і                і дыдущей директивой STRUC или UNION.          і
і                і                                              і
АДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Например, в следующем определении данных типа структуры/объ-
единения содержится в общей сложности 5 элементов.

     CUNION      STRUC
     CTYPE       DB ?
                    UNION      ; начало объединения
                    ; если CTYPE = 0, использовать следующее...
                    STRUC
     CT0PAR1          DW 1
     CT0PAR2          DW 1
                    ENDS
                    ; если CTYPE = 1, использовать следующее...
                    STRUC
     CT1PAR1          DW 3
     CT1PAR2          DW 4
                    ENDS
                 ENDS           ; конец объединения
           ENDS                 ; конец структурного типа

     Список этих элементов приведен в следующей таблице:

                  Элементы блока                      Таблица 8.1
ЪДДДДДДДДДДДВДДДДДДДДДВДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
іЭлемент    і Тип     і  Смещение  і   Значение по умолчанию    і
ГДДДДДДДДДДДЕДДДДДДДДДЕДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і CTYPE     і Byte    і     0      і   ? (не инициализирован)   і
і CT0PAR1   і Word    і     1      і   1                        і
і CT0PAR2   і Byte    і     3      і   2                        і
і CT1PAR1   і Byte    і     1      і   3                        і
і CT1PAR2   і Dword   і     2      і   4                        і
АДДДДДДДДДДДБДДДДДДДДДБДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Длина данной структуры/объединения равна 6 байтам.

       Включение одной именованной структуры в другую
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Чтобы способствовать наследованию объектов,  Турбо Ассемблер
обеспечивает способ,  при  котором  весь тип данных структуры или
объединения, включая имена элементов, встраивается в открытое оп-
ределение структуры.  Он  интерпретирует встроенную структуру или
объединение, как если бы они были вложены в этой точке внутри от-
крытого  определения  структуры  или объединения.  Таким образом,
встраивание одной структуры или объединения в другую принципиаль-
но отличается от включения в структуру или объединение экземпляра
другой структуры или объединения: экземпляр включает в себя толь-
ко инициализированные или неинициализированные данные, в то время
как встраиваемая структура или объединение включает в  себя имена
данных, структур и имена элементов.

     Приведем синтаксис режима Ideal:

     STRUC имя_структуры параметры_заполнения

     В режиме MASM вы можете использовать следующий синтаксис:

     имя_структуры STRUC параметры_заполнение

     Оператор такого вида можно использовать только внутри струк-
туры или объединения. Здесь "имя_структуры" - это имя ранее опре-
деленной структуры  или  объединения,  которая должны включаться.
"Параметры_заполнения" задают изменения, которые вы хотите внести
в начальные  (используемые по умолчанию) значения включенных эле-
ментов структуры.  Ключевое слово ? указывает, что все встраивае-
мые элементы  структуры нужно рассматривать,  как неинициализиро-
ванные. В  противном  случае  поле  "параметры_заполнения"  имеет
следующий синтаксис:

  { [имя_элемента [=выражение] [,имя_элемента [=выражение]...]] }

где "имя_элемента"  - это имя любого элемента включаемой структу-
ры, начальное значение которого при включении требуется изменить.
"Выражение" представляет собой значение, на которое вы хотите его
изменить. При наличии "выражения" начальное значение  этого  эле-
мента структуры  при его включении останется без изменения.  Если
вы задаете в поле выражения ключевое слово ?, то начальное значе-
ние элемента будет записываться при его включении,  как неинициа-
лизированное.

     Поскольку в режиме MASM имена элементов  структуры  являются
глобальными, при  копировании структуры они не  переопределяются.
Таким образом,  в режиме MASM включение одной структуры в  другую
более полезно,  когда вы делаете это в начале определяемой струк-
туры или объединения.

     Обычно, когда вы создаете экземпляр структуры, нужно обеспе-
чить,  что инициализированные данные содержал только один элемент
объединения (подробности см. в Главе 12). Поскольку при встраива-
нии структуры создание экземпляра не предусматривается, это огра-
ничение здесь не применяется. Инициализированные данные могут со-
держать несколько элементов включаемого объединения, например:

     FOO    STRUC
     ABC      DW 1
     DEF      DW 2
              UNION
     A1           DW '123'
     A2           DW ?
              ENDS
            ENDS

     FOO2  STRUC
     FOO   STRUC {A1=2}  ; встроить структуру FOO в структуру
                         ; FOO2 с переопределением
                         ; заметим, что по умолчанию в FOO2
                         ; инициализируется и A1, и A2
     GHI   DB 3
           ENDS

     Определение структуры FOO2 в предыдущем примере эквивалентно
следующей вложенной структуре/объединению:

     FOO    STRUC
             STRUC    ; начало вложенной структуры...
     ABC      DW 1
     DEF      DW 2
              UNION   ; начало вложенного объединения...
     A1           DW '123'
     A2           DW ?
              ENDS    ; конец вложенного объединения...
            ENDS      ; конец вложенной структуры...
     GHI   DB 3
           ENDS

     Заметим, что  при  создании экземпляра FOO2 нужно убедиться,
что инициализируется только одно значение в объединении.

          Использование имен структур в выражениях
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     После того, как вы определите структуру или объединение, ин-
формацию о структуре и объединении можно получить различными  пу-
тями. Для  получения информации с помощью выражений Турбо Ассемб-
лера вы можете использовать имена типа данных структуры или  объ-
единения. Более подробно об этом рассказывается в Главе 5.

                       Определение таблиц
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Табличный тип данных представляет набор  элементов  таблицы.
Каждый элемент  имеет заданный размер (в байтах) и начальное зна-
чение. Элемент таблицы может быть  виртуальным  или  статическим.
Виртуальному элементу  таблицы присваивается смещение в табличном
типе данных.  Для него резервируется место  в  каждом  экземпляре
таблицы. Статических элемент не имеет смещения. В экземпляре таб-
лицы пространство для него не резервируется.

     В целом размер табличного типа данных равен  сумме  размеров
всех виртуальных элементов.

     Табличные типы данных представляют таблицы методов,  исполь-
зуемые в объектно-ориентированном  программировании.  С  объектом
связано обычно некоторое число методов, которые являются указате-
лями на процедуры,  работающие с экземплярами объектов. Процедуры
методов могут  либо вызываться непосредственно (статические мето-
ды), либо косвенно,  через таблицу  указателей  процедур  методов
(виртуальные методы).

     Для описания  табличного  типа  данных  в режиме Ideal можно
использовать следующий синтаксис:

     TABLE имя [элемент_таблицы [,элемент_таблицы...]]

     Следующий синтаксис работает только в режиме MASM:

     имя TABLE [элемент_таблицы [,элемент_таблицы...]]

     Каждое поле "элемент_таблицы" имеет следующий синтаксис:

     имя_таблицы

или
     [VIRTUAL] имя_элемента [[выражение_счетчика_1]]
           [: сложный_тип [:выражение_счетчика_2]] [=выражение]

где "имя_таблицы" - это имя существующего табличного типа данных,
элементы которого целиком встраиваются в определяемую вами табли-
цу. Прибегайте к данному синтаксису,  если вы хотите использовать
наследование.

     "Имя_элемента" -  это  имя элемента таблицы.  Необязательное
ключевое слово VIRTUAL указывает,  что элемент является виртуаль-
ным, и ему нужно присвоить смещение.

     "Сложный_тип" может  представлять собой любое допустимое вы-
ражение сложного типа.  Описание допустимых типов выражений можно
найти в Главе 5.

     Если вы не задается поле "сложный_тип", Турбо Ассемблер под-
разумевает, что это WORD (или DWORD,  если текущей выбранной  мо-
делью является 32-разрядная модель).

     Поле "выражение_счетчик_2" задает, сколько элементов данного
типа определяется в таблице. Определение элемента таблицы:

     foo TABLE VIRTUAL tmp:DWORD:4

определяет элемент таблицы с именем tmp,  состоящий из 4  двойных
слов.

     По умолчанию,  если  вы  его не задаете,  "выражение_счетчи-
ка_2" имеет значение 1. Поле "выражение_счетчика_1" - это коэффи-
циент размера  элемента  массива.  Для элемента резервируется па-
мять, объем,  которой определяется произведением "выражение_счет-
чик_2", длины, заданной полем "сложный_тип", и "выражения_счетчи-
ка_2". Если вы не задаете "выражение_счетчика_2", то по умолчанию
его значение равно 1.  Общее число элементов таблицы определяется
произведением "выражение_счетчика_1" и "выражением_счетчика_2".

     В режиме Ideal имена элементов таблицы  являются  локальными
для таблицы, а в режиме MASM имеют глобальную область действия.

     Поле "имя" задает имя табличного типа данных. Позднее вы мо-
жете использовать его в модуле для получения информации о таблич-
ном типе  данных.  Для получения информации можно также использо-
вать имена отдельных элементов.  Подробнее об этом рассказывается
в Главе 5.

     Табличные типы  данных являются переопределяемыми.  В модуле
вы можете несколько раз определить табличный тип данных с одним и
тем же именем. Подробнее об этом рассказывается в Главе 12.

     Кроме того,  Турбо  Ассемблер  обеспечивает  соответствующий
синтаксис  для определений табличного типа данных,  в которых ис-
пользуется несколько строк.

     Этот синтаксис аналогичен синтаксису перечислимого типа дан-
ных. Приведем пример:

     foo TABLE t1:WORD,t2:WORD,t3:WORD,t4:WORD ; исходная версия

     foo TABLE {                      ; версия, использующая
        t1:WORD,                      ; несколько строк
        t2:WORD,
        t3:WORD,
        t4:WORD
        }

     foo TABLE t1:WORD,t2:WORD, {     ; более компактная версия
               t3:WORD,t4:WORD  }

              Переопределение элементов таблицы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Если в  одном  и том же табличном типе вы описываете два или
более элементов с одинаковым именем,  то  Турбо  Ассемблер  будет
проверять их  и анализировать,  согласуются ли их размеры и типы.
Если это не так,  то будет генерироваться ошибка. Турбо Ассемблер
будет использовать  для  элемента  последнее начальное значение в
таблице. Таким образом, вы можете переопределить начальное значе-
ние таблицы поле того,  как встроите ее в другую таблицу.  Напри-
мер:

 FOO TABLE VIRTUAL MEM1:WORD=MEM1PROC, VIRTUAL MEM2:WORD=MEM2PROC
 FOO2 TABLE FOO, VIRTUAL MEM1:WORD=MEM3PROC ; переопределить
                                            ; наследуемый MEM1

                Определение именованного типа
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Именованные типы представляют простые или сложные  типы. Для
определения именованных  типов  вы  можете использовать директиву
TYPEDEF. Приведем синтаксис режима Ideal.

     TYPEDEF имя_типа сложный_тип

     В режиме MASM синтаксис следующий:

     имя_типа TYPEDEF сложный_тип

где "сложный_тип" описывает любой тип  или  указатель  нескольких
уровней косвенности.  Подробнее  о сложных типах рассказывается в
Главе 5. "Имя_типа" определяет имя заданного типа.

     Когда вы в выражении указываете названный тип,  он действует
так же, как простой тип соответствующего размера. Например:

     MOV ax, word ptr [bx]     ; простой оператор
     foo TYPESEF near ptr byte ; FOO - это слово
     MOV ax, foo ptr  [bx]     ; поэтому это тоже работает

                    Определение объекта
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Объект содержит структуру данных  и  список  соответствующих
объекту методов.  Турбо  Ассемблер используется для представления
связанной с  объектом  структуры  структурный  тип данных,  а для
представления связанного с объектом списка  методов  -  табличный
тип данных.

     Определить объекты вам поможет  директива  STRUC.  В  режиме
Ideal используется следующий синтаксис:

     STRUC имя [модификаторы] [имя_порождающего_объекта]
       [METHOD [элемент_таблицы [,элемент_таблицы...]]]
     элементы_структуры
     ENDS [имя]

     В режиме MASM используется следующий синтаксис:

     имя STRUC [модификаторы] [имя_порождающего_объекта]
       [METHOD [элемент_таблицы [,элемент_таблицы...]]]
     элементы_структуры
     ENDS [имя]

где "имя" - это имя объекта. "Имя_порождающего_объекта" - это не-
обязательное имя порождающего объекта. (Турбо Ассемблер явно под-
держивает только одиночное наследование.) Структура данных порож-
дающего объекта будет автоматически включаться в структуру данных
нового объекта, а таблица методов порождающего объекта - в табли-
цу методов нового объекта.

     Каждое поле "элемент_таблицы" описывает имя метода и  проце-
дуры метода,  связанного  с объектом.  Синтаксис этого поля такой
же, как в определении таблицы.

     Поле "элементы_структуры" описывает  дополнительные элементы
структуры, которые вы хотите определить в структуре данных объек-
та. Они форматируются точно также,  как  в  открытом  определении
структуры.

     Необязательное ключевое слово "модификаторы" может представ-
лять собой одно из следующих слов:

                    Разрешенные модификаторы          Таблица 8.3
ЪДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і  Ключевое слово    і Значение                                 і
ГДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і  GLOBAL            і Приводит к тому, что адрес таблицы  вир- і
і                    і туальных методов (если она имеется)  бу- і
і                    і дет объявлен общедоступным.              і
і                    і                                          і
і  NEAR              і Указатель виртуальной таблицы (если  она і
і                    і имеется будет содержать смещение (16 или і
і                    і 32, бита в зависимости от выбора текущей і
і                    і модели по USE16 или USE32).              і
і                    і                                          і
і  FAR               і Указатель виртуальной таблицы (если  она і
і                    і имеется будет содержать величины, задаю- і
і                    і щие сегмент и смещение (32 или 48 бит, в і
і                    і зависимости  от выбора текущей модели по і
і                    і USE16 или USE32).                        і
АДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Если вы не задаете модификатор, размер указателя виртуальной
таблицы (если он имеется) зависит от того, адресуются ли данные в
текущей модели как NEAR, или как FAR.

                      Директива TBLPTR
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В концепции  объектов используется таблица виртуальных мето-
дов. Экземпляр этой таблицы существует для любого объекта, содер-
жащего виртуальные методы. Структура данных для для любого объек-
та, содержащего виртуальные методы, также должна содержать указа-
тель   на   таблицу  виртуальных  методов  этого  объекта.  Турбо
Ассемблер автоматически обеспечивает в структуре  данных  объекта
указатель таблицы виртуальных методов (если это требуется), и вам
не нужно задавать его явно с помощью директивы TBLPTR.

     Директиву TBLPTR следует использовать в определении структу-
ры данных объекта. TBLPTR позволяет вам явно разместить указатель
таблицы виртуальных методов там, где вы хотите. Она имеет следую-
щий синтаксис:

     TBLPTR

     Размер указателя,  который резервирует TBLPTR,  определяется
тем, задано в текущей модели USE16 или USE32,  и тем, какие моди-
фикаторы используются в определении объекта.

  Идентификаторы, определяемые расширенной директивой STRUC
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Расширенная директива STRUC определяет и использует несколь-
ко идентификаторов,  которые  отражают  определяемый объект.  Эти
идентификаторы показаны в следующей таблице:

    Идентификаторы, определяемые расширенной директивой STRUC
                                                      Таблица 8.4
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і  Идентификатор           і Значение                           і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і  @Object                 і Текстовая макрокоманда,  содержащаяі
і                          і текущий объект.                    і
і                          і                                    і
і  @Table_<имя_объекта>    і Табличный  тип  данных,  содержащийі
і                          і таблицу методов объекта.           і
і                          і                                    і
і  @Tableaddr_<имя_объекта>і Метка,  описывающая  адрес  таблицыі
і                          і виртуальных методов объекта.       і
АДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

      Глава 9. Задание и использование счетчика адреса
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

     Метки представляют собой имена, использующиеся для ссылок на
адреса в программе.  Меткам во время их определения присваивается
текущее значение счетчика адреса программы.  Метки позволяют  вам
назначать имена переменным в памяти и адресам конкретных инструк-
ций.

     В данной главе описываются имеющиеся директивы,  которые ис-
пользуются для работы со счетчиком адреса и описания метод по те-
кущему адресу.

            Идентификатор счетчика адреса $
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Предопределенный идентификатор  $ представляет текущий счет-
чик адреса.  Счетчик адреса состоит из двух  частей:  сегмента  и
смещения. При  ассемблировании  счетчик адреса представляет собой
смещение в текущем сегменте.

     Счетчик адреса - это адрес адрес,  который  увеличивается  и
отражает текущий  адрес при ассемблировании каждого оператора ис-
ходного файла. Например:

     helpkMessage   DB   'это справочное сообщение программы'
     helpLength     =  $ - helpMessage

     Когда эти    две    строки   ассемблируются,   идентификатор
helpLength равен длине справочного сообщения.

                Директивы счетчика адреса $
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В Турбо  Ассемблере предусмотрено несколько директив,  уста-
навливающий счетчик инструкций.  Эти директивы описываются в сле-
дующем разделе. Заметим, что все эти директивы работают как в ре-
жиме MASM, так и в режиме Ideal.

                        Директива ORG
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Вы можете   использовать  директиву  ORG,  чтобы  установить
счетчик адреса в значение текущего сегмента.  Директива ORG имеет
следующий синтаксис:

     ORG выражение

где "выражение" не может содержать никаких имен идентификаторов с
опережающими ссылками. Оно может быть константой или смещением от
идентификатора в  текущем  сегменте,  либо смещением относительно
текущего счетчика адреса.

     Перед данными или кодом,  которые уже введены в сегмент,  вы
можете восстановить значение счетчика адреса. Это можно использо-
вать для возврата назад и заполнения  записей  таблицы,  значения
которых не были известны во время определения таблицы. Используй-
те этот метод с осторожностью: вы можете непреднамеренно что-либо
затереть.

     Директиву ORG  можно  использовать  для того,  чтобы связать
метку с конкретным адресом.  Директива ORG может также  использо-
ваться для задания начального адреса файлов .COM. Приведем приме-
ры ее использования:

     PROG SEGMENT
          ORG 100h         ; начальное смещение файла .COM
     start:
     ;
     ; остальная часть программы .COM
     PROG ENDS
     end start

     Приведем другой пример:

     PROG SEGMENT
          ASSUME cs:PROG, ds:PROG, ss:PROG, es:NOTHING
          ORG 20h
     EnvPtr       label word      ; определить метку для доступа
                                  ; к слову в PSP, которое ука-
                                  ; зывает на сегмент, содержа-
                                  ; щий блок операционной среды
                                  ; (он обычно освобождается для
                                  ; создания более компактной
                                  ; резидентной программы)
          ORG 80h
     CmdLength lebel byte         ; определить метку для доступа
                                  ; к длине командной строки

          ORG @1h
     CmdLine  label byte          ; определить метку для доступа
                                  ; к тексту командной строки

          ORG 0100h
     start:

     ; освободить блок операционной среды

     mov   es, EnvPtr            ; ES -> блок операционной среды
     mov   ah, 49h               ; функция 49h: освободить блок
                                 ; памяти
     int   21h                   ; вызвать MS-DOS
     jc    error_ENV             ; ошибка освобождения EnvBlock?

     ; анализ командной строки

     mov   al, CmdLength         ; длина командной строки
     or    al,al                 ; проверка на 0
     jz    no_params             ; нет параметров
     mov   cl,al                 ; поместить длину в cl
     mov   ch,0
     mov   si,offset CmdLine     ; адрес командной строки
     mov   al,' '                ; символ для поиска
     repne scasb                 ; поиск первого пробела
     ;
     ; остальная часть файла .COM резидентной программы:
     PROG ENDS
     end start

                  Директивы EVEN и EVENDATA
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Вы можете использовать директиву EVEN для округления счетчи-
ка адреса до следующего четного адреса.  Директива EVEN позволяет
вам выравнивать  код для эффективного доступа к процессорам,  ис-
пользующим 16-разрядную шину данных. Производительность процессо-
ров, использующих  8-разрядную  шину  данных,  директивой EVEN не
улучшается.

     Директива EVENDATA выполняет выравнивание на четную границу,
изменяя счетчика адреса без генерации данных, что полезно исполь-
зовать для  неинициализированных  сегментов.  Директивы  EVEN   и
EVENDATA приводят к тому, что если выравнивание текущего сегмента
выполнено недостаточно строго, Турбо Ассемблер выводит предупреж-
дающее сообщение.

     Если когда  встречается  директива EVEN счетчик адреса имеет
нечетное значение,  то Турбо Ассемблер помещает  в  сегмент  один
байт или инструкцию NOP,  чтобы счетчик адреса стал четным. С по-
мощью заполнения инструкциями NOP директиву EVEN можно в  сегмен-
тах кода,  не вызывая на этапе работы программы выполнения невер-
ных инструкций. Если счетчик адреса уже имеет четное значение, то
данная директива не действует.

     Аналогично, если  счетчик  адреса  имеет  нечетное значение,
когда встречается директива EVENDATA,  Турбо Ассемблер генерирует
неинициализированный байт.

     Приведем следующий пример использования директивы EVEN:

     EVEN
     @@A:      lodsb
               xor bl,al ; выравнивание для эффективного доступа
               loop  @@a

     Приведем пример использования директивы EVENDATA:

     EVENDATA
     VAR1      DW   0        ; выравнивание для эффективного
                             ; доступа 8086

                       Директива ALIGN
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для выравнивания счетчика  адреса на адрес, значение которо-
го равно степени 2, можно использовать директиву ALIGN. Директива
ALIGN имеет следующий синтаксис:

     ALIGN граница

где "граница" должна быть степенью 2.

     Если счетчик  адреса еще не соответствует смещению,  которое
представляет собой произведение "границы", Турбо Ассемблер, чтобы
присвоить счетчика адреса нужный адрес,  вставляет в сегмент инс-
трукции NOP (нет операции).

     Вы не можете выполнить надежное выравнивание на границу, яв-
ляющееся более  строгим,  чем выравнивание  сегмента,  в  котором
встречается директива ALIGN. Выравнивание сегмента задается, ког-
да сегмент в первый раз начинается по директива SEGMENT.

     Например, если вы определили сегмент следующим образом:

     CODE SEGMENT PARA PUBLIC

затем вы  можете  задать ALIGN 16 (что эквивалентно PARA),  но не
ALIGN 32,  как как это более строгое выравнивание, чем выравнива-
ние, заданное в директиве SEGMENT с помощью PARA. Если выравнива-
ние сегменте недостаточно строгое,  то директива ALIGN генерирует
предупреждающее сообщение.

     Использование директивы ALIGN показано в следующем примере:

     ALIGN 4             ; выравнивание на границу DWORD для 386
     BignNum  DD    12345678

                      Определение меток
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Метки позволяют  вам  присваивать  значения идентификаторам.
Существует три способа определения меток:

     - использование операции :;
     - использование директивы LABEL;
     - использование операции :: (MASM 5.1).

                         Операция :
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Операция : определяет ближнюю метку кода и имеет синтаксис:

     имя:

где "имя"  -  это идентификатор,  который вы не объявляли ранее в
исходном коде.  Ближние метки кода вы можете размещать на  строке
кода, где содержится только одна метка, или в начале строки перед
инструкцией. Обычно ближние метки кода  используются  в  качестве
адреса перехода в инструкциях JMP и CALL в том же сегменте.

     Если вы  не  используете директиву PUBLIC,  чтобы метка была
доступна из других файлов, она доступна только в текущем исходном
файле.

     Данная директива работает точно также, как при использовании
директивы LABEL для определения ближней метки  (NEAR).  Например,
A: эквивалентно A LABEL NEAR.

     Приведем пример использования операции :

     jne A           ; пропустить следующую инструкцию
     inc si
     A:              ; jne передает управление сюда

                       Директива LABEL
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Директиву LABEL вы можете использовать для определения иден-
тификатора заданного типа.  Заметим, что синтаксис в режимах MASM
и Ideal различен. В режиме Ideal задавайте:

     LABEL имя сложный_тип

     В режиме MASM используйте следующее:

     имя LABEL сложный_тип

где "имя" - это идентификатор,  который вы не определяли ранее  в
исходном файле.  "Сложный_тип"  описывает размер идентификатора и
то, ссылается он на код или данные.  См. Главу 5, в которой можно
найти дальнейшую информацию о сложных типах.

     Если вы  не  используете директиву PUBLIC,  чтобы метка была
доступна из других файлов, она доступна только в текущем исходном
файле.

     Вы можете использовать директиву LABEL для доступа к элемен-
там различного размера,  которые содержатся в  структуре  данных.
Этот принцип иллюстрируется следующим примером:

     WORDS   LABEL  WORD            ; доступ к "BYTES" как к
                                    ; WORDS
     BYTES  DB 64 DUP (0)
            mov WORDS[2],1          ; запись в WORDS 1

                        Директива ::
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Директива ::  позволяет  вам определить с областью действия,
выходящей за рамки процедуры,  в которой она находится. Это отли-
чается от директивы :  тем,  что метки,  определенные с помощью :
имеют область действия только в текущей процедуре.  Заметим,  что
:: отличается  от  :  только  когда  вы  задаете язык в операторе
.MODEL. Приведем пример (файл DBLCOLON.ASM):

     VERSION  M510
     .MODEL SMALL,C
     .CODE

     A PROC
              NOP
     ASINGLE:NOP
     ADOUBLE::NOP
              NOP
     A ENDP

     B PROC
             NOP
             JMP ASINGLE   ; приведет к ошибке
             JMP ADOUBLE
             RET
     B ENDP
       END

                 Глава 10. Описание процедур
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер позволяет вам описывать процедуры нескольки-
ми способами.  В  данной  главе описываются процедуры NEAR и FAR,
объявление языка процедур,  использование в процедурах аргументов
и переменных,  сохранение регистров, вложенные процедуры и описа-
ние процедур методов для объектов.

               Синтаксис определения процедур
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для описания процедур вы можете использовать директиву PROC.
В режиме Ideal она имеет следующий синтаксис:

     PROC [[модификатор_языка] язык] имя [расстояние]
        [ARG список_аргументов] [RETURN список_элементов];
           [LOCAL список_аргументов]
              [USES список_элементов]
          .
          .
          .
     ENDP [имя]

     В режиме MASM используется следующий синтаксис:

     имя PROC [[модификатор_языка] язык] [расстояние]
        [ARG список_аргументов] [RETURN список_элементов];
           [LOCAL список_аргументов]
              [USES список_элементов]
              .
              .
              .
     [имя] ENDP

     Турбо Ассемблер также воспринимает для  определения процедур
синтаксис MASM. Подробнее о синтаксисе MASM рассказывается в Гла-
ве 3.

              Описание процедур NEAR или FAR
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Процедуры NEAR  вызываются  с помощью вызова ближнего типа и
содержат ближний возврат управления. Вы должны вызывать их только
в том же сегменте,  в котором они определены. Вызов ближнего типа
заносит адрес возврата в стек и устанавливает указатель  инструк-
тор  (IP)  в значение смешения процедуры.  Поскольку сегмент кода
(CS) не изменяется,  процедура должна находиться в том же сегмен-
те,  что  и  вызывающая  программа.  Когда процессор обнаруживает
возврат ближнего типа,  он извлекает из стека  адрес  возврата  и
снова устанавливает в него IP. Сегмент кода не изменяется.

     Процедура FAR  вызывается  с  помощью вызова дальнего типа и
содержит возврат дальнего типа.  Процедуры FAR вы можете вызывать
вне сегмента,  в  котором  они определяются.  Вызов FAR заносит в
стек адрес в виде сегмента  и  смещения,  а  затем  устанавливает
CS:IP  в  адрес  процедуры.  Когда процессор обнаруживает возврат
дальнего типа,  он извлекает из стека сегмент и  смещение  адреса
возврата и устанавливает в него CS:IP.

     Расстояние (NEAR или FAR), используемое в процедуре по умол-
чанию, определяется текущей выбранной моделью.  Для моделей TINY,
SMALL и  COMPACT по умолчанию процедура будет ближней (NEAR). Для
всех других моделей по умолчанию выбирается расстояние  FAR. Если
вы не  используете упрощенные директивы определения сегментов, то
по умолчанию процедура всегда будет ближней (NEAR).

           Примечание: FAR или NEAR можно задать в качестве аргу-
      мента оператора MODEL. Более подробно об этом рассказывает-
      ся в Главе 7.

     Вы можете переопределить используемое по умолчанию  расстоя-
ние, задав  нужное расстояние в определении процедуры.  Для этого
вы можете использовать ключевые слова NEAR или FAR.  Эти ключевые
слова переопределяют  расстояние,  используемое  в  процедуре  по
умолчанию, но только для текущей процедуры. Например:

     .
     .
     .
     MODEL TINY                ; по умолчанию расстояния NEAR
     .
     .
     .                         ; test1 - это дальняя процедура
     test1 PROC FAR
                               ; тело процедуры
     RET                       ; это будет дальним возвратом:
     ENDP
                               ; test2 по умолчанию является
                               ; ближней процедурой
     test2 PROC
                               ; тело процедуры
     RET                       ; это будет ближним возвратом
     ENDP
     .
     .
     .

     В процедурах NEAR и FAR используется одна и та же инструкция
RET. Турбо Ассемблер использует расстояние процедуры для  опреде-
ления того,  требуется возврат ближнего или дальнего типа. Анало-
гично, Турбо Ассемблер использует расстояние процедуры для  опре-
деления того,  требуется для ссылки на процедуру возврат ближнего
или дальнего типа.

     .
     .
     .
     CALL test1          ; это дальний возврат
     CALL test2          ; это ближний возврат
     .
     .
     .

     При выполнении  вызова процедуры с опережающей ссылкой Турбо
Ассемблеру может потребоваться для определения расстояния  проце-
дуры выполнить несколько проходов. Например:

     .
     .
     .
     test1 PROC NEAR
     MOV ax,10
     CALL test2
     RET
     test1 ENDP

     test1 PROC FAR
     ADD ax,ax
     RET
     test2 ENDP
     .
     .
     .

     Когда Турбо Ассемблер при первом проходе достигает  инструк-
ции call test2,  он еще не обнаруживает test2, и следовательно не
знает расстояния. Он предполагает, что это расстояние NEAR, и что
можно сделать ближний вызов.

     Когда Турбо  Ассемблер  обнаруживает,  что test2 является на
самом деле дальней процедурой,  он определяет, что для корректной
генерации вызова требуется второй проход. Если вы разрешаете нес-
колько проходов  (с  помощью  параметра-переключателя   командной
строки /m), то можно сделать второй проход. Если вы не разрешаете
несколько проходов,  то Турбо  Ассемблер  будет  выводить  ошибку
'forward reference  needs  override' ('опережающая ссылка требует
переопределения').

     Чтобы избежать такой ситуации (и уменьшить  число проходов),
вы можете задать в вызове расстояние процедур с опережающей ссыл-
кой, как NEAR PTR и FAR PTR.

     .
     .
     .
     test1 PROC NEAR
            mov AX,10
            CALL FAR PTR test2
           RET
     test1 ENDP
     .
     .
     .

     В предыдущем примере Турбо Ассемблеру сообщается,  что нужно
использовать дальний вызов,  поэтому не возникает необходимость в
нескольких проходах.

                  Описание языка процедуры
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Вы можете  легко определить процедуры,  которые используют в
Турбо Ассемблере соглашения по интерфейсу языков высокого уровня.
Соглашения по  интерфейсу  поддерживаются  для  языков NOLANGUAGE
(Ассемблер), BASIC, PROLOG, FORTRAN, C, CPP (C++) и PASCAL.

     Турбо Ассемблер выполняет всю работу по генерации корректно-
го кода начала (вход в процедуру) и завершения (выход из процеду-
ры), необходимых для соблюдения соглашений заданного языка.

     С помощью директивы MODEL вы можете задать язык,  используе-
мый по  умолчанию.  Подробности  можно  найти  в  Главе  7.  Если
используемый по умолчанию язык задан,  все процедуры, для которых
не задается  другой  язык,  используют соглашения назначенного по
умолчанию языка.

     Чтобы переопределить  используемый  по  умолчанию  язык  для
конкретной процедуры, включите имя языка в определение процедуры.
Вы можете задать язык процедуры,  включив описывающее язык ключе-
вое слово  в описание процедуры.  Например,  определение в режиме
MASM процедуры PASCAL может иметь вид:

     .
     .
     .
     pascalproc PROC PASCAL FAR
               ; тело процедуры
     pascalproc ENDP
     .
     .
     .

     Турбо Ассемблер использует заданный в процедуре язык для оп-
ределения того, какой вход начала и завершения нужно автоматичес-
ки включить в тело процедуры.  Начальный код  устанавливает  кадр
стека для передаваемых аргументов и локальных переменных процеду-
ры, а код завершения перед возвратом из процедуры восстанавливает
кадр стека.

     Турбо Ассемблер  автоматически вставляет в процедуру началь-
ный код перед первой инструкцией процедуры или перед первой  мет-
кой ("метка: цель").

     В коде завершения делается следующее:

     - в стеке сохраняется текущий регистр BP;

     - BP настраивается на текущий указатель стека;

     - настраивается  указатель стека для выделения локальных пе-
       ременных;

     - в  стеке  сохраняются  регистры,  заданные  спецификатором
       USES.

       По каждой инструкции RET процедуры Турбо Ассемблер автома-
тически вставляет в процедуру код завершения (в случае нескольких
инструкций RET  код  завершения будет вставляться несколько раз).
Турбо Ассемблер также вставляет код завершения перед переходом на
любой объектно-ориентированный метод (см. Главу 4).

     Завершающий код  изменяет действие кода инициализации на об-
ратное. Это делается следующий образом:

     - из стека извлекаются регистры, заданные оператором USES;

     - настраивается указатель стека,  чтобы отбросить  локальные
       аргументы;

     - из стека извлекается сохраненный регистр BP;

     - стек  настраивается,  чтобы отбросить переданные аргументы
       (если этого требует язык) и выполнить возврат.

     Последний шаг кода завершения (отбрасывание аргументов)  вы-
полняется только  для тех языков,  которые требуют удаления аргу-
ментов процедуры (например,  Бейсик, Фортран, Паскаль). По согла-
шениям, принятым в других языках (Си, С++, Пролог), аргументы ос-
таются в стеке, и удалять их должна вызывающая программа.

     Турбо Ассемблер всегда реализует  код  начала  и  завершения
процедуры с помощью наиболее эффективных инструкций текущего выб-
ранного языка и процессора.

     Для процедур NOLANGUAGE Турбо Ассемблер  не  генерирует  код
начала и  завершения.  Если в таких процедурах ожидается передача
аргументов в стеке, вы должны сами включать код начала и заверше-
ния.

     В общем  случае язык процедуры влияет на процедуру следующим
образом:

                  Как язык влияет на процедуру          Рис. 10.1
ЪДДДДДДДДДВДДДДДДВДДДДДДВДДДДДДДДВДДДДДДДДВДДДДДДДВДДДДДДВДДДДДДї
і Язык    і Нет  іБейсикі Фортрані Паскальі   Си  і С++  іПрологі
ГДДДДДДДДДЕДДДДДДЕДДДДДДЕДДДДДДДДЕДДДДДДДДЕДДДДДДДЕДДДДДДЕДДДДДДґ
і Порядок і L-R  і L-R  і  L-R   і  L-R   і  R-L  і R-L  і R-L  і
і аргу-   і      і      і        і        і       і      і      і
і ментов  і      і      і        і        і       і      і      і
і (слева  і      і      і        і        і       і      і      і
і -напра- і      і      і        і        і       і      і      і
і во,     і      і      і        і        і       і      і      і
і справа- і      і      і        і        і       і      і      і
і налево) і      і      і        і        і       і      і      і
ГДДДДДДДДДЕДДДДДДЕДДДДДДЕДДДДДДДДЕДДДДДДДДЕДДДДДДДЕДДДДДДЕДДДДДДґ
іКто очи- іпроце-іпроце-іпроцеду-іпроцеду-івызыва-івызы- івызы- і
іщает стекідура  ідура  іра      ідура    іющая   івающаяівающаяі
і(вызыва- і      і      і        і        іпрог-  іпрог- іпрог- і
іющая     і      і      і        і        ірамма  ірамма ірамма і
іпрограммаі      і      і        і        і       і      і      і
іили про- і      і      і        і        і       і      і      і
іцедура)  і      і      і        і        і       і      і      і
АДДДДДДДДДБДДДДДДБДДДДДДБДДДДДДДДБДДДДДДДДБДДДДДДДБДДДДДДБДДДДДДЩ

     L-R - слева-направо, R-L - справа-налево.

     Для включения в файл листинга кода начала  и  завершения  вы
можете использовать  параметр командной строки /la.  Это позволит
вам увидеть разницу между языками.

           Примечание: Более подробную информацию можно  найти  в
      Главе 13.

                 Задание модификатора языка
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Модификаторы языка указывают сообщают Турбо  Ассемблеру, что
в процедуры  нужно  включать специальный код начала и завершения,
организующий интерфейс с Windows  и  менеджером  оверлеев  VROOM.
Чтобы эти модификаторы использовать, укажите их перед языком про-
цедуры в директиве модели или в заголовке  процедуры. Допустимыми
модификаторами являются модификаторы NORMAL,  WINDOWS,  ODDNEAR и
ODDFAR.

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

           Примечание: Подробнее об этом рассказывается  в  Главе
      7.

     Чтобы задать  модификатор  языка  для  конкретной процедуры,
включите модификатор языка в конкретную процедуру. Например:

     .
     .
     .
     sample PROC WINDOWS PASCAL FAR
     ENDP
     .
     .
     .
     Если вы не задаете модификатор языка,  Турбо  Ассемблер  ис-
пользует модификатор языка,  заданный в операторе MODEL. Если ди-
ректива MODEL отсутствует,  или если задан модификатор NORMAL, то
Турбо  Ассемблер  будет использовать стандартный код начала и за-
вершения.

     Если вы выбрали модификатор языка WINDOWS,  Турбо  Ассемблер
генерирует код начала и завершения, позволяющий вам выбирать про-
цедуру из Windows. Турбо Ассемблер генерирует специальный код на-
чала и завершения только для процедура FAR WINDOWS. Из Windows вы
не можете вызвать процедуры NEAR,  поэтому специальный код начала
и завершения для них не требуется. Процедуры, вызываемые Windows,
обычно используют  соглашения  по  вызову,  принятые  в   Паскале
(PASCAL). Например:

     .
     .
     .
     Winoproc PROC WINDOWS PASCAL FAR
     ARG __hwnd:WORD, __mess:WORD, __wparam:WORD, __lparam:DWORD
          ; тело процедуры
     ENDP
     .
     .
     .

           Примечание: Подробности о процедурах Windows можно уз-
      нать в документации по Windows.

     Модификаторы языка  ODDNEAR и ODDFAR используются для менед-
жера оверлеев VROOM.  VROOM имеет два режима операций:  oddnear и
oddfar. Чтобы увидеть код начала и завершения,  который порождают
эти модификаторы, вы можете использовать параметр командной стро-
ки /la.

         Определения аргументов и локальных переменных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Турбо Ассемблер передает аргументы процедурам языка высокого
уровня в кадре стека,  занося аргументы в стек перед вызовом про-
цедуры. Когда в процедуре языка требуются аргументы, она считыва-
ет их из стека.  Когда процедура возвращает управление,  она либо
удаляет аргументы из стека (соглашения по вызову  Паскаля),  либо
предполагает,  что  аргументы удаляются из стека вызывающей прог-
раммы (соглашения по вызову языка Си).

     В описании процедуры передаваемые  в  процедуру  через  кадр
стека аргументы задаются директивой ARG. Аргументы имеют внутрен-
нее представление в виде положительных смещений от  регистров  BP
или EBP.

     Языковые соглашения  процедуры  определяют,  будут аргументы
заносится в стек в прямом или обратном порядке. В списке аргумен-
тов директивы ARG аргументы нужно указывать в том порядке,  в ко-
тором они указываются в  описании  процедуры  на  языке  высокого
уровня.

     Директива LOCAL  в  описании  процедуры задает в кадре стека
переменные, локальные для процедуры.  Аргументы имеют  внутреннее
представление в  виде  отрицательных  смещений от регистра BP или
EBP.

     Выделить пространство для локальных переменных  кадра  стека
можно с помощью включения в процедуру кода инициализации, смещаю-
щего вниз указатель стека на нужную величину. Код завершения про-
цедуры должен отбрасывать это лишнее пространство, восстанавливая
указатель стека. (Когда процедура подчиняется любым языковым сог-
лашениям, отличным  от NOLANGUAGE,  Турбо Ассемблер автоматически
генерирует этот код завершения.)

     Нужно помнить о том,  что Турбо Ассемблер предполагает,  что
процедура, использующая аргументы кадра стека, содержит соответс-
твующий код инициализации,  устанавливающий регистр BP  или  EBP.
(Когда процедура подчиняется любым языковым соглашениям, отличным
от NOLANGUAGE,  Турбо Ассемблер автоматически генерирует этот код
завершения.) Даже  если  процедура использует языковые соглашения
NOLANGUAGE, задавайте аргументы и локальные  переменные процедуры
с помощью  директив ARG и LOCAL.  Однако в этом случае код начала
(код инициализации) и завершения автоматически не генерируется.

               Синтаксис директив ARG и LOCAL
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Приведем синтаксис  определения передаваемых процедуре аргу-
ментов:

     ARG аргумент [,аргумент] ... [=идентификатор]
         [RETURNS аргумент] [,аргумент]]

     При определении  локальных переменных процедуры используется
следующий синтаксис:

     LOCAL аргумент [,аргумент] ... [=идентификатор]

     Отдельные аргументы имеют следующий синтаксис:

     имя_аргумента [[выражение_счетчик_1]]
                [: сложный_тип [:выражение_счетчик_2]]

где "сложный_тип" - это тип данных аргумента.  Он может быть либо
простым типом,  либо сложным выражением-указателем.  Подробнее  о
синтаксисе сложных типов рассказывается  в Главе 5.

     Если вы не задаете поле "сложный_тип", Турбо Ассемблер пред-
полагает WORD.  При выборе 32-разрядной  модели  он  предполагает
DWORD.

     "Выражение_счетчик_2" задает, сколько элементов данного типа
определяет аргумент. Например, в определении аргумента:

     ARG tmp:DWORD:4

определяется аргумент с именем  "tmp",  состоящий  из  4  двойных
слов.

     По умолчанию  "выражение_счетчик_2"  имеет значение 1 (кроме
аргументов типа BYTE.  Так как вы не можете занести в стек байто-
вое значение, для аргументов типа BYTE значение счетчика по умол-
чанию равно 2,  что обеспечивает для них в стеке размер в  слово.
Это согласуется с языками высокого уровня, которые интерпретируют
передаваемые в качестве параметров символьные переменные. Если вы
действительно хотите задать аргумент, как один байт в стеке, нуж-
но явным образом определить значение  поля "выражение_счетчик_2",
равное 1. Например:

     ARG realbyte:BYTE:1

     "Выражение_счетчик_1" представляет   собой  число  элементов
массива. Общее пространство, резервируемое для аргумента в стеке,
равно произведению "выражения_счетчик_2" на длину, заданную полем
"тип_аргумента" и на "выражение_счетчик_1". Если поле "выражение_
счетчик_1" не  задано,  то по умолчанию оно равно 1.  Общее число
аргументов задает произведение "выражения"_счетчик_1" на "выраже-
ние_счетчик_2".

     Если вы  завершаете список аргументов символом равенства (=)
и идентификатором,  то Турбо Ассемблер  будет  приравнивать  этот
идентификатор к  общему размеру блока аргументов (в байтах). Если
вы не используете автоматическое использование  соглашений языков
высокого уровня в Турбо Ассемблере, то можете использовать данное
значение в конце процедуры в качестве аргумента  инструкции  RET.
Заметим, что  это  вызывает очистку стека от всех занесенных туда
перед возвратом аргументов (это соглашения по вызову,  принятые в
Паскале).

     Аргументы и переменные определяются в процедуре как операнды
в памяти относительно BP.  Передаваемые аргументы, определенные с
помощью директивы ARG,  имеют положительное смещение относительно
BP. Локальные переменные, определенные с помощью директивы LOCAL,
имеют отрицательное смещение от BP. Приведем пример:

     .
     .
     .
     func1 PROC NEAR
     ARG a:WORD,b:WORD:4,c:BYTE=d
     LOCAL x:DWORD,y=WORD:2=z
     .
     .
     .

     Здесь a   определяется,  как  [bp+4],  b  определяется,  как
[bp+6],  c определяется,  как [bp+14],  а d - как  20.  x  -  это
[bp-2], y - [bp-6], а z - 8.

   Область действия аргументов и имен локальных переменных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Если вы не задаете для них имена с  предшествующий префиксом
локального идентификатора,  все  аргументы,  заданные в заголовке
процедуры, определены ли они с помощью директивы ARG  (передавае-
мые аргументы),  RETURN  (возвращаемые  аргументы) или LOCAL (ло-
кальные переменные) имеют глобальную область действия.

     Идентификаторы с локальной областью действия разрешает дирек-
тива LOCALS. Например:

     .
     .
     .
     LOCALS
     test1 PROC PASCAL FAR
     ARG @a:WORD,@d:WORD,@c:BYTE
     LOCAL @x:WORD,@y:DWORD
        MOV ax,@a
        MOV @x,ax
        LES di,@b
        MOV WORD ptr @y,di
        MOV WORD ptr @y+2,es
        MOV @c,'a'
        RET
     ENDP

     test2 PROC PASCAL FAR
     ARG @a:DWORD,@b:BYTE
     LOCAL @x:WORD
        LES di,@a
        MOV ax,es:[di]
        MOV @x,ax
        CMP a1,@b
        jz @dn
        MVO @x,0
     @dn: MOV ax,@x
        RET
     ENDP
     .
     .
     .

           Примечание: Об  управлении областью действия идентифи-
      каторов подробнее рассказывается в Главе 11.

     Поскольку в данном примере используются переменные локальной
области действия,  их имена существуют только в  теле  процедуры.
Таким образом,  в  test2 можно снова использовать имена @a,  @b и
@x.

                    Сохранение регистров
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Большинство языков высокого уровня требуют, чтобы вызываемые
процедуры сохраняли определенные регистры. Это можно сделать, за-
нося их  в  стек  в  начале процедуры и извлекая из стека в конце
процедуры.

     Турбо Ассемблер может  автоматически  генерировать  код  для
сохранения и восстановления этих регистров,  который включается в
код начала и завершения.  Эти регистры можно указать в  операторе
USES, который имеет следующий синтаксис:

     USES элемент [,элемент] ...

где "элемент" может быть регистром или состоящим из одной лексемы
элементом данных,  который можно заносить и извлекать из стека. В
одной процедуре допускается использовать не  более  8  элементов.
Например:

     .
     .
     .
     myproc PROC PASCAL NEAR
     ARG @source:DWORD,@dest:DWORD,@count:WORD
     USES cx,si,di,foo
         MOV cx,@count
         MOV foo,@count
         LES di,@dest
         LDS si,@source
         REP MOVSB
     ENDP
     .
     .
     .

     О сохранении регистров в языках Си и Паскаль можно подробнее
узнать в Главе 18 и 19.

     Оператор USES можно использовать только  в  тех  процедурах,
которые используют языковые соглашения, отличные от NOLANGUAGE.

        Вложенные процедуры и правила области действия
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Хотя вы можете вкладывать одну процедуру в другую,  все про-
цедуры имеют глобальную область действия, Например:

     .
     .
     .
     test1 PROC FAR
        ; код процедуры
        CALL test2
        ; код процедуры
        RET
     test2 PROC NEAR
        ; код процедуры
        RET   ; ближний возврат
     test2 ENDP
     test1 ENDP
     .
     .
     .

     В данном примере вне охватывающей процедуры  можно  вызывать
test1 и test2.

     Если вы  хотите получить локальные подпроцедуры, используйте
имя с локальной областью действия, например:

     .
     .
     .
     LOCALS
     test1 PROC FAR        ; код процедуры
        RET
     @test2 PROC NEAR      ; код процедуры
        RET
     @test2 ENDP
     test1 ENDP
     .
     .
     .

           Примечание: Директива LOCALS  разрешает идентификаторы
      с локальной областью действия.  Подробнее об этом рассказы-
      вается в Главе 11.

     В данном коде в процедуре test1 вы можете  обратиться только
к процедуре @test2.  Фактически,  если они не находятся в одной и
той же  процедуре может  существовать несколько процедур с именем
@test2. Например, допустимо следующее:

     .
     .
     .
     LOCALS
     test1 PROC FAR
        MOV si, OFFSET Buffer
        CALL @test2
        RET
     @test2 PROC NEAR           ; некоторый код
        RET
     @test2 ENDP

     test2 PROC FAR
        MOV si,OFFSET Buffer2
        CALL @test2
        RET
     @test2 PROC NEAR          ; некоторый код
        RET
     @test2 ENDP
     test2 ENDP
     .
     .
     .

     Следующий код недопустим:

     .
     .
     .
     lOCALS
     test1 PROC FAR
        MOV si,OFFSET Buffer
        CALL @test2
        RET
     test1 ENDP

     @test2 PROC NEAR
        ; код процедуры
        RET
     @test2 ENDP
     .
     .
     .

так как вызов @test2 задает локальный идентификатор для процедуры
test1, а таких идентификаторов не существует.

          Описание процедур методов для объектов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     При создании процедур методов для объектов применяются неко-
торые специальные соглашения.  Процедуры методов объектов  должны
иметь возможность  должны иметь возможность доступа к объекту,  с
которым они работают.  Таким образом, в качестве параметра проце-
дуры должен использоваться указатель на объект.

     Турбо Ассемблер  интерпретирует  объекты  достаточно гибко и
позволяет использовать для передачи аргументов процедурам методов
разнообразные  соглашения.  Эти  соглашения ограничиваются только
необходимостью взаимодействовать  с  объектами,  создаваемыми  на
языке высокого уровня.

     Если вы  пишете  процедуру метода объекта на самом языке Ас-
семблера, то может оказаться полезным  использование  соглашения,
по которому  аргументы  передаются через регистры.  В этом случае
вам следует написать процедуру метода,  воспринимающую  указатель
на объект в регистре или паре регистров ES:DI).

     Если вы пишете процедуру метода, которая использует соглаше-
ния по интерфейсу языка  высокого  уровня,  то  процедура  должна
воспринимать указатель  объекта в одном из аргументов.  Указатель
объекта, передаваемый из объектно-ориентированных языков высокого
уровня (таких как С++),  представляет собой неявный аргумент, по-
мещаемый в начало списка аргументов. Процедура метода, написанная
на языке  Ассемблера,  должна  явно  включать в список аргументов
указатель объекта.  В противном случае вы можете получить непред-
виденные результаты.  Нужно  помнить,  что в зависимости от того,
является ли объект ближним (NEAR) или  дальним  (FAR),  указатель
может быть величиной WORD или DWORD.

     Когда вы пишете на языке Ассемблера конструктор или деструк-
тор, могут возникнуть другие сложности.  Чтобы указать, что конс-
труктор  или  деструктор  должен выполнять определенные действия,
С++ использует (при некоторых обстоятельствах)  использует другие
неявные аргументы.

           Примечание: Об используемых в С++ соглашениях по вызо-
      ву рассказывается в Главе 18.

     Конструкторам, написанным на языке Ассемблера, не обязатель-
но требуется передавать указатель на объект.  Если объект никогда
не распределяется статически, то конструктор объекта всегда будет
выделять для  объекта память из динамически распределяемой облас-
ти.

     Глава 11. Управление областью действия идентификаторов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В Турбо Ассемблере и большинстве других языков  программиро-
вания идентификатор в зависимости от того, где он находится в мо-
дуле, может   иметь   разное   значение.   Например,    некоторые
идентификаторы могут  иметь одно и то же значение во всем модуле,
а другие определены только для конкретной процедуры.

     Под областью действия понимается диапазон строк,  в  котором
идентификатор имеет  определенное значение.  Для разработки прог-
рамм, использующих принципы модульного программирования, правиль-
ное задание  области  действия идентификатора имеет важное значе-
ние. Управляя  областью  действия   идентификатора,   вы   можете
управлять его использованием. Кроме того, правильный выбор облас-
ти действия идентификатора может устранить  проблемы, возникающие
при многократном определении идентификатора с одним и тем же име-
нем.

               Переопределяемые идентификаторы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Некоторые типы  идентификаторов,  которые поддерживает Турбо
Ассемблер, рассматриваются как  переопределяемые.  Это  означает,
что вы  можете  в любом месте модуля переопределить идентификатор
данного типа другим идентификатором данного типа. Этим свойством,
например, обладают числовые идентификаторы:

     foo     = 1
          mov ax,foo         ; поместить 1 в AX
     foo    = 2
          mov ax,foo         ; поместить в AX 2

     В общем случае область  действия  данного  переопределяемого
идентификатора начинается  в точке его определения и продолжается
до того места,  в котором он переопределяется.  Область  действия
последнего переопределения идентификатора включает в себя область
от начало модуля до первого определения идентификатора. Например:

        mov ax,foo         ; поместить 2 в AX!
     foo  = 1
        mov ax,foo         ; поместить 1 в AX
     foo  = 2              ; это определение расширяется на
                           ; начало модуля...
        mov ax,foo         ; поместить 2 в AX

     Типы переопределяемых  идентификаторов перечислены в следую-
щем списке:

     - текстовая макрокоманда;

     - числовое выражение;

     - макрокоманда из нескольких строк;

     - структура/объединения;

     - таблица;

     - запись;

     - перечисление.

           Примечание: Об этом подробнее рассказывается  в  Главе
      5.

               Область действия в границах блока
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Ограничение области действия границами блока позволяет иден-
тификатору иметь область действия,  соответствующую процедуре или
функции. Турбо Ассемблер поддерживает два типа области действия в
границах блока: в стиле MASM и в стиле самого Турбо Ассемблера.

                 Директивы LOCALS и NOLOCALS
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

     LOCALS [префикс_идентификатора]

     Необязательное поле  "префикс_идентификатора" содержит иден-
тификатор (размером в два символа), который Турбо Ассемблер будет
использовать в качестве префикса локального идентификатора.  Нап-
ример:

     LOCALS          ; по умолчанию подразумевается использование
                     ; в качестве префикса @@
     foo proc
     @@a:     jmp @@a ; этот идентификатор @@a относится к
                    ; процедуре FOO
     foo endp

     bar proc
     @@a:    jmp @@a ; этот идентификатор @@a относится к про-
                     ; цедуре BAR
     bar endp

     Если вы хотите запретить идентификаторы с локальной областью
действия, можно использовать директиву NOLOCALS. Она имеет следу-
ющий синтаксис:

     NOLOCALS

     Заметим, что вы можете  использовать  идентификаторы  с  об-
ластью действия в границах блока вне процедур.  В этом случае об-
ласть действия идентификатора определяется метками,  заданными  с
помощью  двоеточия,  которые  на  являются идентификаторами с об-
ластью действия в границах блока. Например:

     foo:            ; начало области действия
     @@a:            ; относится к области действия, начинающейся
                     ; FOO:
     @@b = 1         ; относится к области действия, начинающейся
                     ; FOO:
     BAR:            ; начало области действия
     @@a = 2         ; относится к области действия, начинающейся
                     ; BAR:

          Область действия в границах блока в MASM
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
     В MASM версий 5.1 и 5.2 метки NEAR,  определенные с  помощью
директивы двоеточия (:),  если они находятся в процедуре,  и если
вы выбрали в директиве  MODEL  соглашения  языка,  имеют  область
действия в границах блока.  Однако эти идентификаторы не являются
полными идентификаторами,  имеющими область действия  в  границах
блока:  нигде  в программе их нельзя определить никак иначе,  чем
как ближнюю метку. Например:

     varsion m510
     model small,c

     codeseg

     foo proc
     a: jmp a       ; относится к процедуре FOO
     foo endp

     bar proc
     a: jmp a      ; относится к процедуре BAR
     bar endp

     a = 1        ; недопустимо!

                Локальные метки в стиле MASM
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     В MASM 5.1 и 5.2 предусмотрены  специальные  идентификаторы,
которые вы  можете  использовать для управления областью действия
ближних меток в небольшом диапазоне строк. Это идентификаторы @@,
@F и @B.

     Когда вы описываете @@, как ближнюю метку, используя двоето-
чие (:), то определяете уникальный идентификатор вида @@xxxx (где
xxxx -  это  шестнадцатиричное число).  @B ссылается на последний
определенный таким образом идентификатор. @F ссылается на следую-
щий идентификатор с определением такого вида. Например:

     version m510
     @@:
        jmp @B         ; перейти на предыдущий идентификатор @@
        jmp @F         ; перейти на следующий идентификатор @@
     @@:
        jmp @B         ; перейти на предыдущий идентификатор @@
        jmp @F         ; ошибка: нет следующего @@

              Глава 12. Определение данных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Директивы определения данных используются для выделения байт
в  сегменте.  Вы можете также использовать их для заполнения этих
байт начальными данными и определения переменных данных.

     Все директивы  определения  данных  имеют  некоторые   общие
средства.  Во  первых  они  могут генерировать инициализированные
данные и резервировать место для неинициализированных данных. Для
инициализированных данных определяется некоторое начальное значе-
ние. Неинициализированные данные определяются без задания началь-
ного значения (говорят,  что их начальное значение является неоп-
ределенным). В директивах определения данных неинициализированные
данные указываются с помощью символа ?.  Все прочее должно предс-
тавлять значение инициализированных данных.  О том,  как  следует
различать инициализированные и неинициализированные данные, расс-
казывается в Главе 7.

     Другим средством,  которое применяется  во  всех  директивах
определения данных,  является использование для указания повторе-
ния блока данных ключевого слова DUP.  Приведем  общий  синтаксис
всех директив распределения данных:

     [имя_директивы [выражение_dup [выражение_dup...]]

     Турбо Ассемблер  инициализирует  "имя" таким образом,  чтобы
оно указывало на резервируемую директивой область. Тип данной пе-
ременной зависит от фактически используемой директивы.

     Каждое "выражение_dup" может иметь следующий синтаксис:

     - ?;

     - значение;

     - выражение_счетчик DUP( выражение_dup[,выражение_dup...]);

где "выражение_счетчик"  задает,  сколько  раз  будет повторяться
блок данных.  "Выражение_счетчик" не может быть  относительным  и
иметь опережающие ссылки.

     Если вы хотите получить неинициализированные данные, исполь-
зуйте идентификатор ?.  Объем резервируемой для неиницализирован-
ных данных памяти зависит от фактически используемой директивы.

     "Значение" предназначено для фактического описания отдельно-
го элемента  данных  в  каждой директиве.  В некоторых директивах
поле значения может быть очень сложным и содержать много  элемен-
тов, другие могут потребовать только простого выражения.

     В следующем примере используется директива DW, которая выде-
ляет слова:

     DW 2 DUP (3 DUP (1,3),5) ; эквивалентно директиве
                              ; DS 1,3,1,3,1,35,1,3,1,3,1,3,5

            Простые директивы определения данных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Вы можете определять данные с помощью директив DB,  DW,  DD,
DQ, DF, DP или DT. Как показано в следующей таблице, эти директи-
вы выделяют простые данные различного размера:

   Директивы определения данных различного размера   Таблица 12.1
ЪДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і  Директива   і  Значение                                      і
ГДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    DB        і  Определение данных размером в байт.           і
і              і                                                і
і    DW        і  Определение данных размером в слово.          і
і              і                                                і
і    DD        і  Определение данных размером в двойное слово.  і
і              і                                                і
і    DQ        і  Определение данных размером в четверное слово.і
і              і                                                і
і    DF        і  Определение данных размером в 6 байт (48-бито-і
і              і  вый дальний указатель процессора 80386).      і
і              і                                                і
і    DP        і  Определение данных размером в 6 байт (48-бито-і
і              і  вый дальний указатель процессора 80386).      і
і              і                                                і
і    DT        і  Определение данных размером в 10 байт.        і
АДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Синтаксис поля "значение" для каждой из этих директив разли-
чается и основывается на возможности представлять отдельные вели-
чины с помощью данных определенного размера  (например,  байтовые
данные нельзя интерпретировать, как число с плавающей точкой).

     В директиве DB (байт) можно задавать следующие значения:

     - Выражение-константу,  имеющую значения в диапазоне от -128
       до 255 (байты со знаком в диапазоне от -128 до +127; безз-
       наковые байтовые значения в диапазоне от 0 до 255).

     - 8-битовое относительное выражение,  использующее  операции
       HIGH и LOW.

     - Символьную  строку из 1 или более символов с использование
       стандартного формата заключенной в кавычки строки.  В этом
       случае  определяется  несколько байт,  по одному на каждый
       символ строки.

     Значениями директивы DW (слово) могут быть:

     - Выражение-константа в диапазоне от -32768 до  65535 (слова
       со знаком в диапазоне от -32768 до 32767, беззнаковые сло-
       ва в диапазоне от 0 до 65535).

     - Относительное  выражение,  занимающее  16  или  менее  бит
       (включая смещение в 16-битовом сегменте,  сегмент или зна-
       чение группы).

     - Одно- или двухбайтовая строка в стандартном формате (стро-
       ка, заключенная в кавычки).

     Значениями директивы DD (двойное слово) могут быть:

     - Выражение-константа   в   диапазоне   от   -2147483648  до
       4294967295 (при выборе процессора 80386) или от  -32768 до
       65535 в противном случае.

     - Относительное адресное выражение, состоящее из 16-битового
       сегмента и 16-битового смещения.

     - Строка длиной до 4 символов в стандартном формате (строка,
       заключенная в кавычки).

     Значениями директивы DQ (четверное слово) могут быть:

     - Выражение-константа   в   диапазоне   от   -2147483648  до
       4294967295 (при выборе процессора 80386) или от  -32768 до
       65535 в противном случае.

     - Относительное или адресное выражение,  состоящее из 32 или
       менее бит (при выборе процессора 80386) или 16  или  менее
       бит (для всех других процессоров).

     - Положительная или отрицательная константа,  имеющая значе-
       ние в диапазоне от -2 с 63 степени до  2  в  степени  63-1
       (четверное слово  со  знаком в диапазоне от 2 в 63 степени
       до 2 в степени 63-1,  беззнаковое четверное слово в диапа-
       зоне от 0 до 2 в степени 64-1).

     - Строка длиной до 8 байт в стандартном формате (строка, за-
       ключенная в кавычки).

     Значениями директив DF и DP  (48-битовый  дальний  указатель
процессора 80386) могут быть:

     - Выражение-константа   в   диапазоне   от   -2147483648  до
       4294967295 (при выборе процессора 80386) или от  -32768 до
       65535 в противном случае.

            Простые директивы определения данных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Вы можете определять данные с помощью директив DB,  DW,  DD,
DQ, DF, DP или DT. Как показано в следующей таблице, эти директи-
вы выделяют простые данные различного размера:

   Директивы определения данных различного размера   Таблица 12.1
ЪДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і  Директива   і  Значение                                      і
ГДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і    DB        і  Определение данных размером в байт.           і
і              і                                                і
і    DW        і  Определение данных размером в слово.          і
і              і                                                і
і    DD        і  Определение данных размером в двойное слово.  і
і              і                                                і
і    DQ        і  Определение данных размером в четверное слово.і
і              і                                                і
і    DF        і  Определение данных размером в 6 байт (48-бито-і
і              і  вый дальний указатель процессора 80386).      і
і              і                                                і
і    DP        і  Определение данных размером в 6 байт (48-бито-і
і              і  вый дальний указатель процессора 80386).      і
і              і                                                і
і    DT        і  Определение данных размером в 10 байт.        і
АДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

     Синтаксис поля "значение" для каждой из этих директив разли-
чается и основывается на возможности представлять отдельные вели-
чины с помощью данных определенного размера  (например,  байтовые
данные нельзя интерпретировать, как число с плавающей точкой).

     В директиве DB (байт) можно задавать следующие значения:

     - Выражение-константу,  имеющую значения в диапазоне от -128
       до 255 (байты со знаком в диапазоне от -128 до +127; безз-
       наковые байтовые значения в диапазоне от 0 до 255).

     - 8-битовое относительное выражение,  использующее  операции
       HIGH и LOW.

     - Символьную  строку из 1 или более символов с использование
       стандартного формата заключенной в кавычки строки.  В этом
       случае  определяется  несколько байт,  по одному на каждый
       символ строки.

     Значениями директивы DW (слово) могут быть:

     - Выражение-константа в диапазоне от -32768 до  65535 (слова
       со знаком в диапазоне от -32768 до 32767, беззнаковые сло-
       ва в диапазоне от 0 до 65535).

     - Относительное  выражение,  занимающее  16  или  менее  бит
       (включая смещение в 16-битовом сегменте,  сегмент или зна-
       чение группы).

     - Одно- или двухбайтовая строка в стандартном формате (стро-
       ка, заключенная в кавычки).

     Значениями директивы DD (двойное слово) могут быть:

     - Выражение-константа   в   диапазоне   от   -2147483648  до
       4294967295 (при выборе процессора 80386) или от  -32768 до
       65535 в противном случае.

     - Относительное адресное выражение, состоящее из 16-битового
       сегмента и 16-битового смещения.

     - Строка длиной до 4 символов в стандартном формате (строка,
       заключенная в кавычки).

     Значениями директивы DQ (четверное слово) могут быть:

     - Выражение-константа   в   диапазоне   от   -2147483648  до
       4294967295 (при выборе процессора 80386) или от  -32768 до
       65535 в противном случае.

     - Относительное или адресное выражение,  состоящее из 32 или
       менее бит (при выборе процессора 80386) или 16  или  менее
       бит (для всех других процессоров).

     - Положительная или отрицательная константа,  имеющая значе-
       ние в диапазоне от -2 с 63 степени до  2  в  степени  63-1
       (четверное слово  со  знаком в диапазоне от 2 в 63 степени
       до 2 в степени 63-1,  беззнаковое четверное слово в диапа-
       зоне от 0 до 2 в степени 64-1).

     - Строка длиной до 8 байт в стандартном формате (строка, за-
       ключенная в кавычки).

     Значениями директив DF и DP  (48-битовый  дальний  указатель
процессора 80386) могут быть:

     - Выражение-константа   в   диапазоне   от   -2147483648  до
       4294967295 (при выборе процессора 80386) или от  -32768 до
       65535 в противном случае.

     - Относительное или адресное выражение,  состоящее из 32 или
       менее бит (при выборе процессора 80386) или 16  или  менее
       бит (для всех других процессоров).

     - Относительное адресное выражение, состоящее из 16-битового
       сегмента и 16-битового смещения.

     - Положительная или отрицательная константа,  имеющая значе-
       ние в диапазоне от -2 в 47 степени до 2 в степени 48-1 (6-
       байтовое значение со знаком в диапазоне от 2 в  47 степени
       до 2 в степени 47-1, беззнаковое 6-байтовое значение в ди-
       апазоне от 0 до 2 в степени 48-1).

     - Строка длиной до 6 байт в стандартном формате (строка, за-
       ключенная в кавычки).

     Значениями директивы DT могут быть:

     - Выражение-константа   в   диапазоне   от   -2147483648  до
       4294967295 (при выборе процессора 80386) или от  -32768 до
       65535 в противном случае.

     - Относительное или адресное выражение,  состоящее из 32 или
       менее бит (при выборе процессора 80386) или 16  или  менее
       бит (для всех других процессоров).

     - Относительное адресное выражение, состоящее из 16-битового
       сегмента и 16-битового смещения.

     - Положительная или отрицательная константа,  имеющая значе-
       ние в диапазоне от -2 в 79 степени до 2 в степени 80-1 (10
       -байтовое значение со знаком в диапазоне от 2 в 79 степени
       до 2 в степени 79-1,  беззнаковое 10-байтовое  значение  в
       диапазоне от 0 до 2 в степени 80-1).

     - Строка длиной до 10 байт в  стандартном  формате  (строка,
       заключенная в кавычки).

     - Упакованная десятичная константа,  имеющая значение в диа-
       пазоне от 0 до 99999999999999999999.

            Примечание: При сохранении данных  в  памяти  младшее
       значение всегда записывается перед старшим значением.

     В некоторых случаях числовые и строковые константы в  дирек-
тивах определения  простых  данных  отличаются  от  тех,  которые
встречаются в стандартных выражениях Турбо  Ассемблера. Например,
директивы  DB,  DP,  DT  и  DQ воспринимают заключенные в кавычки
строки,  которые могут иметь большую длину, чем строки, восприни-
маемые в выражениях.

     Заключенные в  кавычки  строки выделяются одинарными (') или
двойными (") кавычками. Внутри строки два ограничителя указывают,
что данный символ-ограничитель должен быть частью строки,  напри-
мер:

     'what''s up doc?'

представляет следующие символы:

     what's up doc?

     В качестве значения в директивах DD, DQ и DT можно указывать
числа с плавающей точкой. Приведем некоторые примеры таких чисел:

     1.0E30                ; означает 1.0x10^30
     2.56E-21              ; означает 2.56х10^E-21
     1.28E+5               ; означает 1.28х10^+5
     0.025                 ; означает .025

     Турбо Ассемблер распознает эти  числа  с  плавающей  точкой,
поскольку они содержат после начальной цифры символ точки. В MASM
эти правила могут быть ослаблены, например:

     DD 1E30       ; допустимое значение с плавающей точкой в
                   ; режиме MASM
     DD .123       ; допустимо только в режиме MASM

           Примечание: Для  ясности вы рекомендуем всегда исполь-
      зовать начальную цифру и десятичную точку.

     Турбо Ассемблер  допускает  также указывать в директивах DD,
DQ и DT кодированные вещественные числа.  Кодированное веществен-
ное число - это шестнадцатиричное число точно определенной длины.
Суффикс R указывает,  что число будет интерпретироваться, как ко-
дированное вещественное число.  Длина числа должна заполнять тре-
буемое поле (плюс одна цифра,  если начальной цифрой является  0.
Например:

     DD  12345678r        ; допустимое число
     DD  012345678r       ; допустимое число
     DD  1234567r         ; недопустимое число (слишком
                          ; короткое)

     Другие значения суффиксов (D,  H, O, B) действуют аналогично
тем, которые указываются в обычных выражениях.

     Некоторые простые директивы определения данных интерпретиру-
ют другие числовые константы особым образом. Например, если вы не
задаете основания для значения в директиве DT, то Турбо Ассемблер
использует двоично-десятичное представление (BCD).  Другие дирек-
тивы предполагают десятичное значение:

     DD 1234            ; десятичное
     DT 1234            ; BCD

     Если значение  представляет  собой простую положительную или
отрицательную константу, используемое по умолчанию основание (за-
даваемое  директивой RADIX) не применяется в директивах DD,  DQ и
DT. Например:

     RADIX 16
     DW 1234           ; шестнадцатиричное значение 1234
     DD 1234           ; десятичное значение 1234

           Примечание: Числовые константы и директива RADIX  под-
      робнее описываются в Главе 5.

        Создание экземпляра структуры или объединения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Чтобы создать экземпляр типа данных,  представляющего  собой
структуру или объединения, используйте в качестве директивы опре-
деления данных  имя структуры или объединения.  Предположим, нап-
ример, что вы определили следующее:

     ASTRUC STRUC
     B   DB "xyz"
     C   DW 1
     D   DD 2
     ASTRUC ENDS

     BUNION UNION
     X   DW  ?
     Y   DD  ?
     Z   DB  ?
     BUNION ENDS

     Тогда операторы:

     ATEST          ASTRUC         ?
     BTEST          BUNUION        ?

будут создавать экземпляры структуры astruc (определяя переменную
atest) и  объединения  bunion (определяя переменную btest).  Пос-
кольку в примере указывается значение неинициализированных данных
?, то начальные данные в текущий сегмент не вводятся.

     Инициализация экземпляра структуры или объединения
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Инициализированные экземпляры  структуры   несколько   более
сложны, чем неинициализированные. Когда вы определяете структуру,
вам нужно определить используемое по умолчанию начальное значение
для каждого  ее  элемента.  (В качестве начального значения можно
использовать ключевое слово ?, которое указывает, что конкретного
начального значения  сохранять не следует.) Когда вы создаете эк-
земпляр структуры, его можно создать с использованием значений по
умолчанию или переопределяемых значений. Простейший инициализиро-
ванный экземпляр структуры содержит просто заданные в определении
начальные значения. Например:

     ASTRUC {}

что эквивалентно следующему:

     DB "xyz"
     DW  1
     DD  2

     Фигурные скобки  ({}) представляет нулевой инициализатор для
структуры. Значение-инициализатор определяет,  что элементы (если
они имеются) должны иметь начальные значения, которые следует пе-
реопределить, и какими новыми значениями,  если вы выделяете дан-
ные для экземпляра структуры.  Инициализатор в виде фигурных ско-
бок имеет следующий синтаксис:

    { [имя_элемента = значение [,имя_элемента...]] }

где "имя_элемента" - это имя элемента структуры  или объединения,
а "значение" - это то значение,  которое вы хотите присвоить эле-
менту в данном экземпляре.  Чтобы указать Турбо  Ассемблеру,  что
для элемента нужно использовать начальное значение из определения
структуры или объединения,  задайте нулевое значение.  Значение ?
показывает, что этот элемент инициализировать не нужно. Турбо Ас-
семблер присваивает всем элементам, которые не указываются в ини-
циализаторе, начальное значение из определения структуры или объ-
единения, например:

     ASTRUC {C=2,D=?}

эквивалентно следующему:

     DB "xyz"
     DW  2
     DD  ?

     Вы можете использовать инициализатор в виде  фигурных скобок
для задания  значения  любого элемента структуры или объединения,
даже если он находится во вложенной структуре или объединении.

     Объединения отличаются от  структур,  поскольку  элементы  в
объединении перекрывают  друг друга.  Будьте аккуратны,  когда вы
инициализируете экземпляр  структуры,  поскольку  если  несколько
элементов перекрывают друг друга, Турбо Ассемблер допускает, что-
бы в  экземпляре только один элемент имел инициализирующее значе-
ние. Например:

     BUNION {}

допустимо, поскольку  все  три элемента в определении объединения
являются неинициализированными. Данный оператор эквивалентен сле-
дующему:

     BD  4  DUP (?)

     В данном  примере 4 байта зарезервированы,  поскольку размер
объединения равен размеру его наибольшего элемента (в данном слу-
чае DWORD).  Если инициализированный элемент объединения не явля-
ется наибольшим элементом объединения, то Турбо Ассемблер воспол-
няет разницу, резервируя место, но не генерируя данные, например:

     BUNION {Z=1}

эквивалентно следующему:

     DB  1
     DB  3 DUP (?)

     Наконец, несколько инициализированных  элементов объединения
приведут к ошибке. Следующее, например, не допускается:

     BUNION {X=1,Z=2}

     Заметим, что  если  два или более поля объединения имеют на-
чальные значения  в  определении  объединения,  то  использование
простого инициализатора  в  виде фигурных скобок также приведет к
ошибке. Чтобы генерировался допустимый  экземпляр,  инициализатор
должен устанавливать только одно значение ?.

     Альтернативным методом инициализации структуры или объедине-
ния является использование инициализатора в виде  угловых  скобок
(<>). Значения  такого инициализатора являются неименованными, но
располагаются в том же порядке,  что и соответствующие элементы в
определении структуры  или объединения.  Для этого инициализатора
используется следующий синтаксис:

     < [значение [,значение...]] >

где "значение" представляет нужное значение соответствующего эле-
мента в определении структуры или  объединения.  Пустое  значение
указывает, что вы будете использовать начальное значение из опре-
деления структуры или объединения.  Ключевое слово  ?  указывает,
что элемент должен быть неинициализированным. Например:

     ASTRUC <"ABC"',,?>

эквивалентно следующему:

     DB "abc"
     DW  1
     DD  ?

     Если вы задаете меньше значений, чем имеется элементов, Тур-
бо Ассемблер закончит инициализацию, используя для остальных эле-
ментов начальные значения из определения структуры или  объедине-
ния.

     ASTRUC <"ABC">        ; то же, что ASTRUC <"ABC",,>

     Когда вы  используете  инициализатор  в виде угловых скобок,
уделите особое внимание вложенным структурам и  объединениям. Для
каждого уровня  вложенности в таком инициализаторе требуется ука-
зывать свою пару угловых скобок,  благодаря чему Турбо  Ассемблер
будет интерпретировать  каждый  инициализатор вложенной структуры
или объединения как отдельную единицу (совпадающее со значением в
экземпляре). Оставив соответствующие угловые скобки  пустыми,  вы
можете  пропустить  инициализацию данного уровня вложенности (для
вложенной структуры  или  объединения  используется  значение  по
умолчанию,  либо использовать ключевое слово ? (для неинициализи-
рованной вложенной структуры или объединения).  Рассмотрите, нап-
ример, следующую вложенную структуру и объединение:

     CUNION               STRUC
     CTYPE                DB ?
        UNION             ; начало объединения

        ; если CTYPE = 0, использовать следующее...
        STRUC
     CT0PAR1             DW  1
     CT0PAR2             DW  2
        ENDS

        ; если CTYPE = 1, использовать следующее...
        STRUC
     CT1PAR1             DW  3
     CT1PAR2             DW  4
        ENDS

        ENDS             ; конец объединения
     ENDS

     Инициализатор в  скобках  для  данной  структуры/объединения
имеет два уровня вложенности.  Эта вложенность должна учитываться
соответствующей парой угловых скобок в инициализаторе, например:

     CUNION <0,<<2,>,?>>

     Эта директива эквивалентна следующему:

     DB  0
     DW  2
     DB  2
     DB  2 DUP (?)

                 Создание экземпляра записи
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Чтобы создать экземпляр данных типа записи,  используйте имя
данного типа, как директиву выделения данных. Например, предполо-
жим, что вы определили следующее:

     MYREC RECORD VEL:3=4,MODE:2,SIZE:4=15

     Тогда оператор:

     MTEST         MYREC  ?

будет создавать  экземпляр  записи  myrec  (определяя  переменную
mtest). В данном примере данные в сегмент не помещаются,  так как
задаются неинициализированные данные (?).

     Экземпляры записи  всегда  имеют  размер  в байт,  слово или
двойное слово, в зависимости от числа бит, выделенных при опреде-
лении.

              Инициализация экземпляров записи
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     При определении записи для некоторых или всех  полей  записи
нужно задавать начальное значение. (Турбо Ассемблер предполагает,
что все не заданные значения равны 0.)  Простейший  инициализиро-
ванный экземпляр  записи  содержит  просто заданное в определении
начальное поле данных, например:

     MYREC {}

что эквивалентно следующему:

     DW (4 SHL 6) + (0 SHL 4) + (15 SHL 0)
         ; SHL - это операция сдвига влево для выражений

     Фигурные скобки  ({})  представляют нулевое инициализирующее
значение записи.  Значение инициализатора определяет, что началь-
ное значение нужно переопределить, и каким именно новым значением
его требуется переопределить (если вы выделяете  данные  для  эк-
земпляра записи).

     Инициализатор записи в фигурных скобках имеет следующий син-
таксис:

     { [имя_поля = выражение [,имя_поля = выражение...]] }

где "имя_поля" - это имя поля записи,  а "выражение" - это значе-
ние, которое  вы  хотите определить для поля в данном экземпляре.
Пустое значение указывает,  что вы будете использовать  начальное
значение поля из определения записи.  Значение ? эквивалентно ну-
лю. Турбо Ассемблер устанавливает для всех полей, которые не ука-
зываются в инициализаторе, начальное значение, заданное в опреде-
лении записи. Например:

     MYREC {VEL=2,SZE=?}

эквивалентно следующему:

     DW (2 SHL 6) + (0 SHL 4) + (0 SHL 0)

     Альтернативным методом  инициализации   экземпляров   записи
является использование угловых скобок (<>). В этом случае скобка-
ми ограничивается инициализатор. Значения инициализатора являются
неименованными, но  располагаются  в том же порядке,  что и соот-
ветствующие поля в определении записи. Данный инициализатор имеет
следующий синтаксис:

     <[выражение [,выражение...]]>

где "выражение" представляет нужное значение поля соответствующей
записи в определении записи.  Пустое значение указывает,  что  вы
будете использовать  начальное  значение  из  определения записи.
Ключевое слово ?  указывает,  что это поле должно быть  равно  0.
Например:

     MYREC <,2,?>

эквивалентно следующему:

     DW (4 SHL 6) + (2 SHL 4) + (0 SHL 0)

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

     MYREC <1>                ; то же, что MYREC <1,,>

        Создание экземпляра данных перечислимого типа
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Экземпляр данных перечислимого типа вы можете  создать,  ис-
пользую как директиву определения данных имя  перечислимого  типа
данных. Предположим, например, что вы определили следующее:

     ETYPE       ENUM FEE,FIE,FOO,FUM

     Тогда оператор:

     ETEST       ETYPE ?

будет создавать экземпляр перечислимого типа данных ETYPE  (опре-
деляя переменную ETEST).  В данном примере, поскольку задано зна-
чение неинициализируемых данных ?,  начальные  данные  в  текущем
сегменте не генерируются.

     Экземпляры перечислимого типа данных всегда представляют со-
бой байт,  слово или двойное слов, в зависимости от максимального
значения, представленного в данных перечислимого типа.

     Инициализация экземпляра перечислимого типа данных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Вы можете использовать любое выражение, при вычисление кото-
рого получается число, умещающееся в экземпляре перечислимого ти-
па данных, например:

     ETYPE ?               ; неинициализированный экземпляр
     ETYPE FOO             ; инициализированный экземпляр,
                           ; значение FOO
     ETYPE 255             ; число вне ENUM также подходит

                 Создание экземпляра таблицы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для создания экземпляра таблицы используйте в  качестве  ди-
рективы выделения данных имя таблицы.  Предположим, например, что
вы определили следующую таблицу:

     TTYPE TABLE VIRTUAL MoveProc:WORD=MoveRtn,   \продолжение...
          VIRTUAL MsgProc:DWORD=MsgRtn,           \продолжение...
          VIRTUAL DoneProc:WORD=DoneRtn,

     Тогда оператор:

     TTEST           TTYPE       ?

создает экземпляр таблицы TTYPE (определяя переменную  TTEST).  В
данном примере, поскольку задано значение неинициализируемых дан-
ных ?, начальные данные в текущем сегменте не генерируются.

              Инициализация экземпляров таблицы
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Когда вы определяете таблицу,  нужно задать начальное значе-
ние для всех ее элементов.  Простейший инициализированный экземп-
ляр таблицы  содержит  просто  заданные  в  определении начальные
данные, например:

     TTYPE {}

что эквивалентно следующему:

     DW MoveRtn
     DD MsgRtn
     DW DoneRtn

     Фигурные скобки ({}) представляют  нулевое  инициализирующее
значение.  Значение инициализатора определяет, что элементы (если
они есть) имеют начальное значение, которое нужно переопределить,
и  каким  именно новым значением его требуется переопределить при
выделении данных для экземпляра таблицы.

     Инициализатор записи в фигурных скобках имеет следующий син-
таксис:

     {[имя_элемента = выражение [,имя_элемента = выражение...]]}

где "имя_элемента"  -  это имя элемента таблицы,  а "выражение" -
это значение,  которое вы хотите определить для элемента в данном
экземпляре. Пустое значение указывает, что вы будете использовать
начальное значение элемента из определения  таблицы.  Значение  ?
эквивалентно нулю. Турбо Ассемблер устанавливает для всех элемен-
тов, которые не указываются в инициализаторе, начальное значение,
заданное в определении таблицы. Например:

     TTYPE {MoveProc=MoveRtn2,DoneProc=?}

что эквивалентно следующему:

     DW MoveRtn2
     DD MsgRtn
     DW ?

Создание и инициализация экземпляра именованного типа данных
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для создания экземпляра именованного типа данных используйте
в качестве директивы выделения данных имя типа. Предположим, нап-
ример, что вы определили следующий тип:

     NNTYPE TYPEDEF PTR BYTE

     Тогда оператор:

     NNTEST           NTTYPE       ?

создает экземпляр именованного типа NTYPE  (определяя  переменную
NTTEST).  В данном примере, поскольку задано значение неинициали-
зируемых данных ?, начальные данные в текущем сегменте не генери-
руются.

     Способ инициализации экземпляра именованного типа зависит от
типа, который этот именованный тип представляет. Например, NTTYPE
в предыдущем примере - это слово,  поэтому он будет инициализиро-
ваться, как если бы вы следующим образом  использовали  директиву
DW:

     NTTYPE  1,2,3    ; представляет указатель значений 1,2,3
     DW      1,2,3    ; то же, что NTTYPE 1,2,3

     Однако, если именованный тип представляет структуру или таб-
лицу, то  его нужно инициализировать также,  как инициализируются
структуры и таблицы. Например:

     foo STRUC
     f1  DB ?
     ENDS
     bar TYPEDEF foo
         bar {f1=1}  ; должен быть инициализатор структуры

                 Создание экземпляра объекта
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Создание экземпляра  объекта в инициализированном или неини-
циализированном сегменте данных полностью совпадает  с  созданием
экземпляра структуры.  Фактически,  объекты  в  Турбо  Ассемблере
представляют собой структуры с некоторыми расширениями.  Одним из
таких расширений является элемент структуры @Mptr_<имя_объекта>.

     Объектный тип  данных с виртуальными методами - это структу-
ра, содержащая один элемент, указывающий  на  таблицу  указателей
виртуальных методов. Именем данного элемента является @Mptr_<имя_
объекта>. Обычно инициализируется с помощью  конструктора метода.
Однако, вы можете построить статические объекты, не имеющие конс-
труктора, но инициализируемые с помощью инициализатора в сегменте
данных.

     Если вы  указываете  используемое по умолчанию значение эле-
мента @Mptr_<имя_объекта>,  то Турбо  Ассемблер  будет  корректно
инициализировать экземпляр объекта.

     Другим отличием структур и объектов является то, что объекты
могут наследовать элементы из предыдущих определений объекта. При
подобном наследовании  Турбо  Ассемблер  интерпретирует его,  как
вложенную структуру.  В связи с этим для инициализации  объектных
данных не рекомендуется использовать угловые скобки (<>).

   Создание экземпляра таблицы виртуальных методов объекта
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

     Для каждого объекта, содержащего виртуальные методы, необхо-
димо наличие  доступной  таблицы виртуальных методов.  Правильное
размещение данной таблицы определяет множество  факторов, включая
то, какую  программную модель вы используете,  хотите вы получить
таблицу NEAR или FAR и т.д. Турбо Ассемблер требует от вас только
размещения данной таблицы.  Экземпляр последних определенных объ-
ектов вы можете создать,  используя псевдооперацию TBLINST, кото-
рая имеет следующий синтаксис:

     TBLINST

     TBLINST определяет в качестве адреса таблицы виртуальных ме-
тодов объекта @TableAddr_<имя_объекта>.  Это эквивалентно следую-
щему:

     @TableAddr_<имя_объекта> @TableAddr_<имя_объекта> {}

                       Оглавление

Введение........................................................7
Требования к программному и аппаратному обеспечению.............8
Поддержка DPMI..................................................8
О данной документации...........................................9
Руководство пользователя........................................9
Соглашения по обозначениям.....................................11
Как обратиться за помощью к фирме Borland......................12
Ресурсы вашего пакета..........................................13
Возможности фирмы Borland......................................13
ЧАСТЬ 1. ИСПОЛЬЗОВАНИЕ ТУРБО АССЕМБЛЕРА........................15
Глава 1. Начало работы на Турбо Ассемблере.....................16
Установка Турбо Ассемблера в системе...........................16
Текстовые справочные файлы.....................................17
Файл README....................................................17
Файл HELPME!.TSM...............................................18
Файл H2ASH.TSM.................................................18
Файл TCREF.TSM.................................................18
Оперативный справочник.........................................18
Ваша первая программа на Турбо Ассемблере......................19
Ассемблирование вашей первой программы.........................21
Компоновка программы...........................................23
Запуск вашей первой программы..................................23
Что происходит?................................................23
Модификация вашей первой программы на Турбо Ассемблере.........25
Вывод информации на устройство печати..........................27
Ваша вторая программа на Турбо Ассемблере......................28
Запуск программы REVERSE.ASM...................................30
Литература по языку Ассемблера.................................30
Глава 2. Использование директив и параметров...................32
Запуск Турбо Ассемблера из DOS.................................32
Параметры командной строки.....................................37
Параметр /A....................................................37
Параметр /B....................................................38
Параметр /C....................................................38
Параметр /D....................................................38
Параметр /E....................................................39
Параметр /H или /?.............................................40
Параметр /I....................................................40
Параметр /J....................................................41
Параметр /KH...................................................41
Параметр /L....................................................42
Параметр /LA...................................................42
Параметр /M....................................................43
Параметр /ML...................................................43
Параметр /MU...................................................44
Параметр /MV#..................................................45
Параметр /MX...................................................45
Параметр /N....................................................46
Параметр /O....................................................46
Параметр /OP...................................................46
Параметр /P....................................................46
Параметр /Q....................................................47
Параметр /R....................................................47
Параметр /S....................................................48
Параметр /T....................................................48
Параметр /V....................................................49
Параметр /W....................................................49
Параметр /X....................................................50
Параметр /Z....................................................51
Параметр /ZD...................................................51
Параметр /ZI...................................................52
Параметр /ZN...................................................52
Косвенные командные файлы......................................53
Файлы конфигурации.............................................53
Глава 3. Общие принципы программирования.......................55
Режим Ideal Турбо Ассемблера...................................55
Для чего используется режим Ideal?.............................56
Переключение в режим Ideal и выход из него.....................56
Отличия режима Ideal и режима MASM.............................58
Выражения и операнды...........................................59
Операции.......................................................60
Подавление корректировок.......................................60
Операнд инструкции BOUND.......................................60
Сегменты и группы..............................................61
Доступ к данным в сегменте, принадлежащем группе...............61
Комментарии в программах.......................................63
Комментарии в конце строки.....................................63
Директива COMMENT..............................................64
Продолжение строки.............................................64
Использование включаемых файлов................................65
Предопределенные идентификаторы................................66
Присваивание идентификаторам значений..........................67
Общая структура модуля.........................................68
Директива VERSION..............................................68
Директива NAME.................................................69
Директива END..................................................69
Вывод сообщения в процессе ассемблирования.....................70
Вывод предупреждающих сообщений................................70
Вывод нескольких сообщений об ошибках..........................72
Глава 4. Объектно-ориентированное программирование.............73
Терминология...................................................73
Для чего в Турбо Ассемблере используются объекты?..............74
Что такое объект?..............................................74
Пример объекта.................................................75
Описание объектов..............................................76
Описание процедуры методa......................................80
Таблица виртуальных методов....................................81
Инициализация таблицы виртуальных методов......................82
Вызов метода объекта...........................................82
Вызов статического метода......................................82
Вызов виртуального метода......................................83
Вызов виртуальных методов "предков"............................86
Кое-что еще о вызове методов...................................87
Создание экземпляра объекта....................................88
Программирование с объектами...................................88
Пример из области программирования.............................89
Глава 5. Использование выражений и значений идентификаторов....91
Константы......................................................91
Числовые константы.............................................91
Изменение используемого по умолчанию основания.................92
Строковые константы............................................93
Идентификаторы.................................................93
Имена идентификаторов..........................................93
Типы идентификаторов...........................................94
Адресные подтипы данных........................................94
Описание сложного адресного подтипа............................96
Выражения......................................................97
Точность в выражениях..........................................98
Константы в выражениях.........................................98
Идентификаторы в выражениях....................................98
Регистры.......................................................99
Стандартные значения идентификаторов..........................100
Значения простых идентификаторов..............................100
Унарная операция LENGTH.......................................102
Унарная операция WIDTH........................................105
Унарная операция MASK.........................................106
Общие арифметические операции.................................106
Простые арифметические операции...............................107
Логические арифметические операции............................108
Поразрядные операции сдвига...................................108
Операции сравнения............................................109
Задание адресного подтипа выражения...........................110
Получение типа выражения......................................111
Переопределение сегментной части адресного выражения..........112
Получение сегмента и смещения адресного выражения.............112
Создание адресного выражения, использующего счетчик
 инструкций...................................................113
Определение характеристик выражения...........................113
Ссылки на структуры,  объединения и смещения элементов в
 таблице......................................................114
Описание содержимого адреса...................................115
Подразумеваемое сложение......................................115
Получение значения старшего или младшего байта выражения......115
Задание 16- или 32-разрядных выражений........................116
Глава 6. Директивы выбора процессора и идентификаторы
 процессора...................................................118
Директивы процессоров iAPx86..................................118
Предопределенные идентификаторы...............................120
Идентификатор @Cpu............................................121
Идентификатор @WordSize.......................................123
Директивы сопроцессора 8087...................................123
Директивы эмуляции сопроцессора...............................124
Глава 7. Использование моделей памяти программы и
 сегментации..................................................126
Директива MODEL...............................................127
Идентификаторы, генерируемые директивой MODEL.................133
Идентификатор @Model..........................................133
Идентификатор @32Bit..........................................133
Идентификатор @CodeSize.......................................133
Идентификатор @DataSize.......................................133
Идентификатор @Interface......................................134
Упрощенные сегментные директивы...............................135
Идентификаторы, создаваемые упрощенными директивами
 сегментации..................................................138
Директива STARTUPCODE.........................................139
Идентификатор @Startup........................................139
Директива EXITCODE............................................139
Определение общих сегментов и групп...........................139
Директива SEGMENT.............................................140
Атрибут комбинирования сегментов..............................141
Атрибут класса сегмента.......................................142
Атрибут выравнивания сегмента.................................142
Атрибут размера сегмента......................................144
Атрибут доступа к сегменту....................................145
Директива ENDS................................................145
Директива GROUP...............................................146
Директива ASSUME..............................................146
Переопределение сегмента......................................147
Изменение упорядочивания сегментов в модуле...................149
Директива .ALPHA..............................................149
Директива .SEQ................................................149
Директива DOSSEG: упорядочивание сегментов в порядке DOS......149
Изменение размера стека.......................................150
Глава 8. Определение типов данных.............................151
Определение перечислимых типов данных.........................151
Определение записей с битовыми полями.........................152
Определение структур и объединений............................154
Открытие определения структуры или объединения................155
Задание элементов структуры и объединения.....................156
Определение меток элементов структур с помощью директивы
 LABEL........................................................157
Выравнивание элементов структуры..............................157
Закрытие определения структуры или объединения................158
Вложенные структуры и объединения.............................158
Включение одной именованной структуры в другую................160
Использование имен структур в выражениях......................162
Определение таблиц............................................162
Переопределение элементов таблицы.............................165
Определение именованного типа.................................165
Определение объекта...........................................165
Директива TBLPTR..............................................167
Идентификаторы, определяемые расширенной директивой STRUC.....168
Глава 9. Задание и использование счетчика адреса..............169
Идентификатор счетчика адреса $...............................169
Директивы счетчика адреса $...................................169
Директива ORG.................................................170
Директивы EVEN и EVENDATA.....................................172
Директива ALIGN...............................................173
Определение меток.............................................173
Операция :....................................................173
Директива LABEL...............................................175
Директива ::..................................................176
Глава 10. Описание процедур...................................177
Синтаксис определения процедур................................177
Описание процедур NEAR или FAR................................178
Описание языка процедуры......................................180
Задание модификатора языка....................................183
Определения аргументов и локальных переменных.................184
Синтаксис директив ARG и LOCAL................................186
Область действия аргументов и имен локальных переменных.......188
Сохранение регистров..........................................189
Вложенные процедуры и правила области действия................189
Описание процедур методов для объектов........................191
Глава 11. Управление областью действия идентификаторов........193
Переопределяемые идентификаторы...............................193
Область действия в границах блока.............................194
Директивы LOCALS и NOLOCALS...................................195
Область действия в границах блока в MASM......................195
Локальные метки в стиле MASM..................................196
Глава 12. Определение данных..................................197
Простые директивы определения данных..........................198
Создание экземпляра структуры или объединения.................202
Инициализация экземпляра структуры или объединения............203
Создание экземпляра записи....................................207
Инициализация экземпляров записи..............................207
Создание экземпляра данных перечислимого типа.................208
Инициализация экземпляра перечислимого типа данных............209
Создание экземпляра таблицы...................................209
Инициализация экземпляров таблицы.............................209
Создание и инициализация экземпляра именованного типа
Определение таблиц............................................162
Переопределение элементов таблицы.............................165
Определение именованного типа.................................165
Определение объекта...........................................165
Директива TBLPTR..............................................167
Идентификаторы, определяемые расширенной директивой STRUC.....168
Глава 9. Задание и использование счетчика адреса..............169
Идентификатор счетчика адреса $...............................169
Директивы счетчика адреса $...................................169
Директива ORG.................................................170
Директивы EVEN и EVENDATA.....................................172
Директива ALIGN...............................................173
Определение меток.............................................173
Операция :....................................................173
Директива LABEL...............................................175
Директива ::..................................................176
Глава 10. Описание процедур...................................177
Синтаксис определения процедур................................177
Описание процедур NEAR или FAR................................178
Описание языка процедуры......................................180
Задание модификатора языка....................................183
Определения аргументов и локальных переменных.................184
Синтаксис директив ARG и LOCAL................................186
Область действия аргументов и имен локальных переменных.......188
Сохранение регистров..........................................189
Вложенные процедуры и правила области действия................189
Описание процедур методов для объектов........................191
Глава 11. Управление областью действия идентификаторов........193
Переопределяемые идентификаторы...............................193
Область действия в границах блока.............................194
Директивы LOCALS и NOLOCALS...................................195
Область действия в границах блока в MASM......................195
Локальные метки в стиле MASM..................................196
Глава 12. Определение данных..................................197
Простые директивы определения данных..........................198
Создание экземпляра структуры или объединения.................202
Инициализация экземпляра структуры или объединения............203
Создание экземпляра записи....................................207
Инициализация экземпляров записи..............................207
Создание экземпляра данных перечислимого типа.................208
Инициализация экземпляра перечислимого типа данных............209
Создание экземпляра таблицы...................................209
Инициализация экземпляров таблицы.............................209
Создание и инициализация экземпляра именованного типа
 данных.......................................................210
Создание экземпляра объекта...................................211
Создание экземпляра таблицы виртуальных методов объекта.......211

Глава 13. Расширенные инструкции................................9
Эффективная генерация кода: директивы SMART и NOSMART...........9
Расширенные инструкции перехода................................10
Дополнительные инструкции цикла процессора 80386...............11
Дополнительные инструкции ENTER и LEAVE........................11
Дополнительные инструкции возврата.............................11
Расширенные инструкции PUSH и POP..............................12
Инструкции PUSH и POP с несколькими операндами.................13
Использование в инструкциях PUSH и POP указателей..............13
Занесение в стек константа (процессор 8086)....................13
Расширенные инструкции сдвига..................................15
Принудительное переопределение сегментов: инструкции SEGxx.....15
Дополнительные инструкции работы с флагами.....................16
Дополнительные инструкции работы с битами полей................17
Инструкция GETFIELD............................................19
Дополнительная быстрая инструкции непосредственного
 умножения.....................................................19
Расширение необходимых инструкций для процессора 80386.........20
Вызов процедур с кадрами стека.................................22
Вызываемые процедуры, содержащие RETURNS.......................23
Вызов процедур методов для объектов: CALL...METHOD.............23
Остаточная рекурсия для методов объектов: инструкция
 JMP...METHOD..................................................25
Дополнительные инструкции для объектного программирования......25
Глава 14. Использование макрокоманд............................26
Текстовые макрокоманды.........................................26
Определение текстовых макрокоманд с помощью директивы EQU......26
Директивы макрокоманд работы с текстовыми строками.............27
Директива CATSTR...............................................28
Директива SUBSTR...............................................28
Директива INSTR................................................28
Директива SIZESTR..............................................28
Примеры макрокоманд работы с текстом...........................29
Макрокоманды, состоящие из нескольких строк....................29
Тело макрокоманды, состоящей из нескольких строк...............29
Использование в макрокомандах символа &........................30
Включение комментариев в тело макрокоманды.....................31
Локальные формальные аргументы.................................31
Директива EXITM................................................33
Директива GOTO и макроидентификаторы перехода..................33
Общие макрокоманды, состоящие из нескольких строк..............34
Вызов общей макрокоманды, состоящей из нескольких строк........36
Литеральные строки в угловых скобках...........................37
Символ !.......................................................37
Символ вычисления выражения %..................................38
Переопределение общей макрокоманды, состоящей из нескольких
 строк.........................................................38
Удаление общей макрокоманды: директива PURGE...................38
Определение вложенных и рекурсивных макрокоманд................39
Счетчик повторения макрокоманды................................40
Директива WHILE................................................41
Макрокоманды повторения строк..................................41
Непосредственная макродиректива %..............................42
Включение расширения макрокоманды в файл листинга..............43
Глава 15. Использование условных директив......................44
Синтаксис условных директив....................................44
Директива условного ассемблирования IFxxx......................45
Директивы условного ассемблирования ELSEIFxxx..................47
Директивы генерации сообщений об ошибке ERRxx..................48
Описания конкретных директив...................................49
Безусловные директивы генерации сообщений об ошибке............49
Условные директивы с выражениями...............................49
Условные директивы с идентификатором...........................50
Условные директивы с текстовыми строками.......................52
Условия выполнения прохода Ассемблером.........................56
Включение условных директив в файл листинга....................56
Глава 16. Интерфейс с компоновщиком............................58
Описание внешних идентификаторов...............................58
Соглашения для конкретного языка...............................58
Описание общедоступных идентификаторов.........................58
Описание идентификаторов библиотеки............................59
Определение внешних идентификаторов............................60
Описание глобальных идентификаторов............................60
Определение общих переменных...................................60
Включение библиотеки...........................................62
Глава 17. Генерация листинга...................................63
Формат листинга................................................63
Общие директивы управления листингом...........................64
Директивы листинга включаемых файлов...........................65
Директивы вывода блоков условного ассемблирования..............66
Директивы вывода в файл листинга макрокоманд...................67
Директивы вывода листинга перекрестных ссылок..................67
Параметры изменения формата листинга...........................69
Глава 18. Интерфейс Турбо Ассемблера и Borland C++.............73
Вызов из Borland C++ функций Турбо Ассемблера..................74
Основные моменты в интерфейсе Турбо Ассемблера и Borland
 C++...........................................................76
Компоновка ассемблерных модулей с С++..........................77
Использование Extern "C" для упрощения компоновки..............78
Модели памяти и сегменты.......................................79
Упрощенные директивы определения сегментов и Borland C++.......79
Старые директивы определения сегментов и Borland C++...........80
Значения по умолчанию: когда необходимо загружать сегменты?....83
Общедоступные и внешние идентификаторы.........................86
Подчеркивания и язык Си........................................86
Различимость  строчных и прописные символов в
 идентификаторах...............................................88
Типы меток.....................................................88
Внешние дальние идентификаторы.................................90
Командная строка компоновщика..................................91
Взаимодействие между Турбо Ассемблером и Borland C++...........93
Передача параметров............................................93
Сохранение регистров..........................................101
Возврат значений..............................................102
Вызов функции Турбо Ассемблера из Borland C++.................104
Написание на языке Ассемблера функций-элементов С++...........108
Соглашения по вызовам, использующиеся в Паскале...............110
Вызов Borland C++ из Турбо Ассемблера.........................111
Компоновка с кодом инициализации С++..........................112
Задание сегмента..............................................112
Выполнение вызова.............................................112
Вызов из Турбо Ассемблера функции Borland C++.................114
Глава 19. Интерфейс Турбо Ассемблера с Турбо Паскалем.........117
Совместное с Турбо Паскалем использование данных..............118
Директива компилятора $L и внешние подпрограммы...............118
Директива PUBLIC..............................................119
Директива EXTRN...............................................119
Ограничения при использовании объектов типа EXTRN.............122
Использование корректировок сегментов.........................123
Устранение неиспользуемого кода...............................125
Соглашения Турбо Паскаля по передаче параметров...............125
Параметры-значения............................................125
Скалярные типы................................................125
Вещественные значения.........................................126
Типы Single, Double, Extended и Comp и типы сопроцессора
 8087.........................................................126
Указатели.....................................................126
Строки........................................................126
Записи и массивы..............................................126
Множества.....................................................127
Параметры-переменные..........................................127
Обеспечение стека.............................................127
Доступ к параметрам...........................................128
Использование для адресации к стеку регистра BP...............128
Директива ARG.................................................129
Турбо Паскаль и директива .MODEL..............................130
Использование другого базового или индексного регистра........131
Результаты функции в Турбо Паскале............................131
Выделение пространства для локальных данных...................132
Выделение статической памяти..................................132
Выделение временной памяти....................................133
Примеры подпрограмм на Ассемблере для Турбо Паскаля...........135
Подпрограмма шестнадцатиричного преобразования общего
 назначения...................................................135
Пример обмена содержимого двух переменных.....................138
Пример анализа операционной среды DOS.........................141
Часть 2. ПРИЛОЖЕНИЯ...........................................147
Приложение A. Замечания по программированию...................148
Упрощенные директивы определения сегмента.....................148
Программы DOS.................................................150
Замечания по программам формата EXE...........................151
Замечания по программам формата COM...........................152
Программы Windows.............................................153
Замечания по динамически компонуемым библиотекам Windows......153
Замечания по прикладным программам Windows....................154
Приложение B. Обзор синтаксических правил Турбо Ассемблера....156
Лексическая грамматика........................................156
Грамматика выражений в режиме MASM............................158
Грамматика выражений в режиме Ideal...........................160
Старшинство ключевых слов.....................................162
Старшинство операций в режиме Ideal...........................162
Старшинство операций в режиме MASM............................162
Ключевые слова и предопределенные идентификаторы..............163
Ключевые слова директив.......................................163
Приложение C. Вопросы совместимости...........................168
Одно- и двухпроходные режимы ассемблирования..................169
Переменные операционной среды.................................170
Формат фирмы Microsoft для двоичных чисел с плавающей
 точкой.......................................................170
Приложение D. Утилиты Турбо Ассемблера........................171
Утилита-преобразователь H2ASH.................................171
Приложение E. Сообщения об ошибках............................174
Информационные сообщения......................................174
Предупреждающие сообщения и сообщения об ошибках..............176
32-bit segment not allowed without .386.......................176
Argument needs type override..................................176
Argument to operation or instruction has illegal size.........177
Arithmetic overflow...........................................177
ASSUME must be segment register...............................177
Bad keyword in SEGMENT statement..............................177
Can't add relative quantities.................................177
Can't address with currently ASSUMEd segment registers........178
Can't convert to pointer......................................178
Can't emulate 8087 instruction................................178
Can't make variable public....................................179
Can't override ES segment.....................................179
Can't subtract dissimilar relative quantities.................179
Can't use macro name in expression............................179
Can't use this outside macro..................................179
Code or data emission to undeclared segment...................180
Constant assumed to mean Immediate const......................180
Constant too large............................................180
CS not correctly assumed......................................180
CS override in protected mode.................................181
CS unreachable from current segment...........................181
Declaration needs name........................................181
Directive ignored in Turbo Pascal model.......................181
Directive not allowed inside structure definition.............182
Duplicate dummy arguments:_...................................182
ELSE or ENDIF without IF......................................182
Expecting METHOD keyword......................................183
Expecting offset quantity.....................................183
Expecting offset or pointer quantity..........................183
Expecting pointer type........................................183
Expecting record field name...................................183
Expecting register ID.........................................183
Expecting scalar type.........................................183
Expecting segment or group quantity...........................184
Extra characters on line......................................184
Forward reference needs override..............................184
Global type doesn't match symbol type.........................184
ID not member of structure....................................185
Illegal forward reference.....................................185
Illegal immediate.............................................185
Illegal indexing mode.........................................186
Illegal instruction...........................................186
Illegal instruction for currently selected processor(s).......186
Illegal local argument........................................186
Illegal local symbol prefix...................................186
Illegal mаcro argument........................................187
Illegal memory reference......................................187
Illegal number................................................187
Illegal origin address........................................187
Illegal override in structure.................................187
Illegal override register.....................................188
Illegal radix.................................................188
Illegal register for instruction..............................188
Illegal register multiplier...................................188
Illegal segment address.......................................188
Illegal use of constant.......................................189
Illegal use of register.......................................189
Illegal use of segment register...............................189
Illegal USES register.........................................189
Illegal version ID............................................189
Illegal warning ID............................................189
Instruction can be compacted with override....................190
Invalid model type............................................190
Invalid operand(s) to instruction.............................190
Labels can't start with numeric characters....................190
Line too long - truncated.....................................190
Missing argument list.........................................191
Missing argument or <.........................................191
Missing argument size variable................................191
Missing COMM ID...............................................191
Missing dummy argument........................................192
Missing end quote.............................................192
Missing macro ID..............................................192
Missing module name...........................................192
Missing or illegal language ID................................192
Missing or illegal type specifier.............................193
Missing table member ID.......................................193
Missing term in list..........................................193
Missing text macro............................................193
Model must be specified first.................................193
Module is pass-dependant - compatibility pass was done........193
Name must come first..........................................194
Near jump or call to different CS.............................194
Need address or register......................................194
Need angle brackets for structure fill........................194
Need colon....................................................194
Need expression...............................................195
Need file name after INCLUDE..................................195
Need left parenthesis.........................................195
Need method name..............................................195
Need pointer expression.......................................195
Need quoted string............................................195
Need register in expression...................................196
Need right angle bracket......................................196
Need right curly bracket......................................196
Need right parenthesis........................................196
Need right square bracket.....................................196
Need stack argument...........................................197
Need structure member name....................................197
Not expecting group or segment quantity.......................197
One non-null field allowed per union expansion................197
Only one startup sequence allowed.............................198
Open conditional..............................................198
Open procedure................................................198
Open segment..................................................198
Open structure definition.....................................198
Operand types do not match....................................199
Operation illegal for static table member.....................199
Pass-dependant construction encountered.......................199
Pointer expression needs brackets.............................199
Positive count expecting......................................200



Яндекс цитирования