48552 (588566), страница 11
Текст из файла (страница 11)
переход прямой ближний (в пределах текущего программного сегмента);
переход прямой дальний (в другой программный сегмент);
переход косвенный ближний;
переход косвенный дальний.
Все разновидности переходов имеют одну и ту же мнемонику jmp, хотя и различающиеся коды операций. Во многих случаях транслятор может определить вид перехода по контексту, в тех же случаях, когда это невозможно, следует использовать атрибутные операторы (short - прямой короткий переход; near ptr - прямой ближний переход; far ptr - прямой дальний переход; word ptr - косвенный ближний переход; dword ptr - косвенный дальний переход).
Команда | Назначение | Процессор |
JMP метка | Безусловный переход | 8086 |
. 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,'$' | ; cтрока с содержащая выводимые данные. |
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 байт.
Следующий пример будет работать так же, как и Пример №1.1, только быстрее.
. 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, '$' | ; cтрока с содержащая выводимые данные |
end begin | ; метка окончания кода программы |
2. Программа для практики.
Напишем программу, выводящую на экран все ASCII-символы (16 строк по 16 символов в строке).
. 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 равны нулю, что и соответствует кратности шестнадцати.
3. Содержание отчета.
3.1 Титульный лист.
3.2 Индивидуальный вариант задания.
3.3 Тестовые наборы данных и предполагаемые результаты.
3.4 Текст программы до отладки.
3.5 Список ошибок, обнаруженных при отладке.
3.6. Результаты выполнения тестов.
3.7. Распечатка листинга компиляции отлаженной программы с указанием работы каждой строки.
4. Задание для выполнения.
4.1 Выполните все примеры, что содержатся в описании данной лабораторной работы.
4.2 Проанализируйте работу программы примера для практики.
4.3 Изучить условия организации циклических переходов на языке Ассемблера.
4.4 Напишите программу, выводящую на экран слово "!!!!!!!!!! Hello!!!!!!!!!!" используя команды циклических переходов (3 варианта).
4.5 Получите задание у преподавателя (один из пяти вариантов табл. №1) и, пользуясь правилами оформления ассемблерных программ, создайте программу, выводящую на экран слово, D число раз.
4.6 Программу ассемблируйте в файл типа *.com или *. exe (на выбор);
5. Контрольные вопросы
5.1 Организация цикла с помощью команды loop?
5.2 Значимость регистра cx?
5.3 Максимальное число повторений команд цикла определяемого регистром сх?
5.4 Организация цикла с помощью команды jmp?
5.5. Разновидности команды jmp?
5.6. Организация цикла с помощью команд dec и jnz?
Табл. №1
№ вар. | Выводимые данные | Формула расчета | А | B | С |
Циклический переход | D=A+B+C | 101 | 345 | 121 | |
Hello world | D=A-B+C | 578 | 152 | 149 | |
Good Bye | D=A+B-C | 333 | 223 | 16 | |
Группа | D=A-B+C | 1502 | 834 | 1 | |
Лабораторная работа | D=A-B-C | 1056 | 33 | 125 |
ЛАБОРАТОРНАЯ РАБОТА №9
СПОСОБЫ И МЕТОДЫ ВЫВОДА ЧИСЕЛ
Цель работы: Освоить методы вывода чисел в двоичном, шестнадцатеричном и десятичном коде.
1. Вывод двоичного кода числа, записанного в регистр DH.
Методика выполнения.
Нужно последовательно проанализировать биты числа. В данной работе ограничимся байтом, который будем хранить в DH. Если бит нулевой (сброшен), то нужно вывести '0', если установлен, то '1'.
Алгоритм решения задачи:
проанализировать значение одного бита;
вывести значение бита;
перейти к следующему биту. И так 8 раз (БАЙТ!) - ЦИКЛ
Анализ бита: При анализе значения программисты обычно используют команду TEST, но в данной лабораторной работе мы будет использовать следующую команду SHL
Команда SHL осуществляет сдвиг влево всех битов операнда. Старший бит операнда поступает в флаг CF. Если команда записана в формате
SHL операнд, 1
сдвиг осуществляется на 1 бит. В младший бит операнда загружается 0. Если команда записана в формате
SHL операнд,CL
сдвиг осуществляется на число битов, указанное в регистре-счетчике CL, при этом в процессе последовательных сдвигов старшие биты операнда, пройдя через флаг CF, теряются, а младшие заполняются нулями
В качестве операнда команды SHL можно указывать любой регистр (кроме сегментного) или ячейку памяти размером, как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение.
Каждый сдвиг влево эквивалентен умножению знакового числа на 2, поэтому команду SHL удобно использовать для возведения операнда в степень 2.
Команда воздействует на флаги OF, SF, ZF, PF и CF.
Прореагировать на значение флага можно с помощью команды
JNC
Осуществляется переход на метку, если флаг CF равен нулю, иначе выполняется команда, непосредственно идущая после команды.
Пример №1.1
. model tiny | ; модель памяти, в которой сегменты кода, данных и стека объединены. |
. code | ; сегмент кода, который содержит данные. |
org 100h | ; начало СОМ-файла |
begin: | ; метка начала кода программы |
mov DH, | ; заносим в регистр dh - любой ASCII-код символа |
mov AH,2 | ; помещаем номер функции DOS "вывод строки (2)" в регистр АН. |
mov CX,8 | ; инициализация переменной цикла |
@1: mov DL,'0' | ; заносим в DL код символа '0' |
shl DH, 1 | ; сдвиг на 1 бит |
jnc @2 | ; переход, если '0' |
inc DL | ; используем тот факт, что код символа '1' на единицу больше кода символа '0' |
@2: int 21h | ; вызов прерывания DOS - вызов символа; |
LOOP @1 | ; переходим на метку @1 |
int 21h | ; вызов прерывания DOS - вызов символа; |
end begin | ; метка окончания кода программы |
Замечание: в описанном способе анализа значение исходного числа теряется. Иначе следует использовать команду ROL, но 8 раз для байта.
2. Вывод значения байта в шестнадцатеричной системе счисления