Лабораторная работа №4
Тема: Программирование разветвляющегося процесса. Программирование цикла с переадресацией.
Цель: Практическая реализация алгоритмов, пути в которых зависят от исходных данных, с использованием команд условной передачи управления. Решение задач, связанных с обработкой массивов, с применением специальных видов адресации.
Время выполнения: 2 часа.
Теоретические сведения
Циклы, позволяющие выполнить некоторый участок программы многократно, в любом языке являются одной из наиболее употребительных конструкций. В системе команд МП 86 циклы реализуются, главным образом, с помощью команды loop (петля), хотя имеются и другие способы организации циклов. В большинстве случаях число шагов в цикле определяется содержимым регистра СХ, поэтому максимальное число шагов составляет 64 К.
Организация циклических переходов, как на языках высокого уровня, так и на языке assembler представляет собой замечательное средство, позволяющее значительно снизить код исполняемой программы.
В общем виде любой цикл записывается в ассемблере как условный переход.
Организация цикла с помощью команды LOOP (Первый способ)
Команда loop (анг. петля) выполняет декремент содержимого регистра СХ (счетчик), и если оно не равно 0, осуществляет переход на указанную метку вперед или назад в том же программном сегменте в диапазоне - 128... + 127 байт (табл. 4). Обычно метка помещается перед первым предложением тела цикла, а команда loop является последней командой цикла. Содержимое регистра СХ рассматривается как целое число без знака, поэтому максимальное число повторений группы включенных в цикл команд составляет 65536 (если перед входом в цикл СХ=0). Команда не воздействует на флаги процессора.
Таблица 4
Синтаксическая запись команды LOOP:
Команда |
Назначение |
Процессор |
LOOP метка |
Организация циклов |
8086 |
Таблица 5
Простейший пример организации циклического перехода (со счетчиком в регистре cx) на языке Assembler:
. model tiny |
; модель памяти, в которой сегменты кода, данных и стека объединены. |
. code |
; сегмент кода, который содержит и данные. |
org 100h |
; начало СОМ-файла |
begin: |
; метка начала кода программы |
mov cx,10 |
; загружаем в (регистр-счетчик) CX количество повторов (отсчет будет идти от 10 до 0) |
Label1: |
; создаем метку (Label - метка). |
mov ah,9 |
; помещаем номер функции DOS "вывод строки (9)" в регистр АН. |
mov dx,offset String |
;помещает в регистр DX смещение метки String относительно начала сегмента данных |
int 21h |
; функция DOS "вывод строки" |
loop Label1 |
; оператор loop уменьшает на единицу CX и, если он не равен нулю, переходит на метку Label1 (строка 6) |
ret |
; функция DOS "завершить программу" |
string db 'privet $' |
; строка, содержащая выводимые данные. |
end begin |
; метка окончания кода программы |
В строке (5) загружаем в CX количество повторов (отсчет будет идти от 10 до 0). В строке (6) создаем метку (Label - метка). Далее (строки (7) - (9)) выводим сообщение. И в строке (10) оператор loop уменьшает на единицу CX и, если он не равен нулю, переходит на метку Label1 (строка (6)). Таким образом, строка будет выведена на экран десять раз. Когда программа перейдет на строку (11), регистр CX будет равен нулю.
Организация цикла с помощью команды JMP (Второй способ).
Команда jmp передает управление в указанную точку того же или другого программного сегмента. Адрес возврата не сохраняется. Команда не воздействует на флаги процессора.
Команда jmp имеет пять разновидностей:
- переход прямой короткий (в пределах - 128... + 127 байтов);
- переход прямой ближний (в пределах текущего программного сегмента);
- переход прямой дальний (в другой программный сегмент);
- переход косвенный ближний;
- переход косвенный дальний.
Все разновидности переходов имеют одну и ту же мнемонику jmp, хотя и различающиеся коды операций. Во многих случаях транслятор может определить вид перехода по контексту, в тех же случаях, когда это невозможно, следует использовать атрибутные операторы (short - прямой короткий переход; near ptr - прямой ближний переход; far ptr - прямой дальний переход; word ptr - косвенный ближний переход; dword ptr - косвенный дальний переход) (табл. 6).
Таблица 6
Синтаксическая запись команды JMP:
Команда |
Назначение |
Процессор |
JMP метка |
Безусловный переход |
8086 |
Таблица 7
Пример использования команды JMP:
. model tiny |
; модель памяти, в которой сегменты кода, данных и стека объединены. |
. code |
; сегмент кода, который содержит данные. |
org 100h |
; начало СОМ-файла |
begin: |
; метка начала кода программы |
label1: |
; создаем метку |
mov ah,9 |
; помещаем номер функции DOS "вывод строки (9)" в регистр АН. |
mov dx,offset String |
;помещает в регистр DX смещение метки String относительно начала сегмента данных |
int 21h |
; функция DOS "вывод строки" |
jmp Label1 |
; переход на строку с меткой Label1 |
add cx,12 |
; прибавить к значению регистра cx число 12 (данная команда не выполняется) |
dec cx |
; уменьшить значение регистра cx на 1 (данная команда не выполняется) |
ret |
; функция DOS "завершить программу" |
string db "PRIVET",13,10,'$' |
; строка, содержащая выводимые данные. |
end begin |
; метка окончания кода программы |
В результате работы программы будет зациклен блок строк (6) - (10) (Вывод строки PRIVET многочисленное количество раз) Строки (10) - (11).
Организация цикла с помощью команд DEC и JNZ (Третий способ)
С помощь этих операторов можно создавать циклы, которые будут работать быстрее оператора Loop. Комбинированная работа команд DEC и JNZ уменьшает содержимое регистра CX на 1 и выполняет переход на метку, если в CX не равен нулю.
Команда DEC, кроме того, устанавливает флаг нуля во флаговом регистре в состояние 0 или 1. Команда JNZ затем проверяет эту установку.
Аналогично командам JMP и LOOP операнд в команде JNZ содержит значение расстояния между концом команды JNZ и адресом перехода (Label1), которое прибавляется к командному указателю. Это расстояние должно быть в пределах от - 128 до +127 байт.
Таблица 8
Пример использования команд DEC и JNZ:
. model tiny |
; модель памяти, в которой сегменты кода, данных и стека объединены. |
. code |
; сегмент кода, который содержит данные. |
org 100h |
; начало СОМ-файла |
begin: |
; метка начала кода программы |
mov cx,10 |
; загружаем в (регистр-счетчик) CX количество повторов (отсчет будет идти от 10 до 0) |
Label1: |
; создаем метку (Label - метка). |
mov ah,9 |
; помещаем номер функции DOS "вывод строки (9)" в регистр АН. |
mov dx,offset String |
;помещает в регистр DX смещение метки String относительно начала сегмента данных |
int 21h |
; функция DOS "вывод строки" |
dec cx |
; оператор DEC уменьшает на единицу CX и, если он не равен нулю, переходит на метку Label1 |
jnz Label1 |
; условный переход на строку с меткой Label1 |
ret |
; функция DOS "завершить программу" |
string db 'priver ',13,10, '$' |
; строка, содержащая выводимые данные |
end begin |
; метка окончания кода программы |
Напишем программу, выводящую на экран все ASCII-символы (16 строк по 16 символов в строке) (табл.9).
Таблица 9
Программа для практики
. model tiny |
; модель памяти, в которой сегменты кода, данных и стека объединены. |
. code |
; сегмент кода, который содержит данные. |
org 100h |
; начало СОМ-файла |
begin: |
; метка начала кода программы |
mov cx,256 |
; задаем значение счетчика (256 символов) |
mov dl,0 |
; первый символ - с кодом 00 |
mov ah,2 |
; номер функции DOS "вывод символа" |
cloop: int 21h |
; вызов DOS |
inc dl |
; увеличение DL на 1 - следующий символ |
test dl,0Fh |
; если DL не кратен 16 |
jnz continue_loop; |
; продолжить цикл, |
push dx |
; иначе: сохранить текущий символ |
mov dl,0Dh |
; вывести CR |
int 21h |
; вызов DOS |
mov dl,0Ah |
; вывести LF |
int 21h |
; вызов DOS |
pop dx |
; восстановить текущий символ |
continue_loop: |
; метка |
loop cloop |
; продолжить цикл |
ret |
; завершение СОМ-файла |
end begin |
; метка окончания кода программы |
Здесь с помощью команды LOOP оформляется цикл, выполняющийся 256 раз (значение регистра СХ в начале цикла). Регистр DL содержит код символа, который равен нулю в начале цикла и увеличивается каждый раз на 1 командой INC DL. Если значение DL сразу после увеличения на 1 кратно 16, оно временно сохраняется в стеке и на экран выводятся символы CR и LF, выполняющие переход на начало новой строки. Проверка выполняется командой TEST DL,0Fh - результат операции AND над DL и 0Fh будет нулем, только если младшие четыре бита DL равны нулю, что и соответствует кратности шестнадцати.
Задания к лабораторной работе
Задание 1. Выполнить все примеры, что содержатся в описании данной лабораторной работы.
Задание 2. Реализовать на языке Ассемблер программу, выводящую букву «а» заданное количество раз.
Контрольные вопросы:
1) Как на языке Ассемблер реализуются различные виды циклов?
2) Как на языке Ассемблер реализуется условный оператор?
3) Каковы возможности циклического и условного оператора в процессе автоматизации системы?
Скачано с www.znanio.ru
Материалы на данной страницы взяты из открытых источников либо размещены пользователем в соответствии с договором-офертой сайта. Вы можете сообщить о нарушении.