Мы назвали "битом" двоичную цифру, единичное значение 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 байт.
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. Остальные структуры данных используются в программах прежде всего для очень больших чисел в Числовом сопроцессоре или для определения собственных структур данных.