$IF умова
A (здійснюється, якщо умова істинна)
$ELSE
B (здійснюється, якщо умова не істинна)
$ENDIF
На мал. 1,б показана блок-схема, що пояснює дію структури $IF-$ELSE-$ENDIF.
Насправді оператори $IF, $ELSE і $ENDIF є командами для програми SALUT. Коли ми викликаємо програму SALUT, то вона перетворює ці оператори в рядки коментарів (так що Асемблер буде їх ігнорувати), а потім створює їхній еквівалент на мові асемблера. Після цього програма може бути відтрансльована Асемблером, тому що операторів $IF, $ELSE і $ENDIF в ній уже немає. У наступних розділах ми покажемо, як програма SALUT перетворить спочатку структуру $IF-$ENDIF, а потім структуру $IF-$ELSE-$ENDIF.
Коли програма SALUT виявляє оператор $IF, вона генерує команду умовної передачі управління Jx, що змушує мікропроцесор пропустити оператори, що знаходяться між оператором $IF і наступним оператором $ENDIF. Звернемо увагу на слово «пропустити». Воно повідомляє нам, що програма SALUT повинна підставити команду Jx, обернену стосовно змісту операнда в операторі $IF. Отже, вона повинна замінити $IF Z на JNZ, а $IF на JNA. Звичайно, у кожної команди умовної передачі управління повинний бути адресат, і тому програма SALUT уставить мітку після оператора $ENDIF. Наприклад після того, як програма SALUT опрацює оператори $IF і $ENDIF, наш попередній приклад прийме такий вид:
CMP BX,0 ;Негативне значення?
;$IF L
JNL $$IF1
NEG BX ;Якщо так, змінити знак
;$ENDIF
$$IF1:
(Ми вставили мітку $$IF1 тільки для ілюстрації, тому що не знаємо яку мітку програма SALUT вставить насправді).
При опрацюванні структури $IF-$ELSE-$ENDIF програма SALUT замінює оператор $IF на команду Jx, що передає керування мітці, що слідує за $ELSE, заміняє $ENDIF на іншу мітку і підставляє замість $ELSE команду короткої передачі керування JMP, що адресується до мітки при $ENDIF Таким чином, як показано на наступному схематичному лістингу, програма SALUT перетворить оператори лівої частини в ті, що зазначені справа.
$IF умова JN умова $$IF1
А
$ELSE JMP SHORT $$EN1
$$IF1:
В
$ENDIF $$EN1:
Загальна форма операторів $IF і $ELSE
$IF умова [,AND/OR][,LONG]
$ELSE [LONG]
де операції AND і OR дозволяють Вам указувати додаткові умови, а атрибут LONG забезпечує можливість використання довгих блоків команд у цій структурі.
Дотепер ми обговорювали структури IF, що залежать від виконання тільки однієї умови, але (як і в мові Бейсік) ми можемо домогтися того щоб у структурі IF розглядалася комбінація умов у сполученні з операціями AND і OR
Проте між умовами в мові Бейсік і умовами на мові асемблера є визначені розходження. З одного боку, мікропроцесор розглядає кожний член вираження в порядку його появи; тут немає дужок, що задають порядок дій. З іншого боку, для кожного застосування операції AND або OR потрібно окремий оператор $IF, так що між ними можна поміщати команди.
Нижче приводиться загальний вид оператора $IF із двома умовами, сполученими операцією IF:
... (Обчислити умову1)
$IF умову1,AND
... (Обчислити умову2)
$IF умову2
... (Обидві умови виконані)
...
$ENDIF
Врахуємо, що команди обчислення умови 2 виконуються тільки в тому випадку, якщо умова 1 істинна. Якщо вона хибна, то мікропроцесор пропустить всі оператори аж до оператора $ENDIF. (Звернемо увагу і на те, що ми використовували тільки один оператор $ENDIF, оскільки операція AND об'єднує оператори $IF в один складний оператор.)
За допомогою команд, що слідують за першим оператором $IF, забезпечується установка флагу (або флагів) для другого оператора $IF. Наприклад, для видачі повідомлення "Вага в нормі", якщо значення WEIGHT знаходиться між 31 і 34, треба використовувати оператори
СМР WEIGHT,31
$IF AE,AND
СМР WEIGHT,34
$IF BE
(видати повідомлення "Вага в нормі")
$ENDIF
Звичайно, ми можемо включити сюди і ELSE, щоб виконати визначені дії (наприклад, видачу повідомлення "Вага за межами норми"), якщо одна з умов не виконується.
Нижче приводиться загальний вигляд оператора $IF, в якому умови пов'язані з операцією OR:
... (Обчислити умову1)
...
$IF умова1,OR
... (Обчислити умову2)
$IF умова2
... (умова1 або умова2 виконана)
$ENDIF
Тут мікропроцесор виконає команди обчислення умови2 тільки в тому випадку, якщо умова1 виявиться невиконаною.
Через те що програма SALUT заміняє оператори $IF і $ELSE на команди Jx і JMP типу SHORT (тобто команди короткої передачі керування), то розмір блоку команд не може перевищувати 127 байт, тобто біля 50-60 команд, що звичайно не є істотним обмеженням. Проте у випадку, якщо наша структура IF включає багато команд, то треба присвоїти операторам $IF або $ELSE атрибут LONG.
Наприклад, можна вказати
$IF A,LONG
Атрибут LONG змушує програму SALUT замінити оператор $IF А на команди
JA $$XL1
JMP $$IF1
$$XL1:
замість команди JNA $$IF1.
- Структура DO змушує мікропроцесор повторювати блоки команд до тих пір, поки не виконається задана умова. Існують такі три її форми: структура DO UNTIL (виконувати ... до) повторює блок команд до тих пір, поки умова вкінці цього блока не стане істинною.
- Структура DO WHILE (поки не ..., виконувати) повторює блок команд, поки умова на початку цього блоку не стане істинною. (Іншими словами, вона виконує блок, поки умова не виконується). Якщо початкова умова істинна, то вона пропускає блок, жодного разу не виконавши його.
- Структура DO COMPLEX (виконувати комплексно) являє собою комбінацію структур DO UNTIL і DO WHILE, що включає в себе два блоки команд. Вона виконує перший блок, потім перевіряє умову. Якщо вона істинна, то виконується другий блок і процес повторюється ще раз; у протилежному випадку другий блок пропускається і цикл завершується.
Примітка. Слова UNTIL (до), WHILE (поки) і COMPLEX (комплексно) використані лише для того, щоб допомогти розрізнити ці три форми структури DO.
Ця структура має загальний вигляд
$DO
A
$ENDDO умова
де умова -- це умова припинення циклу. Так як мікропроцесор перевіряє умову в кінці циклу, то команди блоку А завжди виконуються не менше одного разу. На мал. 2, а показана блок-схема, що описує дію структури DO UNTIL.
Структура DO UNTIL часто використовується для повторення команд в залежності від значення лічильника в регістрі СХ. Наприклад
MOV CX,10
$DO
... (Ці команди будуть повторюватися 10 разів)
...
$ENDDO LOOP
Тут команда LOOP зменшує вміст регістра СХ на одиницю і повертає керування оператору $DO, якщо значення регістра СХ відмінне від нуля. Еквівалентом на мові Бейсік є оператори
FOR X=10 TO 1 STEP -1
...
...
NEXT X
Ця структура має загальний вигляд
$DO
$LEAVE умова
A
$ENDDO
де умова -- це умова завершення циклу. На мал. 2, б показана блок-схема структури DO WHILE.
Звернемо увагу на те, що в структурі DO WHILE умова перевіряється перед командами циклу, а не після них, як це відбувається в структурі DO UNTIL. Отже, якщо початкова умова істинна, то мікропроцесор обходить цикл, не виконавши його ні разу. Структура DO WHILE ніби сигналізує мікропроцесору: "Виконуй наступні команди, поки умова не виконується".
Потрібно користуватися структурою DO WHILE для обходу циклу, організованого за допомогою лічильника в регістрі СХ, якщо регістр СХ вже містить нуль, наприклад
$DO
$LEAVE CXZ
...
...
$ENDDO LOOP
Структура DO COMPLEX схожа на структуру DO WHILE, але дозволяє Вам виконати деякі дії як до перевірки в операторі LEAVE, так і після її. Тим самим забезпечується вихід із середини циклу. Ця структура має такий загальний вигляд:
$DO
А
$LEAVE умова
У
$ENDDO
Як і раніше, умова являє собою умову завершення циклу. На мал.2, в показана блок-схема структури DO COMPLEX.
Тут блок команд А підготовляє умову, а блок команд В виконує те, що потрібно зробити, якщо умова не виконується. Наприклад, для зупинки програми доти, поки користувач не введе правильний пароль, можна скористатися таким прийомом:
$DO
(видати на екран "Будь ласка, введіть ваш пароль:")
(Перевірити пароль. Якщо він правильний, покласти флаг CF
рівним 1.)
$LEAVE CF
(видати на екран "Ви схибили. спробуйте ще раз" )
$ENDDO
Подібно до оператора $IF, що описаний в розд. 2, оператори $ENDDO і $LEAVE допускають вказівку операції AND (И) або OR (АБО), що дозволяє комбінувати умови. Крім того, в них можна вказувати атрибут LONG, що забезпечує можливість користуватися довгими блоками команд. Нарешті, в операторі $ENDDO можна вказувати параметр LOOP, що позбуває від необхідності зменшувати значення регістра СХ. Загальна форма цих операторів
$ENDDO [умова[,AND/OR]][,LONG]
$ENDDO [LOOPx][,LONG]
$LEAVE умова[,AND/OR][,LONG]
Для циклів із заданим числом повторень, лічильником яких служить регістр СХ, у програмі SALUT можна за рахунок застосування форми $ENDDO LOOP опустити команду DEC СХ. Інакше кажучи, замість форми
$DO
...
...
DEC CX
$ENDDO CXZ
Можна використовувати більш просту форму
$DO
...