Адресация и ввод/вывод в программе на
Ассемблере
Работа с данными, находящимися в оперативной памяти составляет основу разработки программ на языке ассемблера. Для определения адреса данных необходимо
хорошо знать способы адресации. Адрес оперативной памяти
состоит из двух частей: адреса сегмента и смещения относительно начала
сегмента. Адрес начала сегмента записан в сегментном регистре(SS, DS, CS. ES), значение
смещения в одном из индексных или базовых регистров, как правило, это регистры BX, DI, SI, SP, BP.
В программах на языке ассемблера применяются следующие типы адресации операндов: регистровая, прямая, непосредственная, косвенная, базовая, индексная, базово-индексная, косвенная адресация с индексированием, базово-индексная с масштабированием.
Регистровая адресация
подразумевает использование в качестве операнда регистра, например:
mov BP, SP
При прямой адресации один операнд
представляет собой адрес памяти, второй - регистр:
mov DATA, AX
Непосредственной адресацией называется случай, когда программист записывает число в регистр :
mov AX, 4C00h
При использовании косвенной адресации адрес записан в одном из
сегментных регистров, а значение смещения в одном из индексных регистров BX, BP, SI или DI, например:
mov AL, [BX]; значение сегмента записано в регистре DS, смещение в регистре BX
mov AH, [SI]; сегмент - в DS, смещение - в SI
mov AX, [DI]; сегмент в DS, смещение - в DI
mov AX, ES: [DI]; сегмент - в ES, смещение - в DI
mov DX, SS:[BP]; сегмент - в SS, смещение - в BP
В случае применения базовой адресации,адрес является суммой значения смещения и содержимого
регистра BP или BX, например:
mov AX, SS:[BP+6]; сегмент - SS, смещение - значение BP, которое складывается с 6
mov [BX+Delta], AX; сегмент - DS, смещение - значение BX+смещение Delta
mov AX, [BP]+4; сегмент - SS, смещение - значение BP+4
mov DX, 8+[BX]; сегмент - DS, смещение
- значение BX+8
При индексной адресации адрес определяется как сумма значений указанного смещения и
содержимого регистра SI или DI так же, как и при базовой адресации, например:
mov DX, [SI+5]; сегмент - DS, смещение - SI+5
mov ES:[DI]+6, AL;сегмент - ES, смещение - DI+6
Базово-индексная адресация
подразумевает использование для вычисления адреса суммы
содержимого базового и индексного регистров, например:
mov BX, [BP+SI]
mov
ES:[BX+DI], AX
Косвенная адресация с индексированием подразумевает использование для вычисления адреса суммы базы, которая находится в базовом или индексном регистре и индекса элемента массива, например:
mov Array[BX+SI+2], 12h
mov AX, [BP+6+DI]
Базово-индексная адресация с масштабированием подразумевает использование для вычисления адреса суммы содержимого базового и индексного регистра, умноженного на размер элемента массива например:
mov Array[BX+SI*4], 0Ah
Девять флагов записаны в регистре флагов. Флаги имеют следующие значения:
1. Бит 0, флаг переноса
CF (carry flag). Установлена 1, если при выполнении арифметической операции регистр был переполнен и необходим перенос.
2. Бит 2, флаг четности PF (parity flag). Если установлена 1, то результат операции - чётное число.
3. Бит 4, вспомогательный флаг переноса
AF (auxiliary carry flag).
4. Бит 6, флаг нуля ZF (zero flag). Установлена 1, если результат арифметической или логической операции - 0.
5. Бит 7, флаг знака SF (sign flag). Установлена 1, если результат арифметической или логической операции - отрицательное число.
6. Бит 8, флаг трассировки TF (trap flag)
7. Бит 9, флаг прерывания IF (interrupt enable flag). Разрешает прерывания от внешних устройств, если установлен 0 - прерывания запрещены.
8. Бит 10, флаг направления DF (direction flag). Используется при строковых операциях, задаёт направление индексирования массива.
9. Бит 11, флаг переполнения OF (overflow flag). Флаг переполнения, установлен, если в результате логической или арифметической операции регистр был переполнен.
Обработка массивов обычно выполняется в цикле. Кроме
того, в программе часто необходимо выполнять многократно некоторые фрагменты
программы. Для этого в Ассемблере имеется удобное решение организации циклов.
Количество повторений цикла заносится в регистр СХ, а команда LOOP обеспечивает
выполнение заданного количества повторений. Как правило, команда LOOP ставится в конце повторяющейся
последовательности команд программы.
Loop метка
Команда вычитает единицу из содержимого регистра CX и, если содержимое не равно нулю,
передает управление на метку. Если регистр
CX становится равен нулю,
выполняется следующая за LOOP инструкция. В регистр СХ записывается количество
повторений цикла.
Например: сложить
десять чисел, которые
находятся в таблице
с именем TAB.
Mydata segment
Tab DB 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ;значения элементов массива Mydata ends
Mycode segment
. . .
MOV CX, 10d ;количество повторений
MOV SI, 0 ;ноль в индексный регистр
MOV BL, 0 сумма будет в BL
BEGIN:
ADD BL, byte ptr DS:[SI] ;добавляем элемент
к сумме
INC SI ;переходим к следующему элементу
LOOP BEGIN ;возврат на начало цикла
. . .
Mycode ends
Команда сравнения
CMP операнд1, операнд2
Команда вычитает операнд2 из операнда1 и устанавливает регистры
флагов.
Операнды не меняются. За ней обычно
идет команда условного
перехода.
В Ассемблере имеется группа команд условного перехода, которые
проверяют состояние флагов в регистре флагов:
Команда проверки состояния флага переноса
JC перейти
если флаг CF установлен в единицу (например, при сдвиге бита из регистра)
JZ перейти, если флаг ZF установлен в единицу (например, результат операции равен нулю
JS перейти,
если флаг SF установлен в единицу (проверяет только старший бит байта или
слова)
JP перейти, если флаг PF установлен в единицу (в результате операции
количество единиц четно
JO перейти, если флаг ОF установлен в единицу (операция
завершилась переполнением)
Флаги, на которые реагирует команда
JE/JZ переход если резултат равен.нулю ZF JNE/JNZ переход
если не равно./.не нуль ZF
JA/JNBE
если выше/ не ниже или равно ZF,CF JAE/JNB если выше или равно/ не ниже CF
JB/JNAE если ниже/не
выше или равно CF
JBE/JNA если ниже или равно/не выше CF, AF
JE/JZ если равно/нуль ZF
JNE/JNZ если не равно/не
нуль ZF
JG/JNLE больше/не меньше или равно ZF,SF,OF
JGE/JNL больше или равно/не меньше SF,OF
JL/JNGE меньше/не больше или равно SF,OF
JLE/JNG меньше или равно/не больше ZF,SF,OF
JMP метка
Передает управление по адресу (метка, адресация).
Устанавливают флаги PF, SF,
ZF
Команда AND получатель, отправитель (логическое умножение). Побитно выполняет операцию
логического умножения над источником и приемником. Если оба обрабатываемых бита
равны 1, результат 1, иначе 0. Как правило, операция применяется для обнуления
заданных в операнде битов или для выделения части битов кода.
Например, необходимо убрать признак кода ASCII в
введенной с клавиатуры цифре. Тогда
MOV AH, 1 Введем с
клавиатуры
INT 21H Цифру по прерыванию 21Н в регистр
AL
AND AL, 00001111BУдалим признак
кода ASCII (т.е. старшие
4 бита)
Команда OR
получатель, отправитель (логическое сложение). Побитно складывает биты в
операндах. Если хотя бы один из пары обрабатываемых битов равен 1, то результат
1, иначе 0. Обычно используется для установки заданных битов в 1.
Например, надо добавить признак
кода ASCII в выводимую на экран цифру.
Тогда
MOV DL, 7 В регистре DL получаем
двоичную семерку
OR DL, 00110000B и добавляем к ней признак ASCII (т.е. в старшие 4 бита)
Команда XOR
получатель, отправитель (сложение по модулю 2). Побитно складывает биты
операндов (но переноса в старший бит нет). Если оба бита одинаковых, результат
0, иначе 1. Обычно используется для изменения заданных битов в обратное
состояние. Например, изменим значения старших
4 битов на обратные. Тогда
MOV AL, 7BH В AL комбинация 01111011
XOR AL, 11110000B После операции в AL 10001011
Команда
TEST источник, приемник. Аналогична команде AND, но не изменяет операнды, а только флаги ZF, SF, PF. Идущая после этой команды команда условного перехода
определяет, каков был результат.
Команда SHR dest, 1 или SHR dest, CL
(Сдвиг вправо). Последний сдвигаемый бит помещается во
флаг CF.
Команда SHL dest, 1 или SHL dest,
CL (Сдвиг влево). Последний сдвигаемый бит помещается во флаг CF.
Команды сдвига обычно
используются для анализа
состояния байта или
слова.
Для реализации заданий
можно воспользоваться программой ввода/вывода, приведенной в приложении 1.
1. Задана
последовательность символов, заканчивающаяся точкой. Подсчитать количество
битов в состоянии 0 для каждого символа. Создать новый массив, который содержит
эти значения для каждого символа. Выведите на экран символ, его двоичное
представление и количество битов в состоянии 1.
2. Задан
массив из 50 слов. Первое число массива содержит действительное количество
чисел в массиве. В каждом слове находятся два числа: одно в битах 14, 13, 12,
11, 10, второе в битах 8, 7, 6, 5, 4, 3. Если
бит 1 в слове неравен 0, то умножить эти два числа и поместить произведение в
новый массив. Выведите на экран числа и произведения.
3. Задан
массив из 30 слов. В каждом слове находятся два числа: одно в битах 14, 13, 12,
11, 10, второе в битах 8, 7, 6, 5, 4, 3. Если
бит 14 и бит 13 в первом числе совпадают с битами 8 и 7 второго числа, то
поместить их в два разных массива.
4. Задан
массив из 40 слов. В каждом слове находятся два числа: одно в битах 12, 11, 10,
9, 8, второе в битах 7, 6, 5, 4, 3, 2. Если бит 9 и бит 8 в первом числе
совпадают с битами 3 и 2 второго числа, то поместить первое число в новый
массив.
5. Задано
слово и массив из 32 чисел форматом слово. Каждому биту слова соответствует
пара чисел из массива: первому биту слова соответствуют числа 1 и 2 из массива,
второму биту - числа 3 и 4, и т.д. Если бит слова равен 1, умножить
соответствующую пару чисел и, если произведение больше слова, поместить его в
новый массив.
6. Задана таблица:
TABL DB 0, 2, 4, 9, 0, 12, 8
DB 5, 12, 7, 0, 8, 0, 5
DB 0, 5, 14, 6, 15, 9, 0
DB 13, 5, 18, 45, 3, 9, 11
Подсчитать количество нулей в каждой строке и
запомнить их в массив. Заменить нули на число FFH. Выведите количество нулей в
каждой строке на экран. Если нулей в строке не обнаружено, то вывести на экран
символ ?.
7. Задан
массив из 50 байтов. Первый байт содержит следующую информацию: биты 7, 6, 5,
4, 3 содержат число, означающее
реальное количество элементов массива, которое необходимо обработать, во втором
байте: биты 7, 6, 5 - константу С1,
биты 4, 3, 2, 1, 0 - константу С2.
Если числа массива (начиная с третьего) больше
230, умножить его на С1, иначе на С2. Все произведения (слова!) поместить в новый массив.
8. Задан
массив из 40 слов. В каждом слове находятся два числа: одно в битах 14, 13, 12,
11,10, второе в битах 8, 7, 6, 5, 4. Если бит 11 и бит 10 в первом числе
совпадают с битами 5 и 4 второго числа, то числа поместить в два разных
массива.
9. Задано
слово и массив из 16 чисел форматом слово. Каждому биту слова соответствует
число из массива. Если бит в слове равен
1, то соответствующее слово из
массива разделить на 10. Ненулевые остатки от деления поместить в новый массив
и вывести на экран.
10. 6. Задана таблица:
TAB DB 5, 2, 0, 9, 11, 16, 7
DB 5, 12, 7, 0,
8, 0,
9
DB 5, 0, 14, 6, 15, 9, 31
DB 13, 5, 18, 45, 3, 9, 45
Числа больше 10 заменить на 9. Вывести на экран
количество таких чисел в каждой строке и запомнить их в новый массив
11. Задан текст
из 100 символов, содержащий слова произвольной длины. Слова в тексте разделены
пробелами. Создать новый массив, в который поместить количества букв в каждом
слове. Вывести на экран количество слов в тексте.
12. Задан текст
из 100 символов, содержащий слова произвольной длины. Слова в тексте разделены
пробелами. Создать новый массив, в который поместить количества букв в каждом
слове. Вывести на экран все слова текста, каждое с новой строки.