Турбо Ассемблер 3

Использование макрокоманд

─────────────────────────────────────────────────────────────────

Макрокоманды позволяют вам задавать имя идентификатора для

текстовой строки или блока кода, которые будут часто использо-

ваться в программе. Однако макрокоманды выходят за рамки простой

подстановки. В Турбо Ассемблере имеются макрооперации, обеспечи-

вающие большую гибкость в определении макрокоманд. В сочетании с

возможностью использования макрокоманд из нескольких строк с ар-

гументами это превращает макросредства Турбо Ассемблера в очень

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

зовать в программах текстовые макрокоманды и макрокоманды, состо-

ящие из нескольких строк.

Текстовые макрокоманды

─────────────────────────────────────────────────────────────────

Текстовая макрокоманда - это идентификатор, представляющий

строку текстовых символов. Когда Турбо Ассемблер обнаруживает

идентификатор в выражениях (и в других ситуациях), он подставляет

вместо него текстовые символы. Например, если DoneMsg - это текс-

товая макрокоманда, имеющая значение "Returning to DOS", то сле-

дующий оператор:

GoodBy DB DoneMsg

дает в результате:

GoodBy DB 'Returning to DOS'

Определение текстовых макрокоманд с помощью директивы EQU

─────────────────────────────────────────────────────────────────

Для определения простых текстовых макрокоманд можно исполь-

зовать директиву EQU.Приведем синтаксис определения текстовой ма-

крокоманды:

имя EQU текстовая_строка

где "текстовая_строка" связывается с текстовой макрокомандой с

именем "имя". Для выделения текста вы можете заключить текстовую

строку в угловые скобки (<>), например:

DoneMsg DB <'Returning to DOS'>

Если в режиме MASM вы опустите скобки, то Турбо Ассемблер

будет определять, можно ли свести текстовую строку к выражению.

Если ее вычислить нельзя, Турбо Ассемблер будет интерпретировать

текстовую строку как текстовую макрокоманду (чтобы сохранить

совместимость c MASM). Чтобы обеспечить правильное определение

текстовой строки, нужно всегда заключать ее в угловые скобки.

Рассмотрим следующие ошибки, которые могут возникать, если вы

этого не делаете:

Earth EQU dirt ; Earth = "dirt"

Planet EQU Earth ; Planet = "dirt" (неверно!)

Planet EQU <Earth> ; Planet = "Earth" (верно!)

В режиме Ideal оператор EQU всегда определяет текстовую мак-

рокоманду.

Текстовые макрокоманды являются переопределяемыми. Вы може-

те переопределить текстовую макрокоманду в том же модуле другой

текстовой строкой.

Директивы макрокоманд работы с текстовыми строками

─────────────────────────────────────────────────────────────────

Турбо Ассемблер обеспечивает директивы, которые могут рабо-

тать с текстовыми макрокоманд. Эти директивы доступны в режиме

Ideal и для версий M510, M520 и T300 (как задается директивой

VERSION).

Строковые аргументы для любой из этих директив могут быть

следующими:

- текстовой строкой, заключенной в скобки, например, <abc>;

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

- выражением с предшествующим символом %, значение которого

эквивалентно числовому представлению строки для текущего

основания.

Директива CATSTR

─────────────────────────────────────────────────────────────────

Директива CATSTR определяет новую текстовую макрокоманду пу-

тем конкатенации строк. Она имеет следующий синтаксис:

имя CATSTR строка[,строка]...

Директива CATSTR выполняет конкатенацию слева-направо. Турбо

Ассемблер создает новую текстовую макрокоманду с именем "имя".

Директива SUBSTR

─────────────────────────────────────────────────────────────────

Директива SUBSTR определяет новую текстовую макрокоманду,

которая является подстрокой строки. Она имеет следующий синтак-

сис:

имя SUBSTR строка,выражение_позиции[,выражение_размера]

Новая текстовая макрокоманда с именем "имя" состоит из части

строки , начинающейся с символа в позиции "выражение_позиции" и

длины "выражение_длины". Если вы не указываете "выражение_разме-

ра", новая текстовая макрокоманда содержит остаток строки, начи-

ная с символа в "выражении_позиции". Турбо Ассемблер рассматрива-

ет первый символ строки как позицию 1.

Директива INSTR

─────────────────────────────────────────────────────────────────

Директива INSTR возвращает позицию одной строки внутри дру-

гой. Она имеет следующий синтаксис:

имя INSTR [выражение_начала,]строка_1,строка_2

Турбо Ассемблер присваивает "имя" числовому значению, кото-

рое соответствует первой позиции первого вхождения "строки_2" в

"строку_1". Первый символ "строки_1" имеет позицию 1. Если "стро-

ка_2" в "строке_1" не содержится, то Турбо Ассемблер возвращает

значение 0. Если вы укажете "выражение_начала", то поиск начина-

ется с символа, задаваемого этим выражением. Первый символ строки

находится в позиции 1.

Директива SIZESTR

─────────────────────────────────────────────────────────────────

Директива SIZESTR возвращает длину текстовой макрокоманды

(число символов в строке). Она имеет синтаксис:

имя SIZESTR строка

где "имя" устанавливается в числовое значение, равное длине ука-

занной строки. Нулевая строка <> имеет длину 0.

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

─────────────────────────────────────────────────────────────────

Следующие примеры показывают, как работают эти операции:

VERSION T300

ABC EQU <abc> ; ABC = "abc"

ABC2 EQU ABC ; ABC2 = "ABC"

ABC EQU <det> ; ABC = "det"

; (переопределяется)

ABC3 CATSTR ABC2,<,>,ABC,<,>,ABC2 ;ABC3 = "ABC,DEF,

; ABC"

ABCLEN SIZESTR ABC ; ABCLEN = 3

ABC3LEN SIZESTR ABC3 ; ABC3LEN = 11

COMMA1 INSTR ABC3,<,> ; COMMA1 = 4

COMMA2 INSTR COMMA1+1,ABC3,<,> ; COMMA2 = 8

ABC4 SUBSTR ABC3,5 ; ABC4 = "def,ABC"

ABC5 SUBSTR ABC3,5,3 ; ABC5 = "def"

ABC6 EQU 3+2+1 ; ABC6 = 6

; (числовое

; присваивание)

ABC7 EQU %3+2+1 ; ABC7 = "6"

; (текстовая

; макрокоманда)

ABC8 EQU %COMMA1 ; ABC8 = "4"

Макрокоманды, состоящие из нескольких строк

─────────────────────────────────────────────────────────────────

Макрокоманды, состояние из нескольких строк, позволяют вам

определить в их теле инструкции, директивы или другие макрокоман-

ды, которые будут включаться в исходный код при вызове макроко-

манды. Вы можете указать аргументы макрокоманды, которые Турбо

Ассемблер будет подставлять в тело макрокоманды при ее включении

в модуле.

Существует насколько типов макрокоманд, состоящих из нес-

кольких строк. Одна версия подставляет каждый элемент строки

(один за другим), который является аргументом макрокоманды. Дру-

гая версия повторяет определенное число раз тело макрокоманды.

Наконец, в одном месте вы можете определить еще одну версию, ко-

торая будет много раз вызываться. Все эти версии имеют общее оп-

ределение тела макрокоманды.

Тело макрокоманды, состоящей из нескольких строк

─────────────────────────────────────────────────────────────────

Независимо от содержимого тела макрокоманды, средство обра-

ботки макрокоманд Турбо Ассемблера интерпретирует макрокоманду,

состоящую из нескольких строк, как просто несколько строк текста.

Турбо Ассемблер позволяет вам заменить идентификаторы в теле мак-

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

команды, которые должны быть заменены, называются формальными

(фиктивными) аргументами. Предположим, например, что идентифика-

тор foo - это формальный аргумент в следующем теле макрокоманды:

PUSH foo

MOV foo,1

Если при вызове данной макрокоманды вы присваиваете foo

текстовую строку AX, то фактическим включаемым в модуль текст бу-

дет:

PUSH foo

MOV AX,1

Правила, которые Турбо Ассемблер использует для распознава-

ния формальных аргументов, достаточно сложны. Рассмотрим, напри-

мер, следующие строки тела макрокоманды, где формальный аргумент

foo не распознается:

symfoo:

DB 'It is foo time'

В общем случае Турбо Ассемблер не будет распознавать фор-

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

ях:

- когда он является частью другого идентификатора;

