На главную Назад
Добро пожаловать, уважаемый посетитель!

До сих пор макрокоманды не отличались от подпрограмм с точки зрения

как их функционирования, так и использования параметров. Далее, нам

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

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

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

быть возможность изменять в момент транслирования генерацию

соответствующего машинного кода в зависимости от удовлетворения

условий.

 

Макроассемблер фирмы IBM допускает условное ассемблирование. На

самом деле, условное ассемблирование не обязательно входит только в

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

в любом месте ассемблерного текста. Однако наиболее часто оно

встречается в макрокомандах. В IBM PC условное транслирование

поддерживается только Макроассемблером MASM.

 

Так же, как и выполнение макрокоманд, условное ассемблирование

происходит во время трансляции, а не выполнения программы. Условное

транслирование позволяет программисту "запрограммировать" ассемблер

на транслирование различных последовательостей кодов. Ассемблер

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

ассемблирования. Хотя эта возможность может использоваться

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

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

 

Фиг. 6.4 иллюстрирует условное транслирование при расширении

макрокоманды FIDIVR сопроцессора 8087. Условное тарнслирование

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

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

FIDIVR, может применяться к операндам двух типов. Операнд может

быть двух- или четырехбайтовым целым числом. Мы хотим, чтобы

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

операнда. Как мы вмдели, у команды ADD в действительности имеется

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

ассемблеру, который выбирает верную форму машинной команды в

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

команды FIDIVR Но в теперь макропроцессор должен определить тип

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

 

У команды FIDIVR может быть один из двух типов операндов, и в

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

Таким образом, расширение макрокоманды FIDIVR должно

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

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

В языке ассемблера имеется оператор TYPE, который возвращает

Microsoft (R) Macro Assembler Version 5.004/2/89 16:06:42

Фиг. 6.4 Условное транслированиеPage 1-1

 

PAGE,132

TITLEФиг. 6.4 Условное транслирование

 

FIDIVRMACROSOURCE

IFE2 - TYPE SOURCE

DB09BH;; FWAIT

ESC037H,SOURCE;; FIDIVR слово

ENDIF

IFE4 - TYPE SOURCE

DB09BH;; FWAIT

ESC017H,SOURCE;; FIDIVR короткое целое

ENDIF

ENDM

 

0000CODESEGMENT

ASSUMECS:CODE,DS:CODE

 

0000???? TWO_BYTEDW?

0002????????FOUR_BYTEDD?

0006??ONE_BYTEDB?

 

FIDIVRTWO_BYTE

00079B 1DB09BH;

0008DE 3E 0000 R 1ESC037H,TWO_BYTE;

FIDIVRFOUR_BYTE

000C9B 1DB09BH;

000DDA 3E 0002 R 1ESC017H,FOUR_BYTE;

FIDIVRONE_BYTE

 

0011CODEENDS

END

 

Фиг. 6.4. Ассемблирование макрокоманд по условию

значение, равное длине операнда. В случае FIDIVR мы ожидаем, что

операнд будет двух- или четырехбайтовым целым числом.

 

Выражение

 

IFE 2-TYPE SOURCE

 

вмакрокоманде FIDIVR проверяет длину операнда SOURCE.

Арифметическое выражение 2=TYPE SOURCE, равняется 0, если операнд

SOURCE является двухбайтовым целым числом, и принимает ненулевое

значение при любом другом типе операнда. Оператор IFE

(транслировать, если равно) сообщает ассемблеру, что нужно

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

операнда равно 0. Таким образом, оператор IFE вырабатывает значение

истина, если операнд SOURCE является двухбайтовым целым числом. В

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

оператором IFE до тех пор, пока не встретится оператор ENDIF. В

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

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

 

DB 09BH

ESC 37H,SOURCE

 

 

В первом вызове макрокоманды на Фиг. 6.4 в качестве операнда

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

макрокоманды ассемблер выбирает команду ESC 37H.

 

Так как команда FIDIVR имеет два варианта, соответствующие двум

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

макрокоманда использует второй оператор IFE. Когда операнд является

четырехбайтовым целым числом, макрокоманда генерирует код ESC 17H.

На Фиг. 6.4 показаны два разных расширения одной макрокоманды.

 

Обратите внимание, что в последнем из показанных на Фиг. 6.4

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

Так как ни один из операторов IFE не вырабатывает значения

"истина", то и ассемблироваться не будет ни один из них. В этом

случае макропроцессор не генерирует никакого кода.

 

С помощью оператора IFE ассемблер может проверять выполнение

различных условий. Эти условия приведены в таблице на Фиг. 6.5.

Общая форма оператора IF имеет вид:

 

IFххвыражение

...

ELSE

...

ENDIF

 

Если значение условия "истина", то ассемблер обрабатывает

участок программы, следующий за оператором IFхх. Этот транслируемый

участок программы заканчивается либо оператором ELSE или ENDIF.

Оператор ELSE не является обязательным. Если он имеется, то

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

невыполнении условия в операторе IF. Оператор ENDIF завершает

условное ассемблирование и является обязательным.

 

IF-операцияАссемблировать если:

