С помощью команд перехода можно реализовать любые разветвления и циклы. Изучите таблицу 4, в которой представлены способы реализации ветвлений и циклов в языках Pascal и ассемблер.
Таблица 4.4
Реализация ветвлений и циклов в языках Pascal и ассемблер.
Тип цикла | Язык Pascal | Язык Ассемблер |
Ветвление | If X > 0 then begin Блок S1 end else begin Блок S2 end; | CMP X, 0 JLE L2 Блок S1 JMP Fin L2: Блок S1 Final: |
Цикл со счетчиком | For X:=1 to N do begin Блок S end; | MOV CX, N L: Блок S DEC CMP CX, 0 JNE L Final: |
Цикл с передусловием | While X > 0 do begin Блок S end; | Begin: CMP X, 0 JLE Fin Блок S JMP Begin Final: |
Цикл с постусловием | Repeat Блок S until X > 0 | Begin: Блок S CMP X, 0 JG Begin |
Для организации циклов с заранее известным числом повторений, в систему команд микропроцессора Intel 8086 включены специальные команды управления циклом: LOOP, LOOPE/LOOPZ и LOOPNE/LOOPNZ. Состояние флагов после выполнения команды этих команд не меняется.
4.4.1. Управление циклом по счетчику: LOOP <метка>
С помощью команды LOOP цикл может быть записан следующим образом:
MOV | CX, N | ; N>0 | |
L: | … | ||
… | |||
… | |||
LOOP | L |
Особенности команды LOOP.
ü В качестве счетчика цикла обязательно использовался регистр СХ, при другом регистре команду применять нельзя.
ü Начальное значение для СХ должно быть присвоено до цикла, причем этому регистру надо присваивать ровно столько, сколько раз должен повторяться цикл.
ü Так как команда LOOP ставится в конце цикла, тело цикла хотя бы раз обязательно выполнится. Поэтому для случая СХ = 0 такая схема цикла не подходит. Если возможен вариант, что число повторений может быть и нулевым, то при СХ = 0 надо сделать обход цикла с помощью команды условного перехода JCXZ:
MOV | CX, N | ; N>0 | |
JCXZ | L1 | ; CX = 0 а L1 | |
L: | … | ||
… | |||
… | |||
LOOP | L | ||
L1: | … |
Команда LOOP реализует только короткий переход, поэтому расстояние от нее до начала цикла (метки L) не должно превышать 127-128 байтов (примерно 30-40 команд). Если цикл содержит больше команд, тогда команду LOOP использовать нельзя и надо реализовывать цикл по-иному.
4.4.2. Цикл по счетчику и пока равно (пока ноль):
LOOPE <метка> или LOOPZ <метка>
Эта команда совмещает в себе изменение счетчика цикла (регистра СХ) и условный переход (короткий), когда счетчик еще не нулевой и когда предыдущая команда выработала флаг нуля, равный 1. Она используется для организации цикла с известным числом повторений, из которого возможен досрочный выход. До начала цикла в регистр СХ записывается число повторений.
По какой причине произошел выход из цикла (по ZF=0 или СХ=0), надо проверять после цикла. Проверить необходимо флаг ZF (по команде JE/JZ или JNE/JNZ), а не регистр СХ, т. к. условие ZF = 0 («не равно») может появиться как раз на последнем шаге цикла, когда и регистр СХ стал нулевым.
Чаще всего команда LOOPE используется для поиска первого элемента некоторой последовательности, отличного от заданной величины.
4.4.3. Цикл по счетчику и пока не равно:
LOOPNE <метка> или LOOPNZ <метка>
Эта команда аналогична команде LOOPE/LOOPZ, но выход из цикла осуществляет при СХ = 0 или ZF = 1. Команда LOOPNE обычно используется для поиска в некоторой последовательности первого элемента, имеющего заданную величину.
Examle 4.3. Фрагмент программы организации цикла, выводящий сообщение N раз.
; описание данных
.data
mes1 db ‘Шаг цикла выполнен’, 10, 13, ‘$’
mes2 db ‘Цикл завершен’, 10, 13, ‘$’
N EQU 5
; фрагмент кода программы
.code;
…
MOV CX, N; количество итерации равен пяти
cycl:
MOV DX, OFFSET mes1; вывод сообщения
MOV AH, 09h;
INT 21h;
LOOP cycl; CX = CX – 1, если CX > 0, то переход на метку, иначе к следующей команде.
MOV DX, OFFSET mes2; сообщение, что цикл завершен
MOV AH, 09h;
INT 21h;
MOV AH, 4Ch;
INT 21h;
…;
Examle 4.4. Фрагмент программы организации цикла, для поиска числа в массиве.
; описание данных
.data
mes1 db ‘Число найдено’, 10, 13, ‘$’
mes2 db ‘Число не найдено’, 10, 13, ‘$’
array db 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
; фрагмент кода программы
.code;
MAIN:
…
MOV CX, 10; количество итерации равен пяти
MOV SI, OFFSET array; инициализация начало массива
MOV BL, 3; искомое число
DEC SI; Декремент адреса в регистре SI
cycl:
INC SI; Инкремент адреса в регистре SI, установка на начало массива
CMP [SI], BL
LOOPNE cycl; CX = CX – 1, если CX > 0 и ZF = 0, то переход на метку, иначе к следующей команде.
JE ravno
JNE neravno
JMP exit
ravno:
MOV DX, OFFSET mes3;
MOV AH, 09h;
INT 21h
JMP exit;
neravno:
MOV DX, OFFSET mes4;
MOV AH, 09h;
INT 21h
exit:
Examle 4.5. Дан массив из десяти слов, содержащих целые числа. Найти максимальное значение элементов массива.
Фрагмент программы.
MAX | DW | ? | ||
MASS | DW | 10h, 20h, 30h, 5h, 40h, 15h, 20h, 70h, 35h, 34h | ||
… | ||||
LEA | BX, MASS | |||
MOV | CX, 10 | ; установить счетчик | ||
MOV | AX, [BX] | ;первый элемент массива в аккумулятор | ||
BEG: | CMP | [BX], AX | ;сравнить текущий элемент массива с максимальным | |
JL | NO | ;он меньше | ||
MOV | AX,[BX] | ;он больше | ||
NO: | ADD | BX, 2 | ;следующий элемент массива | |
LOOP | BEG | ; | ||
MOV | MAX,AX | ; | ||
… | ||||
Examle 4.6. Пусть N - байтовая переменная со значением от 0 до 8. В регистр АХ записать факториал этого числа. (8! = 40320 < 2 16).
Для решения этой задачи надо вначале положить АХ:= 1, а затем N раз выполнить умножение AX:= AX*i, меняя i от 1 до 8. При этом следует учитывать, что при N = 0 цикл не должен выполняться.
MOV | AX,1 | ; AX:=0! | |
MOV | CL, N | ||
MOV | СН, 0 | ; CX:= N как слово (счетчик цикла) | |
JCXZ | Fl | ; при N = 0 обойти цикл | |
MOV | SI, 1 | ; i:= l | |
F: | MUL | SI | ; (DX, AX):= AX*i (DX = 0) * |
INC | SI | ||
LOOP | F | ||
F1: | … |
Examle 4.7. Записать в регистр BL наименьшее число из отрезка [2, К], на которое не делится число N (К и N - байтовые переменные, 2 <= K < N), или записать 0, если такого числа нет.
Для решения будем последовательно делить N на числа 2, 3,..., К и сравнивать остатки от деления с 0 - до тех пор, пока не найдется ненулевой остаток либо не будут исчерпаны все числа отрезка.
MOV | DL, N | ; AX:=0! | |
MOV | DH, 0 | ; DX:= N как слово | |
MOV | CL, K | ||
MOV | CH, 0 | ||
DEC | CX | ; CX:= K-1 (счетчик цикла) | |
MOV | BL, 1 | ||
DV: | INC | BL | ; очередное число из [2,К] |
MOV | AX, DX | ||
DIV | BL | ; AH:=N mod BL | |
CMP | AH, 0 | ; mod = 0? | |
LOOPE | DV | ; цикл СХ раз и пока mod = 0 | |
JNE | DV1 | ; mod <> 0 а DV1 | |
MOV | BL, 0 | ; нет искомого числа | |
DVl: | … |