
Лабораторная работа №2
Цель работы: ознакомление со способами определения данных и изучение механизма передачи управления в программе (циклы и переходы) для операций сравнения.
ОСНОВНЫЕ ПОНЯТИЯ
Определение данных
Сегмент данных предназначен для определения констант, рабочих полей и областей для ввода – вывода. В соответствии с имеющимися директивами в ассемблере разрешено определение данных различной длины. Элемент данных может содержать непосредственное значение или константу, определённую как символьная строка или как числовое значение. Другой способ определения константы – непосредственное значение, т.е. значение, указанное прямо в ассемблерной команде, например:
MOV AL, 20H
В этом случае шестнадцатиричное число 20 становится частью машинного объектного кода. Непосредственное значение ограничено одним байтом или словом, но там, где его можно применять, оно более эффективно, чем использование константы.
Ассемблер обеспечивает два способа определения данных: во-первых, через указание длины данных и, во-вторых, по их содержимому. Основной формат определения данных:
[имя] Dn выражение
• Имя элемента данных не обязательно (это указывается квадратными скобками), но если в программе имеются ссылки на некоторый элемент, то это делается посредством имени.
• Для определения элементов данных имеются следующие директивы: DB, DW, DD, DQ, DT.
• Выражение может содержать константу, например:
FLO1 DB 25,
или знак вопроса для неопределённого значения, например:
FLO2 DB ?
Выражение может содержать несколько констант, разделённых запятыми и ограниченных только длиной строки:
FLO3 DB 11, 12, 13, 14, 15, 16, ….
Ассемблер определяет эти константы в виде последовательности смежных байтов. Ссылка по имени FLO3 указывает на первую константу 11, по FLO3+1 - на вторую, 12. Например, команда
MOV AL, FLO3+4
загружает в регистр значение 14(0ЕН). Выражение также допускает повторение константы в следующем формате:
[имя] Dn число повторений DUP (выражение)
Следующие два примера иллюстрируют повторение:
DW 10 DUP (?) ; Десять неопределённых слов
DB 5 DUP (14) ; Пять байт, содержащих 14.
Выражение может содержать символьную строку или числовую константу. Числовые константы применяются для арифметических значений и для адресов памяти. Для описания числовой константы ковычки не ставятся. Ассемблер преобразует все числовые константы в шестнадцатиричные и записывает байты в объектном коде в обратной последовательности – справа налево. Существуют следующие числовые форматы:
Дсятичный формат. Десятичный формат допускает десятичные цифры от 0 до 9 и обозначается последней буквой , которую можно не указывать, например 125 или 125D, Несмотря на то что ассемблер позволяет кодирование в десятичном формате, он преобразует эти значения в шестнадцатиричный объектный код.
Шестнадцатиричный формат. Шестнадцатиричный формат допускает цифры от 0 до F и обозначается в конце буквой Н. Так как ассемблер полагает, что с буквы начинаются идентификаторы, то первой цифрой шестнадцатиричной константы должна быть цифра от 0 до 9. Например, 2ЕН или 0FFFH ассемблер преобразует соответственно в 2Е и FF0F (байты во втором случае записываются в объектный код в обратной последовательности).
Двоичный формат. Двоичный формат допускает двоичные цифры 0 и 1 и обозначается в конце буквой В. Двоичный формат обычно используется для более чёткого представления битовых значений в логических командах
Восьмиричный формат. Восямиричный формат допускает восьмиричные цифры от 0 до 7 и обозначается последней буквой Q, например 253. На сегодняшний день восьмиричный формат используется редко.
Директива определения байта (DB)
Из различных директив, определяющих элементы данных, чаще используется директива DB. Числовое выражение в директиве DB может содержать одну однобайтовую константу или более. Один байт выражается двумя шестнадцатиричными цифрами. Наибольшее положительное шестнадцатиричное число в одном байте – это 7F, все ”большие„ числа от 80 до FF представляют отрицательные значения.
Директива определения слова (DW)
Директива DW определяет элементы, которые имеют длину в одно слово (два байта). Числовое выражение в DW может содержать одну или более двухбайтовую константу. Два байта представляются четырьмя шестнадцатиричными цифрами. Наибольшее положительное шестнадцатиричное число в двух байтах – это 7FFF; все ”большие„ числа от 8000 до FFFF представляют отрицательные значения.
Директива определения двойного слова (DD)
Директива DD определяет элементы, которые имеют длину в два слова (четыре байта). Числовое выражение в DD может содержать одну или более константу, каждая из которых имеет максимально четыре байта ( восемь шестнадцатиричных цифр). Наибольшее положительное шестнадцатиричное число в четырёх байтах – это 7FFFFFFF; все ”большие„ числа от 80000000 до FFFFFFFF представляют отрицательные значения. Ассемблер преобразует все числовые константы в директиве DD в шестнадцатиричное представление, но записывает объектный код в обратной последовательности.
Директива определения поля из четырёх слов (DQ)
Директива DQ определяет элементы, которые имеют длину четыре слова (восемь байт). Числовое выражение в DQ может содержать одну или более констант, каждая из которых имеет максимум восемь байт или 16 шестнадцатиричных цифр.
Директива определения десяти байт (DT)
Директива DT определяет элементы данных, имеющие длину в десять байт. По директиве DT генерируются различные константы в зависимости от версии ассемблера.
Логика и организация программы.
До этого момента примеры выполнялись последовательно команда за командой. Однако, программируемые задачи редко бывают так просты. Большинство программ содержат ряд циклов, в которых несколько команд повторяются до достижения определенного требования, и различные проверки, определяюшие какие из нескольких действий следует выполнять. Обычным требованием является проверка - должна ли программа завершить выполнение. Эти требования включают передачу управления по адресу команды, которая не находится непосредственно за выполняемой в текущий момент командой. Передача управления может осуществляться вперед для выполнения новой группы команд или назад для повторения уже выполненных команд Некоторые команды могут передавать управление, изменяя нормальную последовательность шагов непосредственной модификацией значения смещения в командном указателе. Ниже приведены три способа передачи управления :
Безусловный переход: JMP
Цикл: LOOP
Условный переход: Jnnn (больше,меньше,равно)
Следует отметить что имеется три типа адресов: SHORT, NEAR и FAR. Адресация SHORT используется при циклах, условных пеpеходах и некоторых безусловных переходах. Адресация NEAR и FAR используется для вызовов процедур (CALL) и безусловных переходов, которые не квалифицируются , как SHORT. Все три типа передачи управления воздействуют на содержимое регистра IP; тип FAR также изменяет регистр CS.
Команда JMP . Одной из команд обычно используемых для передачи управления является команда JMP. Эта команда выполняет безусловный переход, т.е. обеспечивает передачу управления при любых обстоятельствах. В следующей процедуре используется команда JMP. В pегистры AX, BX, и CX загружается значение 1, и затем в цикле выполняются следующие операции:
прибавить 1 к регистру AX,
прибавить AX к BX,
удвоить значение в регистре CX.
Повторение цикла приводит к увеличению содержимого регистра AX: 1,2,3,4..., регистра BX: 1,3,6,10..., и регистра CX: 1,2,4,8... Начало цикла имеет метку, в данном случае, A20: - двоетичие oбозначает, что метка находится внутри процедуры в сегменте кода. В конце цикла находится команда
JMP A20
которая указывает на то, что управление должно быть передано команде c меткой A20. Следует обратить внимание, что адресная метка в операнде команды указывается без двоеточия. Данный цикл не имеет выхода и приводит к бесконечному выполнению - такие циклы обычно не используются.
0100 MAIN PROC NEAR
0100 B8 0001 MOV AX,01 ;Инициализация AX,
0103 BB 0001 MOV BX,01 ; BX,
0106 B9 0001 MOV CX,01 ; и CX
0109 A20:
0109 05 0001 ADD AX,01 ;Прибавить 01 к AX
010C 03 D8 ADD BX,AX ;Прибавить 01 к BX
010У В1 У1 ЫРД СЧб1 жУдвоить СЧ
0110 EB F7 JMP A20 ;Переход на A20
0112 МAIN ENDP
Метку можно кодировать на одной строке с командой:
A20: ADD AX,01
или на отдельной строке:
A20:
ADD AX,0
В обоих случаях адрес A20 указывает на первый байт команды ADD. Двоеточие в метке A20 указывает на тип метки - NEAR. Отсутствие двоеточия в метке является частой ошибкой. В нашем примере A20 соответствует -9 байтам от команды JMP, в чем можно убедиться по объектному коду команды - EBF7. EB представляет собой машинный код для короткого перехода JMP, а F7 - отрицательное значение смещения (-9). Команда JMP прибавляет F7 к командному указателю (IP), котоpый содержит адрес команды после JMP (0112):
Дес. Шест.
Командный указатель: 274 112
Адрес в команде JMP: -9 F7 (двоичное дополнение)
Адрес перехода: 265 109
В результате сложения получается адрес перехода - шест. 109. Проверьте по листингу программы, что относительный адрес метки действительно соответствует шест.109. Соответственно операнд в команде JMP для перехода вперед имеет положительное значение.
Команда JMP для перехода в пределах -128 до +127 байт имеет тип SHORT. Ассемблер генерирует в этом случае однобайтовый операнд в пределах от 00 до FF. Команда JMP, превосходящая эти пределы, получает тип FAR, для которого генерируется другой машинный код и двухбайтовый операнд.
Ассемблер в первом просмотре исходной программы пределяет длину каждой команды. Однако, команда JMP может быть длиной два или три байта. Если к моменту просмотра команды JMP ассемблер уже вычислил значение опеpанда (при переходе назад):
A50:
...
JMP A50
то он генерирует двухбайтовую команду. Если ассемблер еще не вычислил значение операнда (при переходе вперед)
JMP A90
...
A90:
то он не знает тип перехода NEAR или FAR, и автоматически генерирует 3-х байтовую команду. Для того, чтобы указать ассемблеру на необходимость генерации двухбайтовой команды, следует использовать оператор SHORT:
JMP SHORT A90
...
A90:
Команда LOOP. Команда JMP в предыдущем примере реализует бесконечный цикл. Но более вероятно подпрограмма должна выполнять определенное число циклов. Команда LOOP, которая служит для этой цели, использует начальное значение в регистре CX. В каждом цикле команда LOOP автоматически уменьшает содержимое регистра CX на 1. Пока значение в CX не равно нулю, управление передается по адресу, указанному в операнде, и если в CX будет 0, управление переходит на слудующую после LOOP команду.
В следующем примере показана процедура, иллюстрирующая использование команды LOOP, она выполняет действия, аналогичные предыдущему примеру за исключением того, что после десяти циклов программа завершается. Команда MOV инициализирует регистр CX значением 10. Так как команда LOOP использует регистр CX, то в программе для удвоения начального значения 1 вместо регистра CX используется DX. Команда JMP A20 заменена командой LOOP и для эффективности команда ADD AX,01 заменена командой INC AX (увеличение AX на 1).
Аналогично команде JMP, операнд команды LOOP определяет расстояние от конца команды LOOP до адреса метки A20, которое прибавляется к содержимому командного указателя. Для команды LOOP это расстояние должно быть в пределах от -128 до +127 байт. Если операнд превышает эти границы, то ассемблер выдаст сообщение "Relative jump out of range" (превышены границы перехода).
0100 BEGIN PROC NEAR
0100 B8 0001 MOV AX,01 ;Инициализация AX,
0103 BB 0001 MOV BX,01 ; BX,
0106 BA 0001 MOV DX,01 ; и DX
0109 B9 000A MOV CX,10 ;Число циклов
010C A20:
010C 40 INC AX ;Прибавить 01 к AX
010D 03 D8 ADD BX,AX ;Прибавить AX к BX
010F D1 E2 SHL DX,1 ;Удвоить DX
0111 E2 F9 LOOP A20 ;Уменьшить CX и
; повторить цикл, если ненуль
0113 C3 RET ;Завершить работу
0114 BEGIN ENDP