
- •I.Ошский Государственный Университет
- •1. Предварительная подготовка
- •2 Порядок выполнения работы на эвм
- •Контрольные вопросы:
- •IV.Лабораторная работа №2 Массивы
- •23 04 05 67 05 06 07 99 67 08 09 23 87 09 00 08
- •Контрольные вопросы:
- •Лабораторная работа №3
- •Контрольные вопросы:
- •Лабораторная работа №4 Процедуры.
- •Теоретическая часть
- •Работа команд ret и retf
- •Состояние флагов после выполнения команды не меняется. Error: Reference source not found
- •Программа №7.1
- •Контрольные вопросы
Министерство образования,
и культуры Кыргызской Республики
I.Ошский Государственный Университет
II.
ЛАБОРАТОРНЫЕ РАБОТЫ
ПО ЯЗЫКУ ASSEMBLER
Составитель: Аркабаев А.Н
Ош 2004 г.
III.Лабораторная работа №1
Циклы
Цель работы:
научить организацию циклов на Ассемблере;
научить использовать команды организации циклов;
ТЕОРЕТИЧЕСКАЯ ЧАСТЬ
Методы адресации
Во всех 16-битовых ЭВМ принимаются какие-либо меры для расширения адресного пространства памяти, т.к. 16-битовый адрес позволяет адресоваться только к 64 Кб. В изучаемой ПЭВМ память разбивается на сегменты размером до 64 Кб. По умолчанию каждый сегмент начинается с границы параграфа (фрагмента памяти размером в 16 б). Физический адрес в памяти складывается из начального адреса сегмента и 16-битового смещения (исполнительного адреса, EA) в пределах сегмента. Для получения физического начального адреса (ФА) содержимое сегментного регистра (начальный номер параграфа) умножается на 16, т.е. дополняется справа четырьмя нулями:
ФА = ННП * 16 + смещение.
Если какой-либо элемент данных занимает несколько байтов, то его младший байт размещается по младшему адресу, который и считается адресом многобайтового элемента в целом.
При выполнении большинства команд операнд может находиться:
в регистре (1 или 2 байта); непосредственно в команде (1 или 2 байта); в памяти.
В последнем случае исполнительный адрес EA (смещение в сегменте) образуется как сумма содержимого базового регистра (или указателя), индексного регистра и сдвига, указанных в операторе. Возможны и частные случаи - отсутствие того или иного компонента. Всего различных вариантов 8 (вариант задается 3-битовым полем r/m). С учетом того, что сдвиг может иметь длину 1 или 2 байта или отсутствовать (3 варианта), общее количество комбинаций (режимов адресации) 8 * 3 = 24.
Следует заметить, что система адресации микpопpоцессоpа реализует далеко не все существующие в ВТ способы адресации и имеет ряд особенностей:
- существуют ограничения на выбор регистров: для каждого способа адресации подразумевается использование не всех, а только определенной группы регистров;
- есть ограничения на использование способов адресации в двухоперандных командах (недопустимы команды "память-память", "сегментный регистр - сегментный регистр", "сегментный регистр - непосредственный операнд"). Среди 24 режимов адресации есть такие, которые, по сути, мало отличаются друг от друга, поэтому в литературе режимы адресации обычно делят на 7 групп (способов адресации):
1) регистровая; 2) непосредственная; 3) прямая; 4) косвенная регистровая; 5) адресация по базе (базовая); 6) прямая с индексированием; 7) адресация по базе с индексированием (базовая индексная). Нетрудно заметить, что такое разделение есть не что иное, как попытка проклассифицировать режимы адресации по общепринятым способам адресации, причем не бесспорная, т.к., например, базовая отличается от индексной только используемыми регистрами.
ПРИМЕЧАНИЕ. Так как МП реализует режимы адресации, а в операторах языка указываются способы адресации, то различные трансляторы допускают различные вольности в форме написания оператора (далее вам предлагается убедиться в допустимости этих форм). Для переносимости программ на другой транслятор рекомендуется использовать основную форму записи, если в ином нет острой необходимости. Способы адресации приведены в табл.1.
Таблица 1
N п/п |
Адресация |
Основной формат оператора |
Сегмент по умолчанию |
Примечание |
1 |
Регистровая |
Регистр 1 б или 2 б |
|
Наиболее быстрое выполнение |
2 |
Непосредственная |
Данное 1 б или 2 б |
|
Применяется в операциях с константами |
3 |
Прямая |
Исполнительный адрес 2б |
DS |
Применяется для однократного обращения к памяти |
4 |
Косвенная регистровая |
[BX] [ВР] [SI] [DI] |
DS SS DS DS |
Применяется при работе с одномерными массивами |
5 |
Базовая |
[BX] + сдвиг [BP] + сдвиг |
DS SS |
Применяется для обращения к элементу структуры, нач. адрес которой в ВР или ВХ |
6 |
Прямая с индексированием |
Сдвиг[SI] Сдвиг [DI] |
DS DS |
Применяется при работе c одномерными массивами, сдвиг - нач. адрес массива |
7 |
По базе с индексированием |
Сдв.[BX][SI] Сдв.[BX][DI] Сдв.[BP][SI] Сдв.[BP][DI] |
DS DS SS SS |
Применяется при работе с двумерными массивами |
Примечание. Термин "сдвиг", а не "смещение" (это может быть константа, метка, переменная) использован, чтобы избежать двусмысленности: сдвиг указывается в операторе и используется для вычисления смещения (исполнительного адреса) в пределах сегмента.
Одним из видов конструкций в программе, которые можно построить с помощью условных переходов, являются циклы. Цикл - это просто-напросто блок кода, завершающийся условным переходом, благодаря чему данных блок может выполняться повторно до достижения условия завершения. Возможно, вам уже знакомы такие конструкции циклов, как for и while в языке Си, while и repeat в Паскале и FOR в Бейсике.
Для чего используются циклы? Они служат для работы с массивами, проверки состояния портов ввода-вывода до получения определенного состояния, очистки блоков памяти, чтения строк с клавиатуры и вывода их на экран и т.д. Циклы - это основное средство, которое используется для выполнения повторяющихся действий. Поэтому используются они довольно часто, настолько часто, что в наборе инструкций процессора 8086 предусмотрено фактически несколько инструкций циклов: LOOP, LOOPNE, LOOPE и JCXZ.
Давайте рассмотрим сначала инструкцию LOOP. Предположим, мы хотим вывести 17 символов текстовой строки TestString. Это можно сделать следующим образом:
.
.
.DATA
TestString DB 'Это проверка! ...'
..
.CODE
..
mov cx,17
mov bx,OFFSET TestString
PrintStringLoop:
mov dl,[bx] ; получить следующий символ
inc bx ; ссылка на следующий символ
mov ah,2 ; функция DOS вывода на экран
int 21h ; вызвать DOS для вывода символа
dec cx ; уменьшить счетчик длины строки
jnz PrintStringLoop ; обработать следующий символ, если он имеется
.
Есть, однако, лучший способ. Возможно, вспомните, что ранее уже упоминалось о том, что регистр CX весьма полезно бывает использовать для организации циклов. Инструкция:
loop PrintStringLoop
делает то же, что и инструкции:
dec cx
jnz PrintStringLoop
однако выполняется она быстрее и занимает на один байт меньше. Всякий раз, когда вам нужно организовать цикл, пока значение счетчика не станет равным 0, запишите начальное значение счетчика в регистр CX и используйте инструкцию LOOP.
Как же строятся циклы с более сложным условием завершения, чем обратный отсчет значения счетчика? Для таких случаев предусмотрены инструкции LOOPE и LOOPNE.
Инструкция LOOPE работает также, как инструкция LOOP, только цикл при ее выполнении будет завершаться (то есть перестанут выполняться переходы), если регистр CX примет значение 0 или флаг нуля будет установлен в значение 1 (нужно помнить о том, что флаг нуля устанавливается в значение 1, если результат последней арифметической операции был нулевым или два операнда в последней операции сравнения не совпадали). Аналогично, инструкция LOOPNE завершает выполнение цикла, если регистр CX принял значение 0 или флаг нуля сброшен (имеет нулевое значение).
Инструкция LOOPE известна так же, как инструкция LOOPZ, инструкция LOOPNE - как инструкция LOOPNZ, также как инструкции JE эквивалентна инструкция JZ (это инструкции-синонимы).
Имеется еще одна инструкция цикла. Это инструкция JCXZ. Инструкция JCXZ осуществляет переход только в том случае, если значение регистра CX равно 0. Это дает удобный способ проверять регистр CX перед началом цикла.
Относительно инструкций циклов необходимо помнить, во-первых, о том, что инструкции циклов, как и инструкции условных переходов, могут выполнять переход только на метку, отстоящую от инструкции цикла не более чем на 128 байт в ту или другую сторону. Циклы, превышающие 128 байт, требуют использования условных переходов с помощью безусловных переходов (этот метод описан в предыдущем разделе "Условные переходы"). Во-вторых, важно понимать, что ни одна из инструкций циклов не влияет на состояние флагов.
Задание 1 (2 часа)