Магда Юрий
Шрифт:
next:
inc AX ; инкремент регистра АХ
dec CX ; декремент регистра СХ
jnz next ; если CX = 0, выйти из цикла,
; иначе следующая итерация
. . .
Модификациями команды loop являются команды loope/loopz и 1 oopne/1 oopnz. Рассмотрим вначале команду loope/loopz. Обозначения loope и loopz представляют собой синонимы и относятся к одной и той же команде. Эта команда обладает дополнительными возможностями по обработке циклов. Она выполняет декремент содержимого регистра СХ (ЕСХ), и если оно не равно 0 и флаг ZF установлен в 1, то выполняется переход на указанную метку вперед или назад.
Рассмотрим пример использования команды loope. Это простое 16-разрядное приложение, которое выводит на экран дисплея строку без начальных пробелов (листинг 5.3).
Листинг 5.3. Вывод строки без начальных пробелов на экран
.model small
.data
s1 DB « String with leading blanks !$»
len EQU $-s1
msg DB «Blank string!$»
.code
start:
mov AX, @data
mov DS, AX
lea s1 , s1 ; адрес строки -> SI
dec SI ; декремент адреса для организации цикла
mov CX, len ; размер строки -> СХ
mov a1, ' ' ; шаблон для сравнения -> AL
next:
inc SI ; переход к адресу следующего элемента
cmp byte ptr [SI], AL ; сравнить элемент строки с пробелом
loope next ; повторять, пока не будет обнаружен символ,
; отличный от пробела,
; либо не будет достигнут
; конец строки
cmp CX, 0 ; был достигнут конец строки?
je fail ; да, строка состоит из пробелов,
; вывести соответствующее сообщение
mov DX, SI ; нет, в строке есть другие символы,
; поместить адрес первого символа,
; отличного от пробела, в регистр DX
show:
mov АН, 9h ; отобразить сообщения
int 21h
mov АН, lh
int 21h
mov AX, 4C00h
int 21h
fail:
lea DX, msg
jmp show
end start
end
Перейдем к анализу команды 1 oopne/1 oopnz. Отличие этой команды от loopе/1 oopz состоит в том, что цикл выполняется, пока выполняется условие ZF = 0. Обозначения loopпе и 1 oopnz являются синонимами и относятся к одной и той же команде. Пример использования команды loopпе приводится в листинге 5.4. Как и в предыдущем примере, это 16-разрядное приложение, которое выводит на экран дисплея часть строки, следующей за символом + (то есть String 2).
Листинг 5.4. Вывод на экран части строки после символа +
.model small
.data
s1 DB «String 1+String 2$»
len EQU $-s1
msg DB «Char + not found!$»
.code
start:
mov AX, @data
mov DS, AX
lea s1 , s1
dec SI
mov CX, len
mov a1, '+'
next:
inc SI
cmp byte ptr [SI], AL
loopne next
cmp CX, 0
je fail
mov DX, s1
show:
mov AH, 9h
int 21h
mov AH, lh
int 21h
mov AX, 4C00h
int 21h
fail:
lea DX, msg
jmp show
end start
end
Как видно из примеров, команда loop и ее модификации очень удобны для организации вычислительных алгоритмов, поскольку избавляют программиста от необходимости дополнительного кодирования и проверки условий. Последняя
команда, которую мы рассмотрим, является модификацией обычной команды loop, но предназначена она для работы с двойными словами. Такая команда очень полезна при разработке 32-разрядных приложений, которые в большинстве случаев оперируют двойными словами.
Эта команда обозначается как loopd, и основное ее отличие от команды loop состоит в том, что в качестве счетчика цикла используется регистр ЕСХ, содержимое которого в конце каждой итерации уменьшается на 4. Напомню, что двойное слово занимает в оперативной памяти 4 байта, а счетчик ЕСХ содержит размер области памяти в байтах. Адрес следующего обрабатываемого элемента отстоит от текущего на 4 в сторону увеличения или уменьшения, в зависимости от алгоритма задачи. Команда loopd оперирует с теми же флагами, что и loop. Должен заметить, что команда loopd не включена в ранние модели процессоров Intel.
В качестве примера выполнения цикла с использованием команды loopd приведу 32-разрядную процедуру, выполняющую поиск в массиве целых чисел первого элемента, меньшего -100. В случае удачного поиска процедура возвращает значение этого элемента в регистре ЕАХ, в случае неудачи – 0 в этом же регистре. Исходный текст процедуры (она называется _loopdex) приведен в листинге 5.5.
Листинг 5.5. Поиск первого элемента массива, меньшего -100
.586
.model flat
option casemap: none