Команды циклов LOOPx
Группа команд условного перехода LOOPх служит для организации
циклов в программах. Все команды цикла используют регистр CX в
качестве счетчика цикла. Простейшая из них – команда LOOP. Она
уменьшает содержимое CX на 1 и передает управление на указанную
метку, если содержимое CX не равно 0. Если вычитание 1 из
CX привело к нулевому результату, выполняется команда, следующая
за LOOP.
Синтаксис:LOOP короткая метка
Логика работы:
СХ = Counter
short_label:
; Выполнение тела цикла
СХ = СХ - 1
if (СХ != 0) goto short_label
Аналог реализации команды LOOP на Ассемблере:
MOV СХ, Counter
short_label:
; Выполнение тела цикла
; Проверка условия ПРОДОЛЖЕНИЯ цикла
DEC СХ
СМР СХ, 0
JNE short_label
Команда LOOP уменьшает содержимое регистра СХ на 1,
затем передает управление метке shorMabel, если содержимое СХ
не равно 0. Передача управления на метку shortjabel для
базовых процессоров — только КОРОТКАЯ[-128,0]. Поскольку условие
выхода из цикла проверяется в КОНЦЕ, при значении Counter=0 цикл все
равно выполнится. Этого мало, мы еще и зациклимся. Чтобы этого избежать,
обычно ДО НАЧАЛА ЦИКЛА проверяют содержимое регистра СХ на ноль. Таким
образом, стандартная последовательность команд для организации цикла СО
СЧЕТЧИКОМ имеет следующий вид:
MOV CX, Counter
JCXZ ExitCicle            
            ; если CX = 0, цикл ОБОЙТИ
short_label:
; Выполнение тела цикла
LOOP short_label
ExitCicle:
Пример:Вычислить значение факториала
р = n! = 1*2*3*...*n
Известно, что 0! = 1. Отрицательным значение
n быть НЕ может.
.Model Large,С
; определение префикса для локальных меток
locals @@
.code
Extrn С n: Word
Extrn С p: Word
Public proizv1
Proizv1 Proc far            
          ; Вариант 1
mov cx,n
                          
            ; количество повторений
mov si,1
mov ax,si
jcxz @@Exit            
                   ; if cx=0 then Exit
@@begin:                        
            ; = НАЧАЛО цикла =
mul si                      
                        
; < dx:ax > = < ax >*< si >
inc si
; ==== Выход из цикла ==================
loop @@begin
@@Exit:
mov p,ax
ret
proizv1 endp
Public proizv2
Proizv2 Proc far            
          ; Вариант 2
mov cx ,n                           
          ; количество повторений
mov ax,1
jcxz @@Exit            
                   ; if cx=0 then Exit
@@begin:                        
            ; = НАЧАЛО цикла =
mul cx                      
                      
; < dx:ax > = < ax >*< cx >
; ==== Выход из цикла =========
loop @@begin
@@Exit:
mov p,ax ret
proizv2 endp end
Директива locals
Директива locals позволяет нам не думать о дублировании имен меток в
разных подпрограммах. Метки с префиксом @@ считаются локальными. Если
компилятор встретит метку с таким же именем, он просто при компиляции присвоит
ей другое имя (обычно эти метки получают в конце имени номер, который увеличивается
на единицу — все очень просто!).
Команда LOOPE (LOOPZ)
Команда LOOPE (LOOPZ) переход по счетчику и если равно.
Данная команда имеет два равнозначных мнемонических имени (if Equal
— если Равно или if Zero — если Ноль).
Синтаксис команды:
LOOPE короткая_метка
LOOPZ короткая_метка
Логика работы команды:
СХ = Counter
Short_Label:; Выполнение тела цикла
СХ = СХ - 1
if (СХ != 0 && ZF = 1) goto Short_Label
Все то, что говорилось для команды LOOP, справедливо и для команды
LOOPE (LOOPZ), добавляется еще проверка флага ZF. Применяется
данная команда в случае, если нужно досрочно выйти из цикла, как только находится
ПЕРВЫЙ элемент, ОТЛИЧНЫЙ от заданной величины.
Команда LOOPNE (LOOPNZ)
Команда LOOPNE (LOOPNZ) переход по счетчику и если НЕ равно.
Данная команда тоже имеет два равнозначных мнемонических имени (if Not
Equal — если НЕ равно или if Not Zero — если НЕ ноль). В отличие
от предыдущей команды проверяется, сброшен ли флаг нуля ZF=0.
Синтаксис команды:
LOOPNE короткая метка
LOOPNZ короткая_метка
Логика работы команды:
СХ = Counter
shortlabel: ; Выполнение тела цикла
СХ = СХ - 1
if (СХ != 0 && ZF == 0) goto shortlabel
Все то, что говорилось для предыдущей команды, справедливо и для команды
LOOPNE (LOOPNZ). Применяется данная команда в случае, если нужно
досрочно выйти из цикла, как только находится ПЕРВЫЙ элемент, РАВНЫЙ заданной
величине.
Пример:Вычислить значение суммы чисел натурального
ряда: s = 1+2+3+...+n. Вычисления закончить, как только значение суммы
станет равным некоторому числу k или не будут перебраны все n чисел.
Extrn С n:Word
Extrn С s:Word
Extrn С k:Word
Public sum
sum Proc far
mov cx,n          
                        
  ; количество повторений
xor ax, ax
xor si, si
jcxz @@Exit               
              ; if cx=0 then Exit
@@begin:                      
            ; = НАЧАЛО цикла =
inc si
add ax, si
cmp ах,k
; =Выход из цикла, если ax=k или сх=0
loopNE @@begin
@@Exit:
mov s,ax
ret
sum endp