---------------------------------------------------------------

IFвыражение Выражение не равно 0

IFEвыражение Выражение равно 0

IFDEFимя Имя уже было описано как внешнее

IFNDEF имя Имя еще не описывалось

IFB<аргумент> Аргумент пуст

IFNB<аргумент> Аргумент не пуст

IFIDN<арг1>,<арг2> Строка арг1 идентична строке арг2

IFDIF<арг1>,<арг2> Строка арг1 отличается от строки арг2

IF1 Первый поход ассемблера

IF2 Второй проход ассемблера

---------------------------------------------------------------

Фиг. 6.5 Операторы IF для условного ассемблирования

 

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

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

Фиг. 6.6показано применениедругого условного оператора- IFB, а

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

здесьявляетсяFLD-командазагрузкисопроцессора8087. Для

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

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

 

FLD

FLD 1

FLD короткое_вещественное

FLD длинное_вещественное

FLD временное_вещественное

 

Поле операнда макрокоманды FLD может быть пустым, содержать

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

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

случаев и сгенерировать правильный программный код. (все эти типы

данных рассмотрены очень подробно в гл.7.)

Оператор IFB проверяет наличие операнда. Если операнд

отсутствует, то ассемблер генерирует соответствующий этому случаю

программный код, так как оператор IFB вырабатывает значение

"истина". Это иллюстрирует первый вызов макрокоманды, когда

генерируется код

 

DB 09BH,0D9H,0C 1H

 

Оператор EXITM, содержащийся в этой части условного оператора

IF, реализует выход из макрокоманды. Каждый раз, когда при

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

расширение заканчивается, как если бы встретился ENDM. В данном

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

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

предупреждающее сообщение "Open conditionals:1" ("Незавершенные

условные операторы: 1"). Оно предупреждает вас, что ассемблер не Mincho"'>Microsoft (R) Macro Assembler Version 5.004/2/89 16:06:47

Фиг. 6.6 Вложенные условные макрокомандыPage1-1

 

PAGE,132

TITLEФиг. 6.6 Вложенные условные макрокоманды

 

FLDMACROSOURCE

IFB<SOURCE>

DB09BH,0D9H,0C1H;; FLD ST(1)

EXITM

ELSE

IFETYPE SOURCE

DB09BH,0D9H,0C0H+SOURCE

;; FLD ST(i)

ENDIF

IFE4 - TYPE SOURCE

DB09BH

ESC8,SOURCE;; FLD короткое плавающее

ENDIF

IFE8 - TYPE SOURCE

DB09BH

ESC40,SOURCE;; FLD длинное плавающее

ENDIF

IFE4 - TYPE SOURCE

DB09BH

ESC01DH,SOURCE;; FLD временное плавающее

ENDIF

ENDIF

ENDM

 

0000CODESEGMENT

ASSUMECS:CODE,DS:CODE

 

0000????????FOUR_BYTEDD?

0004????????????????EIGHT_BYTEDQ?

000C???????????????????TEN_BYTEDT?

?

FLD

00169B D9 C11DB09BH,0D9H,0C1H;

FLD1

00199B D9 C11DB09BH,0D9H,0C0H+1

FLDFOUR_BYTE

001C9B 1DB09BH

001DD9 06 0000 R1ESC8,FOUR_BYTE;

00219B 1DB09BH

0022DB 2E 0000 R1ESC01DH,FOUR_BYTE;

FLDEIGHT_BYTE

00269B 1DB09BH

0027DD 06 0004 R1ESC40,EIGHT_BYTE ;

FLDTEN_BYTE

 

002BCODEENDS

END

 

Фиг. 6.6 Вложенное условное ассемблирование

встретил оператора ENDIF, закрывающего условный оператор. Это

происходит в результате раннего входа из макрокоманды. Хотя это и

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

приводит. Если оператор EXITM расположен вне условного оператора,

то предупреждение не выводится.

Оператор EXITM необходим в данной макрокоманде, так как

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

транслируются. В нашем случае, если операнд SOURCE пуст, оператор

ELSE предотвращает генерацию всех других вариантов команды FLD.

Однако, продолжая просмотр, ассемблер проверяет оператора

 

IFE TYPE SOURCE

 

хотя и не может сгенерировать никакого кода. Если SOURCE пусто,

то ассемблер фиксирует синтаксическую ошибку. Вы можете не обращать

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

ошибках идет в разрез с нашими правилами. С другой стороны,

использование оператора EXITM приводит к предупреждению "Открытое

условие". Оно нежелательно, но это меньшее из двух зол.

 

Заметим, что макрокоманда FLD использует ветвь ELSE чтобы

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

только в случае непустоты этого поля. IF-выражения, содержащие

оператор TYPE, определяют, какой тип операнда использовался при

вызове макрокоманды. Хотя это не упоминается в Руководстве по

Макроассемблеру, оператор TYPE возвращает значение 0, если операнд

является не символическим именем, а константой. Выбор такого

способа в данной макрокоманде вызван скорее соображениями

работоспособности, чем стремлением к элегантности.


 

Mail.ru