- •Введение
- •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.5. Выражения
Операнды директив, как правило, описываются в виде выражений. Выражения используются и для описания операндов команд.
В целом выражения языка ассемблера похожи на арифметические выражения языка высокого уровня, однако между ними есть и отличия. Наиболее важное отличие заключается в том, что выражения языка ассемблера вычисляются не во время выполнения программы, а во время ее трансляции: встретив в тексте программы выражение, ассемблер вычисляет его и полученное значение (например, число) записывает в машинную программу. Поэтому, когда программа начнет выполняться, от выражений не останется никаких следов. В связи с этим в выражениях языка ассемблера можно использовать только такие величины, которые известны на этапе трансляции (например, адреса и типы имен), и ни в кое случае нельзя использовать величины (например, содержимое регистров или ячеек памяти), которые станут известными лишь во время счета программы.
Вообще говоря, в языке ассемблера для записи операндов директив и команд достаточно только чисел и имен. Более сложные выражения являются лишь удобной формой записи этих чисел и имен. Например, если имеется переменная X размером в слово и нужно описать переменную ТХ, начальным значением которой является тип (размер) этой переменной, то вместо директивы
TX DB 2
лучше использовать эквивалентную ей директиву
ТХ DB TYPE X
поскольку она более универсальна и ее не надо менять, если изменится тип переменной X.
В языке ассемблера выражения делятся на два класса - на константные и адресные, в зависимости от типа их значений. Если значением выражения является целое число, то оно называется константным выражением, а если значением является адрес, то это адресное выражение. Конечно, адрес – это тоже целое число (порядковый номер ячейки в памяти), но по смыслу адреса отличаются от просто чисел, и в языке ассемблера они рассматриваются как самостоятельный тип данных.
Отметим, что выражений иных типов в языке ассемблера нет, однако имеются объекты (например, строки и имена регистров), которые не относятся ни к константным, ни к адресным выражениям, но которые также используются для записи операндов команд и директив.
По структуре и назначению выражения, константные и адресные, можно разделить на простейшие выражения и операторы. Из простейших выражений строятся любые другие выражения. К простейшим выражениям относятся числа, имена констант, имена переменных и т. п. Термином «оператор» в языке ассемблера принято обозначать то, что мы обычно называем функциями и операциями. Операторы языка ассемблера делятся на одноместные (это аналог функций одного аргумента) и двухместные (это аналог бинарных операций); примером может служить TYPE X или А+1. С помощью операторов из простейших выражений строятся более сложные выражения.
О простейших выражениях и операторах будет рассказано далее. Однако уже сейчас следует указать старшинство всех операторов языка ассемблера (в порядке убывания; в каждой строке указаны операторы одного старшинства):
1. (), [ ], LENGTH, SIZE, WIDTH, MASK
2. .
3. :
4. PTR, OFFSET, SEG, TYPE, THIS
5. HIGH, LOW
6. одноместные + и -
7. *, /, MOD, SHL, SHR
8. двухместные + и -
9. EQ, NE, LT, LE, GT, GE
10. NOT
11. AND
12. OR, XOR
13. SHORT, TYPE
Операторы одного старшинства вычисляются слева направо. Например, А+В-С - это (А+В) - С.
Константные выражения
Значениями константных выражений всегда являются 16-битовые целые числа (единственным исключением является директива DD, в которой можно явно указывать 32-битовые числа). При этом, если значением (в математическом смысле) константного выражения является отрицательное число, то в формируемую машинную программу оно записывается в дополнительном коде.
К простейшим константным выражениям относятся:
– число от -215 до 216-1 (числа вне этого диапазона рассматриваются как ошибка);
– символ (значением такого выражения является код символа; например, значением выражения '0' будет число 30h);
– строка из двух символов (значением является число-слово, составленное из кодов этих символов; например, значением выражения '01' будет число 3031h);
– имя константы (значением такого выражения является значение константы; например, если была директива К EQU 10, то значение К равно 10).
Другие простейшие константные выражения будут рассмотрены позже.
Среди константных операторов, т. е. операторов с числовым значением, пока следует отметить уже известный оператор TYPE и следующие арифметические операторы (k, kl и k2 означают любые константные выражения):
– одноместные плюс и минус: +k, -k
– операторы сложения и вычитания: kl+k2, kl-k2
– операторы умножения и деления: kl *k2, kl/k2, kl MOD k2
(* - умножение, / - деление нацело, MOD - взятие остатка от деления)
Пример использования константного выражения с арифметическими операторами:
K EQU 30
X DB (3*K-l)/2 DUP(?) ;массив из 44 байтов
Операндами арифметических операторов должны быть константные выражения. Но здесь есть одно важное исключение: в языке ассемблера разрешается вычитание одного адреса из другого и в результате получается число, а не адрес.
Пример:
X DW 1,2,3,4,5
Y DB ?
SIZE_X EQU Y-X ; SIZE_X = 10
Вычитание адресов используется обычно для определения расстояния (числа бантов) между этими адресами. В нашем случае разность Y-X показывает, сколько байтов занято всеми элементами массива X.
Следует отметить одну особенность арифметических операторов: все они выполняются в области 16-битовых чисел, т. е. от результата всегда берутся только последние 16 битов (остаток от деления на 216, на 10000h), например:
(2*9000h)/100h=(12000h)/100h>2000h/100h=20h(a не 120h)
Адресные выражения
Значениями адресных выражений являются 16-битовые адреса. Все операции над адресами выполняются по модулю 216 (10000h).
К простейшим адресным выражениям относятся:
– метка (имя команды) и имя переменной, описанное в директиве DB,DW или DD (значениями таких выражений являются адреса меток и имен);
– счетчик размещения; он записывается как $ и обозначает адресного предложения, в котором он встретился. При трансляции программы ассемблер следит за тем, в ячейку с каким адресом должен попасть машинный эквивалент очередного предложения программы на языке ассемблера; так вот, если необходимо сослаться на этот адрес, то и надо указать $. Отсюда следует, что в разных предложениях $ обозначает разные адреса. Например, если адрес переменной А равен 100h, то имеем
A DW $ ;эквивалентно A DW 100h
В DW $ ;эквивалентно В DW 102h
Чаше всего счетчик размещения используется для вычисления размера памяти, занимаемой каким-то массивом, например:
X DW 40 DUP(?)
SIZE_X EQU $-X ; SIZE_X = 80
Здесь $ обозначает адрес первого байта за массивом X, из этого адреса и вычитается начальный адрес массива.
Среди операторов, значением которых являются адреса, пока следует отметить лишь операторы сложения и вычитания (a - адресное выражение, k - константное):
сложение адреса с числом: a+k, k+а (значением такого выражения является адрес, полученный прибавлением к адресу a числа k).
вычитание константы из адреса: а-k (значением является адрес а, уменьшенный на величину k).
Адресные выражения вида <имя>±<целое> используются для ссылок на безымянные ячейки памяти (как правило, элементов массивов). Например, если имеются описания
A DB 0,1,2,3
В DB 4
то именованными оказываются только байты со значениями 0 и 4, а остальные элементы массива А оказываются безымянными, поэтому к ним нельзя обратиться по имени. Для доступа к таким безымянным ячейкам в языке ассемблера и используются адресные выражения указанного вида. Например, сослаться на байт со значением 3 можно с помощью выражения А+3 или В-1.
Отметим, что в языке ассемблера запрещено вычитание адреса из числа, не допускается сложение, умножение и деление адресов - все это бессмысленные операции. Однако допускается вычитание адресов, но в этом случае, как мы уже знаем, результатом будет не адрес, а константа.
И еще одно замечание. В языке ассемблера указывать адреса в явном, цифровом, виде нельзя. Если указано число, то оно всегда воспринимается как константа, а не адрес. Если же все-таки надо указать адрес в явном виде, то это делается специальным образом.