- •Введение
- •1. Особенности персонального компьютера
- •1.1. Оперативная память
- •1.2. Регистры
- •1.3. Представление данных
- •1.4. Представление команд
- •2. Язык ассемблера. Начальные сведения
- •2.1. Лексемы
- •2.2. Предложения
- •2.3. Директивы определения данных
- •2.4. Директивы эквивалентности и присваивания
- •2.5. Выражения
- •3. Пересылки. Арифметические команды
- •3.1. Обозначения операторов команд
- •3.2. Команды пересылки
- •3.3. Команды сложения и вычитания
- •3.4. Команды умножения и деления
- •3.5. Изменение размера числа
- •3.6. Примеры
- •3.7. Лабораторная работа № 1
- •4. Переходы. Циклы
- •4.1. Безусловный переход
- •4.2. Команды сравнения и условного перехода
- •4.3. Команды управления циклом
- •4.4. Вспомогательные операции ввода-вывода
- •4.5. Массивы
- •4.6. Лабораторная работа № 2
- •5. Программные сегменты
- •5.1. Сегментирование адресов в пк
- •5.2. Программные сегменты
- •5.3. Начальная загрузка сегментных регистров
- •5.4. Структура программы
- •6. Стек
- •6.1. Стек и сегмент стека
- •6.2. Стековые команды
- •6.3. Приемы работы со стеком
- •7. Процедуры
- •7.1. Дальние переходы
- •7.2. Подпрограммы-процедуры
- •7.3. Передача параметров через регистры
- •7.4. Передача параметров через стек
- •7.5. Локальные данные процедур
- •7.6. Лабораторная работа № 3
- •8. Ввод и вывод данных
- •8.1. Реализация основных операций ввода-вывода
- •8.2. Операции ввода-вывода
- •8.3. Пример структуры программы
- •Заключение
- •Библиографический список
- •Оглавление
- •Учебное издание
- •394026 Воронеж, Московский просп., 14
2.4. Директивы эквивалентности и присваивания
Было рассмотрено, как в языке ассемблера описываются переменные. Теперь рассмотрим, как в этом языке описываются константы. Это делается с помощью директивы эквивалентности – директивы EQU (equal, равно), имеющей следующий синтаксис:
<имя> EQU <операнд>
Здесь обязательно должно быть указано имя, должен быть и операнд, причем только один.
Эта директива аналогична описанию константы в языке Паскаль:
const <имя> = <операнд>
Директивой EQU автор программы заявляет, что указанного операнду он дает указанное имя, и требует, чтобы все вхождения этого имени в текст программы ассемблер заменял на этот операнд. Например, если есть директива
STAR EQU '*'
то ассемблер будет рассматривать предложение
Т DB STAR
как предложение
T DB '*'
Другими словами, указать имя STAR и указать '*' – это одно и то же. Отметим, что директива EQU носит чисто информационный характер, по ней ассемблер ничего не записывает в машинную программу. Поэтому директиву EQU можно ставить в любое место программы - и между командами, и между описаниями переменных, и в других местах.
Теперь рассмотрим, каким может быть операнд директивы EQU и в каких случаях полезна эта директива.
Операнд - имя
Если в правой части директивы указано имя регистра, переменной, константы и т. п., тогда имя слева объявляется синонимом данного имени и все последующие вхождения в текст программы этого имени-синонима ассемблер будет заменять на имя, указанное справа. Например:
A DW?
В EQU A
С DW В ; эквивалентно: С DW A
Имена-синонимы обычно используются для введения более удобных, наглядных обозначений. Например, само по себе имя регистра АХ ни о чем не говорит, но если мы используем этот регистр для вычисления какой-то суммы, то его можно обозначить SUM:
SUM EQU AX
и далее использовать это более наглядное имя SUM.
Отметим, что имя, указанное в правой части директивы EQU, может быть описано в программе как до этой директивы, так и после нее.
Операнд – константное выражение
Примеры:
N EQU 100
К EQU 2*N-1
STAR EQU '*'
Если в правой части директивы EQU стоит константное выражение, тогда указанное слева имя принято называть именем константы. Значением этой константы объявляется значение выражения. Например, N - это константа со значением 100, К – со значением 199, a STAR – со значением 2Ah (это код звездочки в системе ASCII). Все последующие вхождения в текст программы имени константы ассемблер будет заменять на значение этой константы. Например, директива
X DB N DUP (?)
эквивалентна директиве
X DB 100 DUР (?)
Случаи, когда полезно применение констант, - такие же, как и в языках высокого уровня. Например, в качестве констант рекомендуется описывать размеры массивов, поскольку в таком случае легко настроить программу на работу с массивом другого размера – для этого достаточно внести изменение лишь в директиву EQU, описывающую константу.
Отметим, что если в константном выражении используются имена других констант, то они должны быть описаны раньше данной директивы EQU, иначе ассемблер, просматривающий текст программы сверху вниз, не сможет вычислить значение этого выражения.
Операнд – любой другой текст
Примеры:
S EQU 'Вы ошиблись'
LX EQU X+(N-1)
WP EQU WORD PTR
В данном случае считается, что указанное имя обозначает операнд в том виде, как он записан (операнд не вычисляется). Именно на этот текст и будет заменяться каждое вхождение данного имени в программу. Например, следующие предложения слева эквивалентны предложениям справа
ANS DB S, '!' ANS DB 'Вы ошиблись', '!'
NEG LX NEG X+(N-1)
INC WP [BX] INC WORD PTR [BX]
Такой вариант директивы EQU обычно используется для того, чтобы ввести более короткие обозначения для часто встречающихся длинных текстов. После ввода короткого имени, далее в программе можно им пользоваться, а уж ассемблер сам будет его заменять на соответствующий текст.
Следует отметить, что текст, указанный в правой части директивы EQU, должен быть сбалансирован по скобкам и кавычкам и не должен содержать вне скобок и кавычек символа ";". Кроме того, поскольку текст не вычисляется, то в нем можно использовать как имена, описанные до этой директивы EQU, так и имена, описанные после нее.
Теперь рассмотрим еще одну директиву языка ассемблера, похожую на директиву EQU, - директиву присваивания:
<имя> = <константное выражение>
Эта директива определяет константу с именем, указанным в левой части, и с числовым значением, равным значению выражения справа. Но в отличие от констант, определенных по директиве EQU, данная константа может менять свое значение, обозначая в разных частях текста программы разные числа. Например:
K=10
A DW К ;эквивалентно: A DW 10
К=К+4
В DB К ;эквивалентно: В DB 14
Подобного рода константы можно использовать, например, ради «экономии имен»: если в разных частях текста программы используются разные константы и области использования этих констант не пересекаются, тогда, чтобы не придумывать новые имена, этим константам можно дать одно и то же имя (другими словами, поменять значение константы с таким именем). Однако главное применение таких констант – в макросредствах.
Если с помощью директивы EQU можно определить имя, обозначающее не только число, но и другие конструкции, то по директиве присваивания можно определить только числовую константу. Кроме того, если имя указано в левой части директивы EQU, то оно не может появляться в левой части других директив (его нельзя переопределять). А вот имя, появившееся в левой части директивы присваивания, может снова появиться в начале другой такой директивы (но только такой!). Поэтому ошибочными являются все следующие три фрагмента программы:
К EQU 1 К EQU 1 К=1
К EQU 2 К=2 К EQU 2
Появление в языке констант, которые могут менять свои значения, вносит некоторую неопределенность. Рассмотрим, к примеру, фрагмент слева:
K=1 К=1
N EQU К N EQU К+10
A DW N ;А=1 С DW N ; С=11
К=2 К=2
В DW N ;В=2 D DW N ;D=11
Какие начальные значения получат переменные А и В? Относительно значения переменной А сомнений нет – это 1. Но вот значением переменной В, оказывается, будет число 2, а не 1. Почему? Дело в том, что имя N объявлено синонимом имени К, поэтому все вхождения имени N ассемблер будет заменять на имя К. Значит, директива В DW N понимается как директива В DW К. Но в этом месте текста программы константа К имеет значение 2, поэтому данная директива воспринимается как В DW 2.
В то же время в примере справа переменные С и D получат одно и то же значение 11. Дело в том, что в директиве EQU указано, так сказать, настоящее константное выражение, и потому ассемблер вычисляет его сразу. Значение 11 этого выражения объявляется значением константы N, которая далее и будет обозначать это число.
Таким образом, необходимо внести следующее уточнение в действие директивы EQU: если в правой части директивы указано имя константы, то имя слева надо понимать не как имя константы (не как имя числа), а как синоним имени справа; если же в правой части указано любое другое константное выражение, тогда имя слева действительно становится именем константы (обозначением числа). Что же касается директивы присваивания, то ее правая часть всегда вычисляется сразу и полученное число тут же становится новым значением константы.