-
Условный оператор со сложным условием
Если условие сложное, то обычно выполняют проверку составляющих его простых условий, осуществляя после каждой проверки необходимые переходы.
ПРИМЕР
Если бит номер 1 байтовой переменной R равен 0 и бит номер 5 равен 1, перейти на метку DA, иначе на метку NET
Из формулировки задачи следует, что переход на метку DA осуществляется, когда выполняются и первое, и второе условие одновременно, другими словами, если хотя бы одно условие не выполняется, должен быть переход на метку NET.
test R, 10b ; проверка бита номер 1
jnz net ; если бит ≠ 0, переход на net
test R, 100000b ; проверка бита номер 5
jz net ; если бит = 0 ( т.е. ≠1), переход на net
; первый бит = 0 и пятый ≠ 0 ( =1)
da: ……
jmp fin
net: …….
fin: ……
ПРИМЕР
Если бит номер 1 байтовой переменной R равен 0 или бит номер 5 равен 1, перейти на метку DA, иначе на метку net.
Переход на метку DA осуществляется, когда выполняется хотя бы одно условие.
test R, 10b ; проверка бита номер 1
jz da ; если бит = 0, переход на da
; первый бит ≠ 0, необходимо проверить пятый
test R, 100000b ; проверка бита номер 5
jnz da ; если бит . ≠ 0 ( т.е. =1), переход на da
; ни один заданный бит не удовлетворяет заданному условию
; переход на net (следующая команда)
net: …….
jmp fin
da: ……
fin: ……
-
Пример программы 1
7.5.1 Формулировка задачи
Разработать программу вычисления Z в зависимости от значения символа simv по формуле:
(3v) / (2d), если simv ≥ 's'
Z =
55, если simv < 's'
где: v (байт) - возраст студента ( количество полных лет );
d (байт) - день рождения студента.
Значение символа simv вводится с клавиатуры.
При тестировании программы для вывода полученных значений Z использовать модуль IO.ASM [7], листинг которого представлен в приложении А.
7.5.2 Постановка задачи
Для определения типа величины Z проанализируем формулу ее расчета. В первой, наиболее сложной части формулы, Z – результат деления чисел, значит под размещение Z необходимо выделить массив из двух элементов (неполное частное и остаток). Тип обоих результатов деления совпадает с типом делителя, в данном случае, это произведение 2*d, причем d по условию задачи – байт. Произведение сомножителей – байтов дает результат размером слово. Таким образом, Z следует описать как массив из двух элементов-слов.
В начале программы нужно предусмотреть вывод приглашения на ввод любого ASCII-символа. Для ввода символа использовать возможности прерывания int 21h, причем для контроля за правильностью ввода использовать функцию 1h, дающую «эхо».
После сравнения введенного символа с заданным выполнить расчет Z по соответствующей формуле и перейти на блок вывода результата.
Блок вывода должен обеспечивать вывод двух результатов, если расчет выполняется по первой части формулы, и одного – если по второй. Для корректной работы блока вывода ввести вспомогательную переменную - флаг, имеющую некоторое начальное значение (например, 0), задаваемое при ее описании, и изменяющуюся (например, на 1), если расчет выполняется по первой части формулы. Блок в обоих случаях обеспечивает безусловный вывод одного результата (неполного частного или 55), а далее после анализа флага либо выводит второй результат (остаток), либо сразу выполняет переход на завершение программы. Перед выводом остатка предусмотреть табуляцию – перевод курсора вправо на 8 позиций.
При выполнении расчета по первой части формулы в целях сокращения пересылок данных при делении сначала подсчитать знаменатель 2*d, а потом числитель 3*v.
Учесть, что делитель имеет тип – слово, следовательно, делимое (числитель) размещается в двойном слове DX:AX. В то же время фактически числителю, который является результатом умножения байтов 3*v, хватает слова, а именно, АХ. Значит в этом конкретном случае для получения правильного результата перед делением необходимо очистить регистр DX.
Для вывода чисел подключить к программе модуль IO.ASM.
7.5.3 Тестирование программы
Исходные данные: d=28, v=20.
При вводе символа f расчет производится по первой части формулы, неполное частное равно 1 , а остаток 4.
Если ввести символ t, то результат равен 55.
7.5.4 Листинг программы
model small
include io.asm ; подключение модуля io.asm
.stack 100h
.data
d db 28
v db 20
z dw ?, ? ; для результата
priglash db 'Введите символ-> ','$'
rez db 'Результат расчета -> ','$'
flag db 0 ;начальное значение флага
.code
start: ; точка входа в программу
mov ax, @data ; загрузка адреса сегмента данных
mov ds, ax
mov dx, offset priglash ; вывод строки
mov ah, 9h
int 21h
mov ah, 1h ; ввод символа
int 21h ; код символа в al
cmp al, 's' ; сравнение кодов символов
jb menshe ; если введенный символ меньше, на menshe
;********* simv ≥ 's' - расчет по первой части формулы *********
mov flag, 1 ; новое значение флага =1
mov al, 2 ; подготовка к умножению (знаменатель)
mul d ; [ax]:=2d
mov bx, ax ; копирование 2d в bx
mov al, 3 ; числитель
mul v ; [ax]:=3v
; для деления числитель должен быть: в dx - старшее слово,
; в ax - младшее слово (уже находится)
mov dx, 0 ; очистка dx
div bx ; неполное частное в ax, остаток в dx
mov z, ax ; неполное частное в первое слово массива z
mov z+2, dx ; остаток во второе слово массива z
jmp vivod ; безусловный переход на блок вывода
; ************* расчет по второй части формулы ***************
menshe: mov z, 55 ; результат в первое слово массива z
; ******************** блок вывода ************************
vivod: mov dx, offset rez ; вывод строки - сообщения
mov ah, 9h
int 21h
outint z ; вывод первого слова массива z
cmp flag, 0 ; если флаг=0, вывод завершен
je finish
; флаг изменился, продолжение вывода
mov dl, 9 ; вывод символа «табуляция»
mov ah, 2h
int 21h
outint z+2 ; вывод второго слова массива z
; завершение работы
finish: mov ah, 1 ; задержка для обозрения результата
int 21h
mov ax, 4C00h
int 21h
end start