- •2.4. Машинный язык и язык Ассемблера
- •2.5. Синаксис языка Ассемблера
- •2.6. Принципы работы Ассемблера
- •2.7. Биты, байты и слова
- •2.8. Нумерация бит
- •2.9. Набор символов
- •2.10. Принципы работы компьютера
- •2.11. Процедуры
- •2.12. Стек
- •2.13. Прерывания
- •3.1. Модель программирования 8088
- •3.2. Регистры общего назначения
- •3.3. Регистры адресации
- •3.4. Прямая адресация
- •3.5. Вычисление адресов
- •3.6. Адресация через базу и смещение
- •3.8. Байт mod r-m
- •3.9 Физическая адресация
- •3.10. Сегментные регистры
- •3.11. Предназначение сегментов
- •3.12. Оператор Segment
- •3.13. Оператор Assume
- •3.14. Управляющие рагистры
- •3.14.1. Указатель инструкций (ip)
- •3.14.2. Указатель стека
- •3.14.3. Регистр флагов
- •3.14.4. Флаг знака
- •3.14.5. Флаг нуля
- •3.14.6. Флаг четности
- •3.14.7. Флаг переноса
- •3.14.8. Дополнительный флаг переноса
- •3.14.9. Флаг переполнения
- •3.14.10. Флаг захвата
- •3.15. Векторы прерываний
- •Глава 4 - Набор команд микропроцессора 8088
- •4.1. Пересылка данных
- •4.1.1. Команда пересылки
- •4.1.2. Команда замены
- •4.1.3. Команды ввода и вывода
- •4.1.4. Загрузка исполнительного адреса
- •4.1.5. Загрузка указателя
- •4.1.6. Пересылка флагов
- •4.1.7. Перекодировка
- •4.2. Операции со стеком
- •4.3. Передача параметров
2.7. Биты, байты и слова
Мы назвали "битом" двоичную цифру, еденичное значение 0 или 1. Для удобства введем специальные названия для некоторых последовательностей битов. Группу из 8 бит принято называть байтом. Во всей документации IBM и в этой книге о любых 8 битах информации говорится как о байте. Байт заслужил свое собственное имя по нескольким причинам. Элементарная ячейка памяти имеет длину 8 бит. При каждом обращении к паамяти IBM PC для процессора запрашивается ровно 8 бит информации. Как мы увидим позднее, отдельные команды 8088 могут производить арифметические и логические опреации над группами в 8 бит. Байт - наименьшая еденица информации, с которой 8088 может манипулировать непосредственно. 8088 может одной операцией сложить два 8-битовых числа, но не может этого проделать с 4-битовыми. Кроме того IBM PC использует байт для представления одного символа. Используя один байт можно представить 256 (2**8) отдельных элементов, таких, например, как графические символы. В следующем пункте мы рассмотрим набор символов IBM PC.
Поскольку байт является элементом памяти, мы должны иметь средство определения в ней отдельных байтов. Задача ассемблера фактически и будет состоять в определении содержимого памяти для выполнения программы. В основном исходный текст ассемблера состоит из выполняемых инструкций. Но для помещения определенного значения в байт памяти ассемблер располагает специальным механизмом - определением байта (dtfine byte) или псевдокомандой DB. DB не является командой 8088. Это команда ассемблеру поместить в память определенные значения. Псевдокоманда
DB 23
дает ассемблеру задание сохранить десятичное значение 23 в текущий байт памяти. А оператор
DB 1,2,3,4
сохраняет значения от 1 до 4 по четырем последовательным адресам в памяти.
В программах на языке ассемблера оператор DB применяют для определения областей памяти. В предыдущих примерах мы размещали в памяти определенные значения. Это может быть поисковая таблица или информация для перекодировки чисел. Мы составим несколько примеров, в которых используется определенная подобным образом информация. Кроме того встречаются ситуации, когда программе требуется место в памяти для сохранения данных в процессе исполнения. Во время ассемблирования программы содержимое этого участка памяти неизвестно: собственно, это содержимое будет переменным во время исполнения программы. Инструкция
DB ?
сообщает ассемблеру о необходимости выделить один байт памяти, не изменяя его содержимое. В Этом байте может оказаться любое случайное число, которое будет там оставаться пока какая-либо команда не поместит в него определенное значение.
Нам может потребоваться выделить и большое количество байтов, например, чтобы оставить область памяти для массива. Мы можем это сделать так:
DB 25 DUP(?)
Этой инструкцией выделяется 25 байт памяти. Ключевое слово DUP в этой псевдокоманде означает повторить (duplicate). Число 25 указывает, сколько раз ассемблер повторит определение байта в памяти. Значение или значения в скобках ассемблер использует для инициализации этой области памяти. В данном случае это значение неизвестно. Для инициализации области с одним и тем же значением выражение, например,
DB 17 DUP(31)
создает 17 байт со значением 31 каждый. Наконец,
DB 30 DUP(1,2,3,4,5)
выделяет 30 байт со значениями от 1 до 5 в первых пяти байтах. Следующие пять байт тоже имеют значения от 1 до 5 и т.д. Ассемблер повторяет значения в скобках пока не будут заполнены все 30 байт.
Иногда нам хочется обратиться к набору бит меньшему чем байт. Принят размер 4 бит. В 4 битах мы можем представить все 10 десятичных цифр. Для значений такого размера мы будем пользоваться термином "полубайт". Этот термин (в оригинале "nybble" - прим. перев.), который достиг широкого применения, позволяет нам говорить о данных, меньших, чем "байт".
Термин "Слово" имеет для программиста значение отличное от принятого в языке. В применении к ЭВМ слово - это наибольшее количество бит, с которым машина может обращаться как с единым элементом. Для системы IBM/370 слово составляет 32 бит, а для семейства Intel 8088 - 16. Поэтому термин "слово" имеет неопределенный смысл, пока не известна конкретная машина. Размер слова в 8088 составляет 16 бит. Этот размер определяется каналами передачи данных в процессоре. Над числами до 16 бит 8088 может призводить операции одной командой. Любое более крупное число потребует более одной команды. Существуют команды, которые манипулируют и с меньшими объемами памяти, как, например, команда сложения двух 8-битовых чисел. Несколько инструкций позволяют манипулировать и с отдельными битами. Но для сложения двух 32-битовых чисел потребуется уже две команды, складывающие по 16 бит каждая. Наибольшее число над которым мы можем производить элементарные операции типа сложения имеет размер машинного слова.
Аналогично команде определения байта памяти, существует и инструкция для определения слова памяти. Оператор ассемблера DW означает определение слова (define word). Первое утверждение DW на Фиг. 2.10 определяет 16 бит памяти со значением 1234H. Как и в случае с байтами, мы можем использовать оператор DUP для определения больших областей памяти, разбитых на слова. И точно также, для обозначения неинициируемых областей можно использовать операнд "?".
Microsoft (R) Macro Assembler Version 5.00 10/29/88 16:10:44
Фиг. 2.10 Примеры определения слов Page 1-1
1 PAGE ,132
2 TITLE Фиг. 2.10 Примеры определения слов
3
4 0000 1234 DW 1234H
5 0002 0003[ DW 3 DUP(5678H)
6 5678
7 ]
8
9 0008 ???? DW ?
10
11 END
Фиг. 2.10 Примеры определения слов
Одна из обескураживающих черт 8088 - это его манера хранения слов в памяти. На Фиг. 2.10, хоть мы и определяли значение слова как 1234Н, ассемблер сохранит в памяти значение 3412Н, по крайней мере так это выглядит. Посмотрим, как это получается.
Допустим, слово 1234Н сохранено в ячейках 100 и 101. 8088 требует, чтобы ассемблер поместил значение 34Н в ячейку 100, а 12Н - в 101. Легче всего запомнить это так, что ассемблер сохраняет младший байт слова в ячейку памяти с меньшим адресом, а старший байт - с большим. На Фиг. 2.11 показано, содержимое памяти после того, как ассемблер поместит в нее данные. Пока вы не привыкнете к такому методу, вам
Адрес Значение
-------------------------
. .
. .
100 34Н
101 12Н
. .
. .
-------------------------
Фиг. 2.11 Представление в памяти DW 1234H
будет казаться, что все в памяти наоборот. К счастью, если вы не будете смешивать операции над байтами и над словами одной и той же области в памяти, вам незачем беспокоиться об этом неожиданном "переключении" байтов. Программа может спокойно работать со словами, а 8088 всегда разберется что к чему. Только в том случае, если вы захотите обратиться к конкретному байту какого-либо слова, вам придется иметь дело с фактическим способом хранения слов в памяти семейства 8088. Ассемблер обращает внимание на структуру слов в распечатке программы, то есть изображает слова в объектном коде как слова, а не как байты, которые выглядели бы перевернутыми наоборот. Вы сможете различать слова благодаря тому, что ассемблер записывает их шестнадцатеричными цифрами без пробелов.
Однако остался еще один тип данных, который постоянно используется программах на языке ассемблера для микропроцессора 8088. Это - двойное слово, значение в 32 бита длиной. Программы пользуются двойными словами для хранения адресов и очень больших чисел. Чтобы определить область, содержащую значение двойного слова, оператор ассемблера DD значение генерирует поле размером в 4 байта. DD означает операцию выделения двойнго слова (define doubleword). Так же как в случае с DW - опратором, ассемблер размещает в памяти младший байт ниже, а старший - выше. В таком же порядке сохраняются средние два байта. Аналогично операторам DB и DW вы можете пользоваться функцией DUP и применять операнд "?" для того чтобы оставить область неопределенной.
Ассемблер может генерировать и другие структуры данных. Их обсуждение мы отложим, пока не дойдем до некоторых свойств макроассемблера и сопроцессора 8087. Остальные структуры данных используются в программах прежде всего для очень больших чисел в Числовом сопроцессоре или для определения собственных структур данных.