
- •Практическая работа № 8.
- •2) Lds и les (Load ds и Load es) — команды загрузки адреса, состоящего из двух слов, в пару регистров (сегментный регистр и, чаще всего, базовый).
- •Организация циклов.
- •Inc al ; в регистре al организуем счетчик нулевых элементов
- •Inc si ; увеличиваем si на 1, для перехода к след. Элементу mas
- •Команды, организующие циклы
- •Доступ к элементам массива
- •Осторожно ошибки!
- •Int 21h ; вызов dos
- •Inc cx ; добавляем 1 к cx (!)
- •Варианты заданий
- •Контрольные вопросы:
Организация циклов.
Организовать циклическое выполнение некоторого участка программы можно, например, используя команды условной передачи управления или команду безусловного перехода jmp.
Пример программы, подсчитывающей количество нулевых элементов в массиве байтов:
.model small
.stack 100h
.data
len equ 10 ; количество элементов в mas
mas db 1, 0, 9, 8, 0, 7, 8, 0, 2, 0
.code
start:
mov ax, @data
mov ds, ax
mov cx, len ; кол-во элементов в mas записали в cx
xor ax, ax
xor si, si
cycl:
jcxz exit ; проверка cx на 0, если cx=0, то выход
cmp mas[si], 0 ; сравнение очередного элемента массива mas с 0
jne ml ; если не равно 0, то переход на метку ml
Inc al ; в регистре al организуем счетчик нулевых элементов
ml:
Inc si ; увеличиваем si на 1, для перехода к след. Элементу mas
dec cx ; уменьшаем значение счетчика цикла на 1
jmp cycl
exit:
mov ax, 4c00h
int 21h
end start
Цикл в данной программе организован тремя командами jcxz, dec и jmp. Команда jcxz выполняет две функции: предотвращает выполнение "пустого" цикла (когда счетчик в cx равен 0) и отслеживает окончание цикла после обработки всех элементов поля mas. Команда dec после каждой итерации (прохода) цикла уменьшает значение счетчика в регистре cx на 1. При такой организации цикла все операции по его функционированию предусматриваются программистом. Учитывая важность циклов при создании программ, в систему команд ввели группу из трех команд, облегчающую программирование циклов. Эти команды также используют регистр cx в качестве счетчика цикла. Это такие команды, как:
Команды, организующие циклы
LOOP метка_перехода - повторить цикл. Команда позволяет организовать циклы. подобные циклам for в языках высокого уровня с автоматическим уменьшением счетчика цикла. Работа команды заключается в выполнении следующих действий:
декремента регистра cx;
сравнения регистра cx с нулем;
если cx > 0, то управление передается на метку перехода;
если cx = 0, то управление передается на следующую после loop команду программы.
LOOPE/ LOOPZ метка_перехода - повторить цикл пока cx <> 0 или флаг zf = 0. Обе эти команды являются полными синонимами, работайте с той, с которой удобно. Работа этих команд заключатся в выполнении следующих действий:
декремента регистра cx;
сравнения регистра cx с нулем;
анализа состояния флага нуля zf;
если cx > 0 и zf = 1, то управление передается на метку перехода;
если cx = 0 или zf = 0, то управление передается на следующую после loop команду программы.
LOOPNE/ LOOPNZ метка_перехода - повторить цикл пока cx <> 0 или флаг zf = 1. Обе эти команды также являются абсолютными синонимами, работайте с той, с которой удобно. Работа этих команд заключатся в выполнении следующих действий:
декремента регистра cx;
сравнения регистра cx с нулем;
анализа состояния флага нуля zf;
если cx > 0 и zf = 0, то управление передается на метку перехода;
если cx = 0 или zf = 1, то управление передается на следующую после loop команду программы.
Команды LOOPE/LOOPZ и LOOPNE/LOOPNZ по принципу своей работы являются взаимообратными. Они расширяют действие команды LOOP тем, что дополнительно анализируют флаг zf, что дает возможность организовать досрочный выход цикла, используя этот флаг в качестве индикатора. Типичное использование данных команд связано с операцией поиска определенного значения в последовательности или со сравнением двух чисел.
Недостаток всех перечисленных команд организации цикла в том, что они реализуют только короткие переходы (от -128 до +127 байтов). Для работы с длинными циклами придется использовать команды условного перехода и команду jmp, поэтому необходимо освоить оба способа организации циклов.
Описание команд цикла сведено в таблице
Таблица 2 - Команды циклов
Название |
Мнемоника |
Альтернативная мнемоника |
КОП |
Проверяемое условие |
Зациклить |
LOOP |
- |
11100010 |
(CX)=0 |
Зациклить пока ноль (равно) |
LOOPZ |
LOOPE |
11100001 |
(ZF=1)&((CX)=0) |
Зациклить пока не ноль (неравно) |
LOOPNZ |
LOOPNE |
11100000 |
(ZF=0)&((CX)=0) |
Перейти по (CX) |
JCXZ |
- |
11100011 |
(CX)=0 |
Команды циклов идентичны по формату и очень близки по выполняемым действиям командам условных переходов. Однако по сравнению с последними они имеют ряд особенностей, позволяющих эффективно использовать их при программировании циклических участков алгоритмов.
Один из наиболее распространенных видов циклического участка программы представлен на рисунке:
СЧ=<число
повторений>
тело цикла
СЧ=СЧ-1
нет
СЧ = 0
да
Рис.
Структура счетного цикла с постпроверкой
Команды циклов предназначены для упрощения действий декремента (вычитания единицы), проверки условия и перехода.
За исключением команды JCXZ, которая не изменяет значения регистра CX, при выполнении команд циклов производятся следующие действия: CX=(CX)-1. Затем если проверяемое условие выполнено, то IP=(IP)+disp8 с расширением знаком до disp16, в противном случае IP не изменяется, и программа продолжает выполнение в естественном порядке.
Пример представления фрагмента
программы в машинной форме записи
Рассмотрим пример кодирования команд, представляющих собой некоторый законченный в смысловом отношении фрагмент программы.
Необходимо сложить k слов массива a[i], расположенных последовательно в оперативной памяти, начиная с адреса [31A6h], а результат записать по адресу [3000h].
Один из возможных вариантов программы, не использующий команду цикла, представлен в табл. 3.5. В программе предполагается, что конечный и промежуточные результаты не превышают длины слова. Количество слагаемых также занимает слово и записано перед исходным массивом, то есть по адресу 31A4h. Начальное значение IP взято произвольно.
Отметим некоторые особенности использования отдельных команд этой программы. Обнуление регистра AX осуществляется вычитанием его содержимого из самого себя. Переход к новому слагаемому достигается использованием регистровой относительной адресации с изменением на каждом шаге содержимого индексного регистра на длину слагаемого, то есть на 2.
Последняя команда, засылка результата, закодирована в специальном формате работы с аккумулятором.
ПРИМЕР
Таблица 3 – Коды команд программы
Символическая запись |
Коммен- тарий |
IP |
Машинное представление |
|
2-й код |
16-й код |
|||
MOV CX,[31A4h]; |
CX = содержимое ячейки 31A4h |
0100 |
10001011 00001110 10100100 00110001 |
8B 0E A4 31 |
SUB AX,AX; |
AX = 0 |
0104 |
00101001 11000000 |
29 C0 |
MOV SI,AX; |
SI=AX |
0106 |
10001011 11110000 |
8B F0 |
CYC: ADD AX,[SI+31A6h]; |
S = S+a[i] |
0108 |
00000011 10000100 10100110 00110001 |
03 84 A6 31 |
ADD SI,2; |
SI=SI+2 |
010C |
10000011 11000110 00000010 |
83 C6 02 |
DEC CX; |
CX=CX-1 |
010F |
01001001 |
49 |
JNZ CYC; |
перейти, если ZF= 0 |
0110 |
01110101 11110110 |
75 F6 |
MOV [3000h],AX; |
содержимое ячейки 3000h=AX |
0112 |
10100001 00000000 00110000 |
A1 00 30 |
Организация одномерных массивов
Все элементы массива располагаются в памяти последовательно!
Описание элементов массива
mas db 1,2,3,4,5
mas dw 5 dup (0)