- когда он находится внутри кавычек (' или ");

- в режиме Ideal, когда он указывается после двоеточия не

внутри кавычек.

Использование в макрокомандах символа &

─────────────────────────────────────────────────────────────────

Символ & в теле макрокоманды имеет специальное значение. В

общем случае & отделяет имя формального аргумента от окружающего

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

подстановке. Если, например, имеется следующее тело макрокоманды:

sym&foo:

DB 'It is &foo time'

и если вы при вызове данной макрокоманды присвоите foo текстовую

строку party, то фактическим включаемым в модуль текст будет сле-

дующее:

symparty:

DB 'It is party time'

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

foo&sym:

DB 'We are in O&foo&o'

Если вы при вызове данной макрокоманды присвоите foo тексто-

вую строку hi, то фактическим включаемым в модуль текст будет

следующее:

hisym:

DB 'We are in Ohio'

Приведем правила для символа &:

- вне заключенных в кавычки строк символ & используется как

разделитель;

- внутри заключенной в кавычки строки и после двоеточия, ко-

торое не находится в заключенной в кавычки строке в режиме

Ideal, символ & должен предшествовать формальному аргумен-

ту (чтобы этот аргумент мог распознаваться);

- при расширении макрокоманды Турбо Ассемблер удаляет один

символ & из группы таких символов.

Последний пункт дает возможность помещать внутри макрокоманд

макроопределения, требующие символа &. Турбо Ассемблер будет уда-

лять только один символ & из группы.

Включение комментариев в тело макрокоманды

─────────────────────────────────────────────────────────────────

В особенно сложных макрокомандах иногда желательно поместить

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

ее расширении. Это также уменьшает объем необходимой Турбо Ас-

семблеру для обработки макрокоманд памяти. Для этого используйте

комментарий с предшествующей двойной точкой запятой (в начале

строки). Например, следующее тело макрокоманды:

;; Это макрокоманда с комментарием

DB 'макрокоманда с комментарием'

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

DB 'макрокоманда с комментарием'

Примечание: Комментарии с одиночной точкой с запятой

при вызове макрокоманды всегда включаются в макрорасшире-

ние.

Локальные формальные аргументы

─────────────────────────────────────────────────────────────────

В начале тела макрокоманды вы всегда можете включить одну

или более директив LOCAL. Директива LOCAL описывает специальные

формальные аргументы, которым при каждом расширении макрокоманды

будет присваиваться уникальное символьное имя.

Синтаксис директивы LOCAL в теле макрокоманды выглядит сле-

дующим образом:

LOCAL формальный_аргумент_1 [,формальный_аргумент_2]...

Если имя "формальный_аргумент", указанное в директиве LOCAL,

не содержит префикс локального идентификатора, то присваиваемое

ему уникальное имя идентификатора будет иметь вид ??xxxx, где

xxxx представляет шестнадцатиричное число. В противном случае

уникальное символьное имя будет иметь вид <локальный_пре-

фикс>xxxx.

Примечание: Подробности о разрешении локальных иденти-

фикаторов и задании локального префикса можно узнать в Гла-

ве 11.

Вы можете использовать формальные аргументы LOCAL для зада-

ния в теле макрокоманды меток, например:

LOCAL @agn, @zero

XOR dx,dx

MOV cx,exp

MOV ax,1

JCXZ @zero

MOV bx,factor

@agn: MUL bx

LOOP @agn

@zero:

Директива EXITM

─────────────────────────────────────────────────────────────────

Директиву EXITM можно использовать в теле макрокоманды для

принудительного завершения ассемблирования включаемого тела мак-

рокоманды. Она имеет следующий синтаксис:

EXITM

Когда Турбо Ассемблер обнаруживает директиву EXITM в теле

макрокоманды, которая включена в исходный код модуля, ассемблиро-

вание расширенного тела макрокоманды немедленно прекращается.

Вместо этого Турбо Ассемблер будет продолжать ассемблирование мо-

дуля после конца макрокоманды.

Для завершения макрокоманды при определенных условиях вы мо-

жете использовать оператор EXITM с директивой условного ассембли-

рования.

Примечание: Директивы условного ассемблирования под-

робнее рассматриваются в Главе 15.

Директива GOTO и макроидентификаторы перехода

─────────────────────────────────────────────────────────────────

Использование директивы GOTO и макроидентификаторов перехода

позволяют вам управлять последовательностью расширения строк мак-

рокоманды. Вы можете поместить цель перехода в любом месте тела

макрокоманды. Она занимает всю строку макрокоманды и имеет следу-

ющий синтаксис:

:идентификатор_перехода

При расширении макрокоманды все макроидентификаторы перехода

отбрасываются.

Директива GOTO сообщает Турбо Ассемблеру, что нужно перейти

на заданную точку исходного кода, а именно - на "идентифика-

тор_перехода". Это позволяет вам поместить GOTO в блоке условного

ассемблирования. Например:

IF foo

GOTO tag1

ENDIF

DISPLAY "foo имеет значение false!"

:tag

; возобновление макрокоманды...

; работает одинаково, независимо от того,

; равно foo false или true

Примечание: Будьте аккуратны и не создавайте при ис-

пользовании директивы GOTO бесконечных циклов. Бесконечные

циклы могут привести к тому, что Турбо Ассемблер исчерпает

доступную память или даже прекратит работу.

Подробнее о директивах условного ассемблирования рассказыва-

ется ниже

Общие макрокоманды, состоящие из нескольких строк

─────────────────────────────────────────────────────────────────

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

нескольких строк (включая директивы, инструкции и другие макроко-

манды) с символьным именем макрокоманды. При использовании имени

макрокоманды в качестве директивы Турбо Ассемблер включает в

программу тело макрокоманды (операторы). Таким образом вы можете

использовать макрокоманду, состоящую из нескольких строк, нес-

колько раз.

Приведем синтаксис общей макрокоманды из нескольких строк

режима Ideal:

MACRO имя список_параметров

тело_макрокоманды

ENDM

В режиме MASM общее определение макрокоманды из нескольких

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

имя MACRO список_параметров

тело_макрокоманды

ENDM

где "имя" - это имя определяемой вами макрокоманды из нескольких

строк. "Тело_макрокоманды" содержит операторы, которые составляет

тело макрорасширения. В макрокоманду вы можете помещать любые до-

пустимые операторы Турбо Ассемблера (и любое их число). Макроко-

манду завершает ключевое слово ENDM.

В следующем примере определяется макрокоманда с именем

PUSHALL, которая при вызове включает в вашу программу тело макро-

команды, состоящее из трех инструкций PUSH:

PUSHALL MACRO

PUSH AX BX CX DX

PUSH DS SI

PUSH ES DI

ENDM

"Список_параметров" - это список формальных аргументов (их

идентификаторов) макрокоманды. Он имеет следующий синтаксис:

[формальный_аргумент [,формальный_аргумент]...]

В макрокоманде вы можете использовать любое число формальных

аргументов (если они не умещаются на одной строке, для продолже-

ния на другой строке можно использовать символ /). Например:

ADDUP MACRO dest,\ ; dest - это первый формальный

; аргумент, а s1,s2 -

; это второй и третий

; аргумент макрокоманды

MOV dest,s1

ADD dest,s2

ENDM

Каждый формальный аргумент имеет следующий синтаксис:

имя_формального_аргумента[:тип_аргумента]

где "имя_аргумента" - это символьное имя, используемое для подс-

тановки (вместо него) фактического параметра, передаваемого мак-

рокоманд при ее вызове. Необязательный "тип_аргумента" задает ка-

кую-то информацию о виде фактического параметра, воспринимаемого

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

Типы формальных аргументов Таблица 14.1

┌──────────────────────┬────────────────────────────────────────┐

│ Тип │ Значение │

├──────────────────────┼────────────────────────────────────────┤

│ REQ │ Аргументы не могут быть нулевыми или │

│ │ состоять из пробелов. │

│ │ │

│ =<текстовая_строка> │ Заключенная в кавычки текстовая строка │

│ │ задает используемое по умолчанию зна- │

│ │ чение аргумента (когда фактический ар- │

│ │ гумент является нулевым или состоит из │

│ │ пробелов). │

│ │ │

│ VARARG │ Фактический аргумент состоит из ос- │

│ │ тальной части макровызова, интерпрети- │

│ │ руемого как список аргументов. Для │

│ │ обеспечения этой интерпретации исполь- │

│ │ зуются угловые скобки, запятые. │

│ │ │

│ REST │ Фактический аргумент состоит из ос- │

│ │ тальной части макровызова, интерпрети- │

│ │ руемого как непосредственный текст. │

└──────────────────────┴────────────────────────────────────────┘

Вызов общей макрокоманды, состоящей из нескольких строк

─────────────────────────────────────────────────────────────────

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

раммы в качестве директивы имя макрокоманды. Турбо Ассемблер

вставляет в этой точке модуля (поле подстановок всех формальных

аргументов) тело макрокоманды. При вызове общей макрокоманды,

состоящей из нескольких строк, используется следующий синтаксис:

имя_макрокоманды [аргумент [[,]аргументе]...]

где "имя_макрокоманды" - это идентификатор макрокоманды. Если вы

вызываете макрокоманду с аргументами, то список аргументов указы-

вается после имени макрокоманды. Вы можете задать любое число

аргументов, но все они должны умещаться на одной строке. Аргумен-

ты нужно отделять друг от друга запятыми или пробелами. При рас-

ширении макрокоманды Турбо Ассемблер заменяет первый формальный

аргумент макроопределения первым передаваемым аргументом, второй

аргумент - вторым аргументом и т.д.

Каждый "аргумент" представляет текстовую строку. Вы можете

задать эту текстовую строку следующими способами:

- как непрерывную группу символов, не содержащую пробелов,

запятых или двоеточий;

- как группу символов, выделенную угловыми скобками (<>),

которая может содержать пробелы, запятые и двоеточия;

- как одиночный символ с предшествующим знаком !, что экви-

валентно заключению символа в угловые скобки;

- как выражение с предшествующим символом %, которое предс-

тавляет текстовое значение выражения, соответствующее те-

кущему выбранному основанию.

Литеральные строки в угловых скобках

─────────────────────────────────────────────────────────────────

Используйте угловые скобки для выделения литеральной строки,

содержащей символы-разделители. Следует использовать следующий

синтаксис:

<текст>

где "текст" интерпретируется как одиночный строковый параметр,

даже если он содержит запятые, пробелы или символы табуляции, ко-

торые обычно разделяют параметры. Используйте данную операцию,

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

волов.

Вы можете также использовать эту операцию, чтобы Турбо Ас-

семблер интерпретировал символ литерально, не придавая ему специ-

альное значение. Например, если вы хотите передать в качестве па-

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

ее интерпретацию как комментария, вы можете заключить ее в угло-

вые скобки (<;>). При преобразовании заключенной в скобки строки

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

угловых скобок. Это позволяет вызывать макрокоманду, требующую

наличия угловых скобок, из другой макрокоманды.

Символ !

─────────────────────────────────────────────────────────────────

Символ ! позволяет вам вызывать макрокоманду с аргументами,

которые содержат специальные символы. Указание этого символа пе-

ред другим символом эквивалентно заключению этого второго символа

в угловые скобки. Например, !; действует также, как <;>. Некото-

рые общие случаи использования данного символа показаны в следую-

щей таблице:

Использование специального символа ! Таблица 14.2

┌─────────────────┬─────────────────────────────────────────────┐

│ Строка │ Полученные в результате символ │

├─────────────────┼─────────────────────────────────────────────┤

│ !> │ > │

│ │ │

│ !< │ < │

│ │ │

│ !! │ ! │

└─────────────────┴─────────────────────────────────────────────┘

Символ вычисления выражения %

─────────────────────────────────────────────────────────────────

Символ % указывает Турбо Ассемблеру, что выражение нужно вы-

числить. Ассемблер преобразует результат выражения к виду ASCII с

текущим основанием. Используйте данный символ, когда в качестве

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

ный результат, а не само выражение. При этом используется следую-

щий синтаксис:

%выражение

где "выражение" может быть либо выражением (использующим любые

допустимые операнды и операции), или именем текстовой макрокоман-

ды. Если это выражение, то создаваемым текстом будет результат

выражения с текущим основанием. Если "выражение" - это текстовая

макрокоманда, то создаваемым тестом будет текст, который предс-

тавляет текстовая макрокоманда. Например, следующий фрагмент

программы:

DEFSYM MACRO NUM

TMP_&NUM:

ENDNUM

TNAME EQU <JUNK> ; определение

; текстовой макрокоманды

DEFSYM %5+4

DEFSYM %TNAME

приведет с следующему макрорасширению:

TMP_9:

TMP_JUNK:

Переопределение общей макрокоманды, состоящей из нескольких строк

─────────────────────────────────────────────────────────────────

Общие макрокоманды, состоящие из нескольких строк, вы можете

переопределять. Новое определение автоматически заменяет старое

определение. Все предшествующие места, где макрокоманда уже была

вызвана, не изменяются. Во всех вызовах макрокоманды, следующих

за переопределением, используется новое определение.

Удаление общей макрокоманды: директива PURGE

─────────────────────────────────────────────────────────────────

Для удаления макрокоманд вы можете использовать директиву

PURGE. Директива PURGE имеет следующий синтаксис:

PURGE имя_макрокоманды, [имя_макрокоманды]...

Директива PURGE удаляет определение макрокоманды, состоящей

из нескольких строк, с именем "имя_макрокоманды" После использо-

вания директивы PURGE Турбо Ассемблер больше не интерпретирует

идентификатор PURGE как макрокоманду, например:

ADD MACRO a1,a2

SUB a1,a2

ENDM

ADD ax,bx ; этот вызов даст SUB ax,bx

PURGE ADD

ADD ax,bx ; теперь это не макрокоманда, поэтому

; вы получите ADD ax,bx

Вы можете сразу удалить этой директивой несколько макроко-

манд, разделив их имена запятыми. Отметим однако, что идентифика-

тор удаленной макрокоманды можно переопределить только другой

макрокомандой.

Определение вложенных и рекурсивных макрокоманд

─────────────────────────────────────────────────────────────────

Операторы в теле макрокоманды могут включать в себя операто-

ры, вызывающие или определяющие другие макрокоманды. Возьмем сле-

дующий пример:

MCREATE MACRO opname, op1,op2,op3,op4,op5,op6,op7

IFNB opname

DO & opname MACRO op,count

IF count LE 4

REPT count

opname op,1

ENDM

ELSE

MOVE CL,count

opname op,CL

ENDIF

EMDM ; конец DOopname

MCREATE op1,op2,op3,op4,op5,op6,op7 ; рекурсия!

ENDIF ; конец if

ENDM ; конец макрокоманды MCREATE

После вызова:

MCREATE ror,rol,rcl,rcr,shl,sal,sar

будут созданы дополнительные макрокоманды DOror, DOrol и т.д.,

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

DOshr ax,5

DOrcr bx,3

Рекурсивные макрокоманды можно вызывать со списком парамет-

ров и задавать их таким образом, что они будут работать с пере-

менным числом параметров (от 0 до максимального числа парамет-

ров). Для этого макрокоманда должна использовать первый параметр

для выполнения ее макрорасширения, а затем вызывать сама себя с

оставшимися параметрами. При каждой рекурсии остается на один

параметр меньше. В конце концов, будет последняя рекурсия без па-

раметров.

Когда вы вызываете макрокоманду рекурсивно, всегда требуется

как-то проверить конец рекурсии. Обычно при наличии передаваемого

параметра это делается в теле макрокоманды с помощью условного

оператора IFNB. Приведем простой пример рекурсивной макрокоманды:

PUSH MACRO r1,r2,r3,r4,r5,r6,r7,r8

IFNB r1

PUSH r1

PUSH r2,r3,r4,r5,r6,r7,r8

ENDIF

ENDM

Счетчик повторения макрокоманды

─────────────────────────────────────────────────────────────────

Для повторения тела макрокоманды заданное число раз вы може-

те использовать директиву повторения REPT. Для этого используется

следующий синтаксис:

REPT выражение

тело_макрокоманды

ENDM

где "выражение" указывает Турбо Ассемблеру, сколько раз нужно

повторить тело макрокоманды, заданное между директивами REPT и

ENDM. При вычислении "выражения" должна получаться константа. Оно

не должно содержать имен идентификаторов с опережающими ссылками.

Чтобы отметить конец блока повторения, используйте директиву

ENDM. Например, следующий код:

REPT 4

SHL ax,1

ENDM

даст в результате следующее:

SHL ax,1

SHL ax,1

SHL ax,1

SHL ax,1

Директива WHILE

─────────────────────────────────────────────────────────────────

Для повторения тела макрокоманды до того момента, пока опре-

деленное выражение не примет значения 0 (false), вы можете ис-

пользовать макродирективу WHILE. Она имеет следующий синтаксис:

WHILE выражение

тело_макрокоманды

ENDM

Перед каждой итерацией тела макрокоманды Турбо Ассемблер вы-

числяет "выражение". Будьте аккуратны и избегайте бесконечных

циклов, которые привести к тому, что Турбо Ассемблер исчерпает

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

вания директивы WHILE:

WHILE 1

;; ничего не делает

ENDM

Макрокоманды повторения строк

─────────────────────────────────────────────────────────────────

Для повторения тела макрокоманды для каждого элемента в

списке или каждого символа в строке вы можете использовать макро-

директивы повторения IRP и IRPC. Каждая из этих директив требует

от вас задания одного формального аргумента. Приведем синтаксис

директивы IRP:

IRP формальный_аргумент, список_аргументов

тело_макрокоманды

ENDM

Директива IRPC имеет следующий синтаксис:

IRP формальный_аргумент, строка

тело_макрокоманды

ENDM

в обоих случаях "формальный_аргумент" - это аргумент, используе-

мый в теле макрокоманды. Конец тела макрокоманды отмечает ENDM.

В синтаксисе директивы IRP "список_аргументов" состоит из

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

любой текст (идентификаторы, строки, числа и т.д.). Форма каждого

аргумента в списке аналогична той, которая описана выше для вызо-

ва общей макрокоманды, состоящей из нескольких строк. Список ар-

гументов всегда нужно заключать в угловые скобки (<>).

В синтаксисе директива IRPC аргумент состоит из одной стро-

ки. Строка может содержать столько символов, сколько вы хотите.

Для каждого аргумента или символа в строке Турбо Ассемблер

будет включать в модуль тело макрокоманды, подставляя вместо фор-

мального аргумента аргумент или символ (когда он его находит).

Например:

IRP reg <ax,bx,cx,dx>

PUSH reg

ENDM

дает следующее:

PUSH ax

PUSH bx

PUSH cx

PUSH dx

а директива IRPC:

IRPC LUCKY,1379

DB LUCKY

ENDM

дает следующее:

DB 1

DB 2

DB 3

DB 4

Используйте директива IRPC аккуратно, поскольку Турбо Ас-

семблер помещает каждый символ в строке в макрорасширение "как

есть", поэтому макрокоманда строкового повторения:

IRPC CHAR,HELLO

DB CHAR

ENDM

может дать не DB 'H','E'','L','L','O', а DB H,E,L,L,O (где каждая

буква интерпретируется как имя идентификатора.

Непосредственная макродиректива %

─────────────────────────────────────────────────────────────────

Непосредственная макродиректива % интерпретирует строку

текста так, как если бы это было тело макрокоманды. Приведем ее

синтаксис:

# строка_тела_макрокоманды

где "строка_тела_макрокоманды" представляет тело макрокоманды,

используемое для непосредственного макрорасширения, например:

SEGSIZE EQU <TINY>

LANGUAGE EQU <WINDOWS PASCAL>

% MODEL SEGSIZE,LANGUAGE ; дает MODEL TINY,WINDOWS PASCAL

Включение расширения макрокоманды в файл листинга

─────────────────────────────────────────────────────────────────

Расширения макрокоманд, состоящих из нескольких строк, обыч-

но включаются в файл листинга. Однако в Турбо Ассемблере предус-

мотрены следующей директивы:

- .LALL

- .SALL

- .XALL

- %MACS

- %NOMACS

которые позволяют управлять листингом макрорасширений.

Использование условных директив

─────────────────────────────────────────────────────────────────

Существует два класса условных директив: директивы условного

ассемблирования и условные директивы генерации сообщений об ошиб-

ке. С помощью директив условного ассемблирования вы можете управ-

лять тем, какой код будет ассемблироваться в программе при опре-

деленных условиях.

Директивы условного ассемблирования позволяют вам генериро-

вать во время ассемблирования сообщения об ошибках при наступле-

нии определенных событий. Турбо Ассемблер выводит сообщение об

ошибке на экран и в файл листинга и предотвращает создание объек-

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

имеющиеся условные директивы.

Синтаксис условных директив

─────────────────────────────────────────────────────────────────

Тремя директивами условного ассемблирования являются дирек-

тивы IFxxx, ELSEIFxxx и ERRxxx. Эти директивы используются также,

как операторы условия в языках высокого уровня.

Директива условного ассемблирования IFxxx

─────────────────────────────────────────────────────────────────

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

IFxxx для определения блока кода, который включается в объектный

файл при удовлетворении определенных условий (таких как определе-

ние идентификатора или установка какого-то значения). Приведем

синтаксис оператора условного ассемблирования:

IFxxx

тело_условия_true

EMDIF

или

IFxxx

тело_условия_true

ELSE

тело_условия_false

ENDIF

где IFxxx представляет следующие директивы:

IF

IF1

IF2

IFDEF

IFNDEF

IFB

IFNB

IFIDN

IFIDNI

IFDIF

IFDIFI

Каждая директива условного ассемблирования IFxxx задает

конкретное условие, при вычислении которого получается истинное

(true) или ложное (false) значение. Если условие имеет значение

true, то выполняется ассемблирование и помещение в объектный файл

блока ассемблируемого кода "тело_условия_true". Если при вычисле-

нии условия получается значение false, то Турбо Ассемблер пропус-

кает "тело_условия_true" и не включает его в объектный файл. При

наличие директивы ELSE, если условие имеет значение false, то ас-

семблируется и выводится в объектный файл блок "тело_усло-

вия_false". Если условие имеет значение true, то этот блок игно-

рируется. Условный блок завершается директивой ENDIF.

Кроме особых случаев директив IF1 и IF2 (которые мы обсудим

позднее) два описанных блока кода являются взаимноисключающими:

в объектный файл включается либо "тело_условия_true", либо "тело_

условия_false", но не оба блока одновременно. Кроме того, если вы

используете форму IFxxx...ELSE...ENDIF, один из блоков будет обя-

зательно включаться в объектный файл. Если используется форма

IFxxx...ENDIF, то "тело_условия_true" может включаться или не

включаться в объектный файл, в зависимости от условия.

При использовании вложенных директив IF и ELSE директива

ELSE всегда соответствует ближайшей директиве IF.

В следующем примере test является идентификатором, который

управляет включением кода (если идентификатор не определен, то

генерируется соответствующий блок кода) Идентификатор color уста-

навливается в ненулевое значение, если дисплей цветной, и равен

0, если дисплей монохромный.

От этих значений зависит фактическая генерация кода:

.

.

.

IFDEF test ; true, если test определен

; первая часть блока кода ; если test определен

IF color ; true, если color <> 0

; блок кода color ; если color <> 0

ELSE ;

; код для монохромного

; дисплея если color = 0

ENDIF ;

; вторая часть блока кода ; если test определен

ELSE ;

; другой код ; если test не определен

ENDIF

.

.

.

┌────────────┬──────────┬───────────┬──────────────┬────────────┐

│ test │определен │ определен │ не определен │не определен│

│ color │ 0 │ не 0 │ 0 │ не 0 │

├────────────┼──────────┼───────────┼──────────────┼────────────┤

│ код │ блок кода│ блок кода │ другой код │другой код │

│ │ 1 │ 1 │ │ │

│ │ │ │ │ │

│цветной/моно│ блок кода│ блок кода │ блок кода │ │

│ │ color │ 2 │ 2 │ │

└────────────┴──────────┴───────────┴──────────────┴────────────┘

Если идентификатор test не определен,то не ассемблируется ни

код для цветного дисплея (color), ни для монохромного, поскольку

все это включено в блок условного ассемблирования, который ас-

семблируется только при определенном идентификаторе test.

Директивы условного ассемблирования ELSEIFxxx

─────────────────────────────────────────────────────────────────

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

ELSEIFxxx как сокращенную форму, когда требуется использовать

несколько директив IF. Директива ELSEIFxxx представляет собой эк-

вивалент директивы ELSE, за которой следует вложенная директива

IFxxx, но дает более компактный код. Например:

.

.

.

IF mode EQ 0

; кода для mode = 0

ELSEIF mode LT 5

; код для coe = 1..4

ELSE

; код для mode = 5...

ENDIF

.

.

.

сравните его со следующим:

.

.

.

IF mode EQ 0

; кода для mode = 0

ELSE

IF mode LT 5

; код для coe = 1..4

ELSE

; код для mode = 5...

ENDIF

ENDIF

.

.

.

Вне оператора IFxxx директиву ELSEIFxxx использовать нельзя.

Директивы генерации сообщений об ошибке ERRxx

─────────────────────────────────────────────────────────────────

Директива ERRxxx генерирует при удовлетворении определенных

условий сообщения пользователя об ошибке. Она имеет следующий об-

щий синтаксис:

ERRxxx [аргументы] [сообщение]

В этом случае директива ERRxxx представляет какую-либо из

директив условной генерации сообщения об ошибке (такие как

ERRIFB, .ERRB и т.д.).

"Аргументы" представляют аргументы, которые могут потребо-

ваться в директиве для вычисления условия. Некоторые директивы

требуют выражения, другие требуют символьного выражения, а неко-

торые - одно или два текстовых выражений. Некоторые из директив

вовсе не требуют аргументов.

Если указано "сообщение", то оно задает необязательное сооб-

щение, которое выводится с ошибкой. Сообщение должно быть заклю-

чено в кавычки (' или ").

Директивы генерации сообщений об ошибке генерируют пользова-

тельское сообщение об ошибке, которое выводится на экран и

включается в файл листинга (если он имеется) в месте расположения

директивы в исходном коде. Если директива задает сообщение, оно

выводится на той же строке непосредственно за ошибкой. Например,

директива:

ERRIFNDEF foo "foo не определено!"

если идентификатор foo не определен при обнаружении ошибки, при-

ведет к генерации ошибки:

User error: "foo не определено!"

Описания конкретных директив

─────────────────────────────────────────────────────────────────

Далее следует описание директив.

Безусловные директивы генерации сообщений об ошибке

─────────────────────────────────────────────────────────────────

Безусловными директивами генерации сообщений об ошибке явля-

ются директивы ERR и .ERR. Эти директивы всегда генерируют ошибку

и не требуют аргументов, хотя могут содержать необязательное со-

общение. Директиву .ERR можно использовать только в режиме MASM.

Условные директивы с выражениями

─────────────────────────────────────────────────────────────────

Эти директивы обеспечивают условное ассемблирование или ге-

нерацию сообщений об ошибке на основе результатов вычисления в

Турбо Ассемблере выражения. Во всех этих директивах при вычисле-

нии выражения должна получаться константа, и оно не может содер-

жать опережающих ссылок. Если при вычислении выражения получается

0, Турбо Ассемблер рассматривает выражение, как ложное (false). в

противном случае оно рассматривается как истинное (true).

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

вания, использующие выражения.

Директивы условного ассемблирования, использующие сообщения

Таблица 15.1

┌─────────────────────┬─────────────────────────────────────────┐

│ Директива IFxxx │ Ассемблирует "тело_условия_true" если: │

├─────────────────────┼─────────────────────────────────────────┤

│ IF выражение │ при вычислении выражения получается │

│ │ значение true. │

│ │ │

│ IFE выражение │ при вычислении выражения получается │

│ │ значение false. │

│ │ │

│ ELSEIF выражение │ при вычислении выражения получается │

│ │ значение true. │

│ │ │

│ ELSEIFE выражение │ при вычислении выражения получается │

│ │ значение false. │

└─────────────────────┴─────────────────────────────────────────┘

В следующей таблице показаны директивы генерации сообщений

об ошибке, в которых используются выражения:

Директивы генерации сообщений об ошибке, использующие выражения

Таблица. 15.2

┌────────────────────┬──────────────────────────────────────────┐

│ Директива ERRxxx │ Генерируется сообщение user error, если: │

├────────────────────┼──────────────────────────────────────────┤

│ ERRIF выражение │ при вычислении выражения получается зна- │

│ │ чение true. │

│ │ │

│ .ERRNZ выражение │ при вычислении выражения получается зна- │

│ │ чение true (только в режиме MASM). │

│ │ │

│ ERRIFE выражение │ при вычислении выражения получается зна- │

│ │ чение false. │

│ │ │

│ .ERRE выражение │ при вычислении выражения получается зна- │

│ │ чение false (только в режиме MASM). │

└────────────────────┴──────────────────────────────────────────┘

Условные директивы с идентификатором

─────────────────────────────────────────────────────────────────

Эти директивы обеспечивают условное ассемблирование или ге-

нерацию сообщения об ошибке на основе того, является ли опреде-

ленным один или более идентификаторов. Данные идентификаторы объ-

единены в выражение с идентификаторами.

Выражение с идентификаторами - это выражение, состоящее из

имен идентификаторов, булевских операций AND, OR, NOT и круглых

скобок. В выражении с идентификаторами каждое имя идентификатора

интерпретируется как булевское значение, при вычислении которого

получается значение true, если идентификатор существует (опреде-

лен), или false, если идентификатор не существует (даже если он

определяется в модуле позднее). Турбо Ассемблер комбинирует эти

значения, используя булевские операции, для получения конечного

значения true или false. В своей простейшей форме выражение с

идентификаторами содержит имя единственного идентификатора и дает

при вычислении значение true, если этот идентификатор определен.

Синтаксические правила в выражении с идентификаторами аналогичны

тем, которые используются в выражениях Турбо Ассемблера. Напри-

мер, если идентификатор foo определен, а идентификатор bar - нет,

то при вычислении выражения с идентификаторами получаются следую-

щие результаты:

Вычисление определенных и неопределенных идентификаторов

Таблица 15.3

┌───────────────────────────────────┬───────────────────────────┐

│ Выражение с идентификаторами │ Результат │

├───────────────────────────────────┼───────────────────────────┤

│ foo │ True │

│ │ │

│ bar │ False │

│ │ │

│ not foo │ False │

│ │ │

│ not bar │ True │

│ │ │

│ foo OR bar │ True │

│ │ │

│ foo AND bar │ False │

│ │ │

│ NOT (foo AND bar) │ True │

│ │ │

│ NOT foo OR NOT bar │ True (то же, что │

│ │ (NOT foo) OR (NOT bar) │

└───────────────────────────────────┴───────────────────────────┘

В следующей таблице показаны директивы, которые управляют

ассемблированием и используют выражение с идентификаторами:

Директивы, использующие выражение с идентификаторами Таблица 15.4

┌────────────────────────┬──────────────────────────────────────┐

│Директива IFxxx │ Ассемблирует "тело_условия_true" если│

├────────────────────────┼──────────────────────────────────────┤

│IFDEF выражение_ид │ при вычислении выражения получается│

│ │ значение true. │

│ │ │

│IFNDEF выражение_ид │ при вычислении выражения получается│

│ │ значение false. │

│ │ │

│ELSEIFDEF выражение_ид │ при вычислении выражения получается│

│ │ значение true. │

│ │ │

│ELSEIFNDEF выражение_ид │ при вычислении выражения получается│

│ │ значение false. │

└────────────────────────┴──────────────────────────────────────┘

В следующей таблице показаны директивы выводы сообщения об

ошибке, которые используют выражение с идентификаторами:

Директивы генерации сообщения об ошибке Таблица 15.5

┌────────────────────────┬──────────────────────────────────────┐

│Директива IFxxx │ Ассемблирует "тело_условия_true" если│

├────────────────────────┼──────────────────────────────────────┤

│ERRIFDEF выражение_ид │ при вычислении выражения получается│

│ │ значение true. │

│ │ │

│.ERRDEF выражение_ид │ при вычислении выражения получается│

│ │ значение true (только для режима│

│ │ MASM). │

│ │ │

│ERRIFNDEF выражение_ид │ при вычислении выражения получается│

│ │ значение false. │

│ │ │

│.ERRNDEF выражение_ид │ при вычислении выражения получается│

│ │ значение false (только в режиме│

│ │ MASM). │

└────────────────────────┴──────────────────────────────────────┘

Например, следующие условия генерации сообщения об ошибке

эквивалентны и приводят к генерации ошибки в случае определения

foo и bar:

ERRIFDEF foo AND bar

ERRIFNDEF NOT ( foo AND bar )

ERRIFBDEF NOT foo OR NOT bar

Условные директивы с текстовыми строками

─────────────────────────────────────────────────────────────────

Эти директивы условное ассемблирование или генерацию сообще-

ний об ошибке на основе содержимого текстовой строки. Текстовой

строкой может быть либо строка, заключенная в угловые скобки

(<>), либо имя текстовой макрокоманды с предшествующим символом

%. Например:

<ABC> ; текстовая строка ABC

%foo ; содержимое текстовой макрокоманды foo

Директивы условного ассемблирования, использующие текстовую

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

Директивы условного

ассемблирования, использующие текстовую строку Таблица 15.6

┌──────────────────────┬────────────────────────────────────────┐

│ Директива IFxxx │ ассемблирует "тело_условия_true", если:│

├──────────────────────┼────────────────────────────────────────┤

│ IFNB текст_строка │ "текст_строка" не состоит из одних про-│

│ │ белов. │

│ │ │

│ IFB текст_строка │ "текст_строка" не пуста. │

│ │ │

│ IFIDN текст_строка_1,│ "текст_строка_1" и "текст_строка_2" │

│ текст_строка_2 │ идентичны. │

│ │ │

│ IFINDI текст_строка_1│ "текст_строка_1" и "текст_строка_2" │

│ ,текст_строка_2 │ идентичны (регистр символов не учиты- │

│ │ вается. │

│ │ │

│ IFDIF текст_строка_1,│ "текст_строка_1" и "текст_строка_2" │

│ текст_строка_2 │ различны. │

│ │ │

│ IFDEFI текст_строка_1│ "текст_строка_1" и "текст_строка_2" │

│ ,текст_строка_2 │ различны (регистр символов игнорирует- │

│ │ ся. │

│ │ │

│ ELSEIFNB текст_строка│ "текст_строка" не состоит из пробелов. │

│ │ │

│ ELSEIFB текст_строка │ "текст_строка" не пуста. │

│ │ │

│ ELSEIFIDN текст_стро-│ "текст_строка_1" и "текст_строка_2" │

│ ка_1, текст_строка_2│ идентичны. │

│ │ │

│ │ │

│ ELSEIDNI текст_стро- │ "текст_строка_1" и "текст_строка_2" │

│ ка_1,текст_строка_2 │ идентичны (регистр символов игнориру- │

│ │ ется). │

│ │ │

│ ELSEIFDIF текст_стро-│ "текст_строка_1" и "текст_строка_2" │

│ ка_1,текст_строка_2 │ различны. │

│ │ │

│ ELSEIFDIFI текст_стро│ "текст_строка_1" и "текст_строка_2" │

│ -ка_1,текст_строка_2│ различны (регистр символов игнориру- │

│ │ ется). │

└──────────────────────┴────────────────────────────────────────┘

Использующие текстовую строку директивы генерации сообщения

об ошибке показаны в следующей таблице:

Директивы вывода сообщений

об ошибке использующие текстовую строку Таблица 15.6

┌────────────────────────┬──────────────────────────────────────┐

│Директива ERRxxx │ Генерирует сообщение об ошибке, если:│

├────────────────────────┼──────────────────────────────────────┤

│ERRIFNB текст_строка │ "текст_строка" не состоит из одних│

│ │ пробелов. │

│ │ │

│.ERRIFNB текст_строка │ "текст_строка" не состоит из одних│

│ │ пробелов (только для режима MASM). │

│ │ │

│ERRIFB текст_строка │ "текст_строка" состоит из пробелов. │

│ │ │

│.ERRB текст_строка │ "текст_строка" состоит из одних про-│

│ │ белов. │

│ │ │

│ERRIFIDN текст_строка_1,│ "текст_строка_1" и "текст_строка_2" │

│ текст_строка_2 │ идентичны. │

│ │ │

│.ERRIDN текст_строка_1, │ "текст_строка_1" и "текст_строка_2" │

│ текст_строка_2 │ идентичны (только для режима MASM). │

│ │ │

│ERRIFIDNI текст_строка_1│ "текст_строка_1" и "текст_строка_2" │

│ ,текст_строка_2 │ идентичны (регистр символов игнориру-│

│ │ ется). │

│ │ │

│.ERRIDNI текст_строка_1,│ "текст_строка_1" и "текст_строка_2" │

│ текст_строка_2 │ идентичны (регистр символов игнориру-│

│ │ ется) - только для режима MASM. │

│ │ │

│ERRIFDIF текст_строка_1,│ "текст_строка_1" и "текст_строка_2" │

│ текст_строка_2 │ различны. │

│ │ │

│.ERRDIF текст_строка_1, │ "текст_строка_1" и "текст_строка_2" │

│ текст_строка_2 │ различны (только для режима MASM). │

│ │ │

│ERIFDIFI текст_строка_1,│ "текст_строка_1" и "текст_строка_2" │

│ текст_строка_2 │ различны (регистр символов игнориру- │

│ │ ется). │

│ │ │

│.ERRFIFI текст_строка_1,│ "текст_строка_1" и "текст_строка_2" │

│ текст_строка_2 │ различны (регистр символов игнориру- │

│ │ ется) - только для режима MASM. │

└────────────────────────┴──────────────────────────────────────┘

Используйте эти директивы для проверки передаваемых макроко-

мандам аргументов (однако их можно использовать не только в мак-

рокомандах).

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

IFNB позволяют определить, передали ли вы в макрокоманду нужное

число аргументов. Если при вызове макрокоманды вы передали слиш-

ком мало аргументов, Турбо Ассемблер не генерирует сообщение об

ошибке. Незаданные аргументы просто остаются пустыми. Таким обра-

зом, вы можете определить макрокоманду, воспринимающую переменное

число аргументов. Например:

.

.

.

load MACRO addr, reg

IFNB <reg>

MOV reg,addr

ELSE

MOV ax,addr

ENDIF

ENDM

.

.

.

Вы можете вызывать макрокоманду данного примера, как load

test,cx, что даст генерацию инструкции mov cx,test, или вызвать

ее как load test, то приведет к генерации инструкции mov ax,test,

поскольку второй параметр пуст. Можно также использовать директи-

ву ERRIFB для генерации сообщения об ошибке, если в вызове макро-

команды пропущен аргумент:

.

.

.

load MACRO addr

ERRIFNB <addr>

MOV reg,addr

ENDM

.

.

.

Если эту макрокоманду вызвать с помощью load, а не с помощью

load test, то будет генерироваться ошибка.

Условия выполнения прохода Ассемблером

─────────────────────────────────────────────────────────────────

Следующие директивы обеспечивают выполнение условного ас-

семблирования или генерацию ошибки на основе текущего прохода Ас-

семблера:

┌─────────────────────┬─────────────────────────────────────────┐

│ Директива IFxxx │ ассемблирует "тело_условия_true", если:│

├─────────────────────┼─────────────────────────────────────────┤

│ IF1 │ Турбо Ассемблер выполняет первый проход.│

│ IF2 │ Турбо Ассемблер выполняет второй проход.│

└─────────────────────┴─────────────────────────────────────────┘

┌─────────────────────┬─────────────────────────────────────────┐

│ Директива ERRxxx │ генерирует ошибку user error, если: │

├─────────────────────┼─────────────────────────────────────────┤

│ ERRIF1 │ Турбо Ассемблер выполняет первый проход.│

│ │ │

│ .ERR1 │ Турбо Ассемблер выполняет первый проход│

│ │ (только для режима MASM). │

│ │ │

│ ERRIF2 │ Турбо Ассемблер выполняет второй проход.│

│ │ │

│ .ERR2 │ Турбо Ассемблер выполняет второй проход│

│ │ (только для режима MASM). │

└─────────────────────┴─────────────────────────────────────────┘

Обычно Турбо Ассемблер работает как однопроходный ассемблер.

Если вы используете средство многопроходной работы Турбо Ассемб-

лера (вызывая его с параметром командной строки /m), то при не-

обходимости используется несколько проходов.

Поскольку Турбо Ассемблер всегда выполняет по крайней мере

один проход, директива условного ассемблирования IF1 всегда будет

ассемблировать код своего условного блока, а директивы .ERR1 и

ERRIF1 всегда будут генерировать сообщение об ошибке (но только

на первом проходе).

Если вы используете любую из этих директив и не разрешаете

многопроходную работу, то Турбо Ассемблер будет генерировать для

всех таких директив предупреждение "Pass dependent construction"

("Конструкция, зависящая от прохода"), чтобы предупредить вас о

возможно опасном пропуске кода. Если вы разрешите многопроходную

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

рировать предупреждение Vaximum compatibility pass was done (Вы-

полнен проход с целью обеспечения максимальной совместимости).

Включение условных директив в файл листинга

─────────────────────────────────────────────────────────────────

Обычно код условного ассемблирования с ложным условием

(false) в листинг не включается. Используя директивы Турбо Ас-

семблера и параметры командной строки, вы можете это переопреде-

лить.

Генерация листинга

─────────────────────────────────────────────────────────────────

Файл листинга полезно использовать, когда вы хотите точно

видеть, что генерирует Турбо Ассемблер при ассемблировании каждой

инструкции или директивы. Основу этого файла составляет исходный

файл, в который включен большой объем сопровождающей информации о

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

инструкции полученный машинный код, а также смещение в текущем

сегменте (на каждой строке с машинным кодом). Кроме того, Турбо

Ассемблер выводит в таблицах информацию о метках и сегментах, ис-

пользуемых в программе, включая значение и тип каждой метки и ат-

рибуты каждого сегмента.

Примечание: См. в Главе 2 описание параметров команд-

ной строки /l и /la.

Турбо Ассемблер может также по запросу генерировать таблицу

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

ле, в которой показано, где определяется каждая метка, и где на

нее имеется ссылка.

Примечание: См. в Главе 2 описание параметра командной

строки /c.

Формат листинга

─────────────────────────────────────────────────────────────────

В верхней части каждой страницы листинга выводится заголо-

вок, содержащий версию Турбо Ассемблера, с помощью которой выпол-

нено ассемблирование файла, дату и время ассемблирования и номер

страницы в листинге.

Файл листинга содержит две части: аннотированный листинг ис-

ходного кода и таблицу идентификаторов. Сначала выводится исход-

ный ассемблируемый код с заголовком, содержащим имя файла, в ко-

тором находится исходный код. Вывод исходного кода Ассемблера

сопровождается информацией о машинном коде, который ассемблирует

Турбо Ассемблер. Все ошибки или предупреждения, обнаруженные в

процессе ассемблирования, включаются в листинг непосредственно за

содержащей ошибку строкой.

Строки кода в файле листинга имеет следующий формат:

<глубина> <номер_строки> <смещение> <машинный_код> <исходный_код>

где <глубина> показывает уровень вложенности включаемых файлов

или макрокоманд в файле листинга.

Поле <номер_строки> содержит номер строки в файле листинга

(не включая заголовки). Номера строк особенно полезны при исполь-

зовании перекрестных ссылок Турбо Ассемблера, в которых указыва-

ются номер строк. Учтите, что поле <номер_строки> не соответству-

ет номерам строк исходного модуля. Например, если в файл

включается другой файл или выполняется макрорасширение, то значе-

ние поля <номер_строки> продолжает увеличиваться, хотя текущая

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

мер строки обратно в строку исходного кода, вы должны найти стро-

ку в файле листинга, и найти такую же строку в исходном коде (по

ее внешнему виду, а не по номеру).

Поле <смещение> представляет смещение в текущем сегменте на-

чала машинного кода, сгенерированного из соответствующей исходной

строки Турбо Ассемблером.

Поле <машинный_код> показывает фактическую последователь-

ность шестнадцатиричных значений размером в байт или слово, кото-

рые ассемблированы из соответствующей исходной строки на Ассемб-

лере.

Поле <исходный_код> - это просто исходная строка Ассемблера,

с комментариями и всем, что в ней содержится. Некоторые исходные

строки (например те, которые содержат только комментарии) не ге-

нерируют никакого машинного кода. Эти строки не содержат полей

<смещение> и <машинный_код>, но имеют номер строки.

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

─────────────────────────────────────────────────────────────────

Имеется ряд директив, которые позволяют вам управлять видом

файла листинга. Общие директивы управления листингом включают в

себя следующие директивы:

- .LIST ; только режим MASM

- .XLEST ; только режим MASM

- %LIST

- %NOLIST

- %CTLS

- %NOCTLS

- %SYMS

- %NOSYMS

Директива %LIST выводит в файл листинга все строки исходного

кода. Эта директива назначается по умолчанию при создании файла

листинга. Чтобы запретить вывод в листинг всех строк исходного

кода, используйте директиву %NOLIST. Приведем пример:

%NOLIST ; запретить листинг

INCLUDE MORE .INC

%LIST ; разрешить листинг

Директивы .LIST и .XLIST работают также, как директивы %LIST

и %NOLIST. Приведем пример:

.LIST

jmp xyz ; эта строка всегда выводится

.XLIST

add dx,ByteVar ; не содержится в листинге

Для управления включением в листинг директив управления лис-

тингом вы можете использовать директивы %CTL и %NOCTL. Директива

%CTLS приводит к включению в листинг директив управления листин-

гом (таких как %LIST, %INCL и т.д.). Обычно они в листинг не вы-

водятся. Эта директива действует для всех последующих строк, поэ-

тому сама директива %CTLS в листинг не выводится. Директива

%NOCTLS изменяет действие директивы %CTLS на обратное. После за-

дания директивы %NOCTLS все последующие директивы управления лис-

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

Турбо Ассемблером по умолчанию, когда начинается ассемблирование

исходного файла). Например:

%CTLS

%NOLIST ; эта директива не будет включена в

; исходный файл

%NOCTLS

%LIST ; это не будет включаться в листинг

Для задания включения или не включения в файл листинга таб-

лицы идентификаторов вы можете использовать директивы %SYMS и

%NOSYMS (по умолчанию таблица идентификаторов выводится). Таблица

будет выводиться в конце файла листинга.

Приведем синтаксис директивы %SYMS:

%SYMS

Директива %NOSYMS имеет следующий синтаксис:

%NOSYMS

Директивы листинга включаемых файлов

────────────────────────────────────────────────────────────────

В том случае, когда вы хотите вывести в файл листинга вклю-

чаемые файлы, вы можете разрешить или запретить эту возможность с

помощью директив %INCL и %NOINCL. По умолчанию включаемые файлы

обычно включаются в файл листинга. Директива %NOINCL приостанав-

ливает вывод в файл листинга всех последующих включаемых файлов,

пока он снова не будет разрешен директивой %INCL. Это полезно ис-

пользовать при наличии больших включаемых файлов, которые содер-

жат, например, много определений EQU, которые никогда не изменя-

ются.

Приведем пример:

%INCL

INCLUSE DEFS.INC ; содержимое выводится в листинг

%NOINCL

INCLUSE DEF1.INC ; содержимое не выводится в листинг

Директивы вывода блоков условного ассемблирования

────────────────────────────────────────────────────────────────

Когда в исходном коде у вас содержатся блоки условного

ассемблирования, может оказаться желательным включение в листинг

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

мочь в тех случаях, когда вы хотите точно видеть поведение исход-

ного кода. В Турбо Ассемблере предусмотрены следующие директивы

вывода блоков условного ассемблирования:

- .LFCOND ; только для режима MASM

- .SFCOND ; только для режима MASM

- ,TFCOND ; только для режима MASM

- %CONDS

- %NOCONDS

Обычно Турбо Ассемблер не включает в листинг блоки условного

ассемблирования.

Директива %CONDS выводит в файл листинга все операторы ус-

ловного блока. При этом в файл листинга выводятся также все блоки

с условием false. Директива .LFCOND работает аналогично директиве

.LFCOND. Директива %NOCONDS предотвращает вывода в файл листинга

блоков условного ассемблирования с условием false. Директива

.SFCONDS работает аналогично директиве %NOCOND. Если вы хотите

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

пользуйте директиву .TFCOND.

Первая директива .TFCOND, которую обнаруживает Турбо Ассемб-

лер, разрешает вывод в листинг всех блоков условного ассемблиро-

вания. Если вы используете параметр командной строки /X, блоки

условного ассемблирования будут сначала выводиться в листинг, а

первая директива .TFCOND запретит их вывод. При каждом обнаруже-

нии в исходном файле директивы .TFCOND состояние вывода блоков

условного ассемблирования изменяется на обратное.

Для указания любой из этих директив поместите директиву на

отдельной строке исходного кода. Она будут влиять на непосредс-

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

вания.

Обычно макрорасширения включаются в файлы листинга. Наличие

такой информации в файле листинга может оказаться очень полезной,

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

семблере предусмотрено несколько директив, которые позволяют

включать и выключать данное средство. Это следующие директивы:

- .LALL ; только для режима MASM

- .SALL ; только для режима MASM

- .XALL ; только для режима MASM

- %MACS

- %NOMACS

Директива %MACS разрешает листинг всех макрорасширений. Тоже

самое делает директива .LALL, но она работает только в режиме

MASM. Вы можете использовать эти директивы для включения макро-

расширений в файл листинга.

Директива %MACS имеет следующий синтаксис:

%MACS

Директиву .LALL вы можете задать следующим образом:

.LALL

Если вы хотите подавить вывод всех операторов макрорасшире-

ния, используйте директивы %NOMACS или .SALL. Заметим, что эти

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

ния в файл листинга.

Директива %NOMACS имеет следующий синтаксис:

%NOMACS

Директива .SALL задается следующим образом:

.SALL

Доступная в режиме MASM директива .XALL позволяет вам выво-

дить в листинг только те макрорасширения, которые генерируют код

или данные. Она имеет следующий синтаксис:

.XALL

Директивы вывода листинга перекрестных ссылок

────────────────────────────────────────────────────────────────

В таблице идентификаторов листинга ссылок обычно выводится

большой объем информации о метках, группах и сегментах, но там не

сообщается, где определены сегменты, группы и метки и где они ис-

пользуются. Информация, выводимая в таблице перекрестных ссылок,

позволяет вам легко находить метки и следить за ходом выполнения

программы при ее отладке.

Существует несколько способов разрешения включения информа-

ции о перекрестных ссылках в файл листинга. Для получения инфор-

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

вать параметр командной строки /c (подробности можно найти в

Главе 2), либо включить в исходный код директивы, позволяющие вам

разрешать и запрещать вывод перекрестных ссылок для отдельных

частей исходного кода. Это следующие директивы:

- .CREF ; только для режима MASM

- .XCREF ; только для режима MASM

- %CREF

- %NOCREF

- %CREFALL

- %CREFREF

- %CREFUREF

Директивы %CREF и .CREF позволяют вам собрать информацию о

перекрестных ссылках для всех идентификаторах в исходном файле,

начиная с данной точки. Директивы %CREF и .CREF отменяют действие

директив %NOCREF или .XCREF, которые запрещают сбор информации о

перекрестных ссылках.

Директивы %CREF и .CREF имеют следующий синтаксис:

%CREF

или

.CREF

Директивы %NOCREF и .XCREF имеют синтаксис:

%NOCREF [идентификатор, ...]

или

.XCREF [идентификатор, ...]

Если вы используете директивы %NOCREF и .XCREF без указания

идентификатора, то вывод перекрестных ссылок запрещается пол-

ностью. Если вы указываете одно или более имен идентификаторов,

то вывод перекрестных ссылок запрещается только для данных иден-

тификаторов.

Директива %CREFALL выводит в листинг перекрестные ссылки для

всех идентификаторов. Директива %CREFALL изменяет действие преды-

дущей директивы %CREFREF (запрещающей вывод в таблицу перекрест-

ных ссылок тех идентификаторов, на которые ссылки отсутствуют) на

обратное. После указания директивы %CREFALL все встречающиеся да-

лее в исходном файле идентификаторы будут включаться в листинг

перекрестных ссылок. Турбо Ассемблер использует это режим по

умолчанию а начале ассемблирования исходного файла.

Директивы %CREFALL, %CREFREF и %CREFUREF имеют следующий

синтаксис:

%CREFALL

%CREFREF

%CREFUREF

Параметры изменения формата листинга

────────────────────────────────────────────────────────────────

Директивы управления форматом листинга изменяют формат файла

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

бить вид листинга под свой вкус и потребности.

Директива PAGE задает высоту и ширину страницы файла листин-

га и начинает новую страницу. Директива PAGE работает только в

режиме MASM. Она имеет следующий синтаксис:

PAGE [число_строк] [,число_столбцов]

PAGE +

где "число_строк" задает число строк, выводимых на странице лис-

тинга. Поле "число_столбцов" может принимать значения от 59 до

255 и задает число столбцов на странице. Если вы опустите один из

этих параметров, то текущая установка данного параметра остается

без изменений. Чтобы изменить только число столбцов, укажите пе-

ред этим параметром запятую, в противном случае вы измените число

строк.

Если вы укажете после директивы PAGE символ плюса (+), то

начинается новая страница, номер раздела увеличивается, а номер

страницы снова начинается с 1. Если вы используете директиву PAGE

без аргументов, то листинг возобновляется с новой страницы без

изменения номера раздела.

Директива %PAGESIZE работает также, как директива PAGE, но

она не начинает новую страницу и работает как в режиме Ideal, так

и в режиме MASM. Директива %PAGESIZE имеет следующий синтаксис:

%PAGESIZE [число_строк] [,число_столбцов]

Директива %NEWPAGE работает как директива PAGE без аргумен-

тов. Строки исходного текста после директивы %NEWPAGE будут начи-

наться в файле листинга с новой страницы. Директива %PAGESIZE

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

%NEWPAGE

Директива %BIN устанавливает длину поля объектного кода в

файле листинга. Директива %BIN имеет синтаксис:

%BIN размер

где "размер" является константой. Если вы не используете эту ди-

рективу, то поле кода операции занимает в файле листинга до 20

позиций, например:

%BIN 12 ; устанавливает 12 позиций в листинге

Директива %DEPTH устанавливает размер поля глубины в файле

листинга. Эта директива имеет следующий синтаксис:

%DEPTH размер

где "размер" задает, скольку столбцов нужно зарезервировать в по-

ле глубины файла листинга. Это поле указывает уровень вложенности

включаемых файлов (INCLUDE) и макрорасширений. Если в качестве

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

Обычно не требуется задавать "размер" > 2, поскольку при этом без

усечения будет выводиться глубина до 99. По умолчанию это поле

имеет значение 1.

Директива %LINENUM задает размер поля номеров строк в файле

листинга. Данная директива имеет следующий синтаксис:

%LINENUM размер

Директива %LINENUM позволяет вам задать, сколько позиций

должны занимать номера строк в файле листинга. В поле "размер"

должна указываться константа. Если вы хотите минимизировать шири-

ну листинга, то можете уменьшить размер поля номеров строк. Кроме

того, если ваш файл содержит более 9999 строк, то размер этого

поля может потребоваться увеличить, чтобы номера не усекались. По

умолчанию номер строки занимает 4 столбца.

Директива %TRUNC усекает слишком длинные поля листинга. Она

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

%TRUNC

Поле объектного кода в файле листинга имеет достаточно мес-

та для вывода кода, генерируемого большинством инструкций или ди-

рективами выделения данных. Размер этого поля можно настроить с

помощью директивы %BIN. Если отдельная строка исходного кода ге-

нерирует больше кода, чем можно вывести на одной строке, то оста-

ток автоматически усекается и таким образом будет невидимым. Если

вы хотите видеть весь генерируемый код, то используйте директиву

%NOTRUNC (слишком длинная строка при этом будет переноситься на

следующую). В противном случае используйте директиву %TRUNC. Вы

можете использовать эти инструкции для переключения режима усече-

ния.

Директива %NOTRUNC имеет следующий синтаксис:

%NOTRUNC

Директива %PCNT задает размер поля "сегмент:смещение" в фай-

ле листинга. Она имеет следующий синтаксис:

%PCNT размер

где "размер" - это число столбцов, которые вы хотите зарезервиро-

вать для смещения в текущем ассемблируемом сегменте. Турбо Ас-

семблер устанавливает размер, равный 4, для обычных 16-битовых

сегментов и 8 для 32-битовых сегментов процессора 80386. Директи-

ва %PCNT позволяет переопределить эти используемые по умолчанию

значения.

Директива TITLE, которую вы можете использовать только в ре-

жиме MASM, задает заголовок файла листинга. Эта директива имеет

следующий синтаксис:

TITLE текст

Заголовок "текст" будет выводиться в верхней части каждой

страницы после имени исходного файла и перед заголовком, заданным

по директиве SUBTTL. Директиву TITLE можно использовать в прог-

рамме только один раз.

Директива %TITLE работает также, как директива TITLE, но вы

можете использовать ее как в режиме MASM, так и в режиме Ideal.

Эта директива имеет следующий синтаксис:

%TITLE "текст"

Директива SUBTTL работает только в режиме MASM и задает под-

заголовок файла листинга. Она имеет следующий синтаксис:

SUBTTL текст

Подзаголовок выводится в верхней части каждой страницы после

имени исходного файла и после заголовка, заданного директивой

TITLE.

Директиву SUBTTL можно указывать в программе столько раз,

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

рый будет выводиться на следующей странице листинга.

Директива %SUBTTL работает аналогично директиве SUBTTL, но

ее можно указывать как в режиме Ideal, так и в режиме MASM. Эта

директива имеет синтаксис:

%SUBTTL "текст"

Директива %TABSIZE задает позицию табуляции в файле листин-

га. Данная директива имеет следующий синтаксис:

%TABSIZE размер

где "размер" - это число столбцов между двумя позициями табуляции

в файле листинга. По умолчанию это 8 столбцов.

Для задания длины поля исходного текста в файле листинга

можно использовать директиву %TEXT, которая имеет синтаксис:

%TEXT размер

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

ле листинга исходных строк. Если размер исходной строки превышает

длину этого поля, то оно будет либо усекаться, либо переноситься

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

%TRUNC или %NOTRUNC.

Чтобы сохранить все параметры управления листингом в

16-уровневом стеке, можно использовать директиву %PUSHCTL. Она

сохраняет только те параметры управления листингом, которые можно

разрешить или запретить (%INCL, %NOINCL и т.д.). Размеры полей

листинга не сохраняются. Данная директива особенно полезна в мак-

рокомандах, когда вы можете вызывать специальные режимы листинга,

которые отменяются при завершении макрорасширения.

Директива %PUSHCTL имеет синтаксис:

%PUSHCTL

Директива %POPCTL восстанавливает из стека параметры управ-

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

%POPCTL

Эта директива восстанавливает параметры управления листингом

в те значения, которые они имели перед последней директивой

%PUSHCTL. Значения размеров полей листинга (%DEPTH, %PCNT и т.д.)

не восстанавливаются.

Замечания по программам формата EXE

─────────────────────────────────────────────────────────────────

При загрузке программы EXE операционная система устанавлива-

ет регистры следующим образом:

┌─────────────────┬─────────────────────────────────────────────┐

│ Регистр │ Значение │

├─────────────────┼─────────────────────────────────────────────┤

│ DS, ES │ Содержит адрес параграфа для префикса прог- │

│ │ рамного сегмента программы (PSP). PSP со- │

│ │ держит передаваемые программе в командной │

│ │ строке аргументы и указатель на строку опе- │

│ │ рационной среды для программы. │

│ │ │

│ CS:IP │ Содержит начальный адрес, заданный в опера- │

│ │ торе END в одном из модулей программы, или │

│ │ адрес директивы STARTUPCODE. │

│ │ │

│ SS:SP │ Содержит адрес последнего слова, которое │

│ │ задает в программе сегмент стека. │

└─────────────────┴─────────────────────────────────────────────┘

В программах EXE вы можете задавать любую модель памяти.

Следует использовать возможно более простую модель, поскольку это

обеспечивает более быстрое выполнение и упрощает программирова-

ние. Например, если в вашей программе никогда не предполагается

использовать более 64К данных и области стека, то вполне можно

использовать модель TINY.

Директива STURTUPCODE в модуле генерирует инструкции, кото-

рые автоматически инициализируют все необходимые регистры, соот-

ветствующие выбранной модели. Для использования в программе она

сохраняет адрес параграфа PSP в сегменте ES.

Когда вы загружаете программу, операционная система выделяет

программе до ее завершения всю оставшуюся память. Для программ,

которые не используют динамически распределяемую область памяти,

или которые строят в памяти свою собственную динамически распре-

деляемую область, такое поведение вполне подходит. Другие прог-

раммы могут выделять память через DOS. В этом случае через запро-

сом на память из DOS память должна быть освобождена и доступна

операционной системе.

Для выхода из программы используется прерывание INT 21,

функция 4Ch.

Эти вопросы иллюстрируются примером программы EXEPROG.ASM на

дистрибутивном диске. Чтобы сформировать программу EXE, исполь-

зуйте утилиту MAKE. В формирующем файле MAKEFILE следует указать

все модули, с которыми компонуется программа, например:

EXECPROG.EXE: EXECPROG.OBJ

TLINK EXECPROG;

EXECPROG.OBJ: EXECPROG.ASM

TASM EXECPROG

Замечания по программам формата COM

─────────────────────────────────────────────────────────────────

Программы COM представляют собой ограниченные версии прог-

рамм EXE. Каждую программу формата COM можно представить как

программу EXE, но не каждую программу EXE можно представить как

программу формата COM. Здесь действуют следующие ограничения:

- Программы COM следует писать с использованием модели TINY.

- В программах COM нельзя использовать предопределенный сег-

мент стека.

- Программа COM не может содержать прямых адресных ссылок на

адрес сегмента или группы. Это означает, что программа не

может содержать непосредственных дальних вызовов или ссы-

латься на сегменты по имени. Все процедуры в программе COM

должны описываться как BEAR.

- Выполнение должно начинаться со смещения 100h в сегменте

кода. Чтобы это произошло, укажите в качестве первой инс-

трукции сегмента кода директиву STURTUPCODE.

Турбо Ассемблер загружает программы COM, начиная со смещения

100h в префиксе программного сегмента программы (PSP). Для этого

директива STARTUPCODE для модели TINY автоматически помещает в

программу ORG 100h.

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

ры:

┌───────────────────┬───────────────────────────────────────────┐

│ Регистр │ Значение │

├───────────────────┼───────────────────────────────────────────┤

│ CS,DS,ES,SS │ Содержит адрес параграфа в PSP программы. │

│ │ │

│ IP │ Устанавливается в значение 100h. │

│ │ │

│ SP │ Устанавливается в 0FFFEh (последнее слово │

│ │ в сегменте программы. │

└───────────────────┴───────────────────────────────────────────┘

Если вы не хотите размещать стек в конце сегмента программы,

то нужно установить новый стек. Для такого стека используйте неи-

нициализированный сегмент данных (UDATASEG).

Хотя программы COM должны определяться с моделью памяти

TINY, с помощью директив CODESEG, DATASEG и UDATASEG можно разде-

лить код данные и неинициализированные данные.

Как и в случае программ EXE, когда вы загружаете программу

COM, Турбо Ассемблер выделяет для ее завершения всю оставшуюся

память. При возврате памяти в DOS убедитесь, что вы не освободи-

ли непреднамеренно неинициализированные данные.

Данные вопросы иллюстрируются файлом-примером COMPROPG.ASM,

который можно найти на дистрибутивных дисках Турбо Ассемблера.

Чтобы сформировать программу COM, используйте утилиту MAKE.

В формирующем файле MAEKFILE следует указать все модули, с кото-

рыми компонуется программа, например:

COMPROG.COM: COMPROG.OBJ

TLINK COMPROG;

COMPROG.OBJ: COMPROG.ASM

TASM COMPROG

─────────────────────────────────────────────────────────────────

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

─────────────────────────────────────────────────────────────────

Данная глава познакомит вас с необязательными параметрами

командной строки Турбо Ассемблера. Мы опишем каждый параметр ко-

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

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

командные файлы. Наконец, мы опишем также файл конфигурации и то,

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

об ошибках.

Запуск Турбо Ассемблера из 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

то будет выведен экран со вспомогательным описанием параметров

командной строки и синтаксиса для задания ассемблируемых файлов.

─────────────────────────────────────────────────────────────────

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=отсутствует.

─────────────────────────────────────────────────────────────────

С помощью параметров командной строки вы можете задавать имя

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

управляющие их ассемблированием. В последующих параграфах все

ссылки на 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.

Примечание: С помощью директив, указанных в исходном

коде, вы можете отменить эквивалентные им параметры Ассемб-

лера.

Выше) приведен полный список параметров

Турбо Ассемблера. Далее эти параметры описаны подробно.

Параметр /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, задающие упорядочивание

сегментов по алфавитному порядку и эмулирование инструкций с пла-

вающей точкой.