назад

Как процессор обменивается данными с памятью

1. Краткие сведения об устройстве памяти

Каждому, кто изучал хотя бы минимальный курс информатики, известно, что все данные и программы их обработки хранятся в компьютере в дискретном двоичном виде. Согласно классическим принципам, минимальной допустимой информацией является 1 бит и именно бит служит основой компьютерной памяти, ее минимальным конструктивным элементом.  В настоящее время благодаря успехам в технологии производства миниатюрных электронных схем сформулированный тезис не имеет столь очевидных (в прямом смысле этого слова!) доказательств, но, тем не менее, своей актуальности не утратил.

Бит слишком маленькая единица информации, чтобы быть достаточной для представления практически полезных данных. Известно, например, что для сохранения одного символа требуется 8 бит, стандартного целого числа – 16, а разрядность целочисленных данных в современных процессорах достигла 32 бит. Следовательно, обеспечивать доступ к каждому отдельному биту памяти едва ли нецелесообразно. Начиная с третьего поколения, в ЭВМ фактически сложился стандарт организации памяти, при котором минимальной считываемой порцией информации является 1 байт. Кроме того, для работы с более крупными данными современные процессоры способны одновременно считывать несколько байт, начиная с заданного (как правило, два или четыре).

Итак, минимальной единицей обмена информацией с памятью в современных компьютерах является 1 байт. Каждый байт имеет свой идентификационный номер, по которому к нему можно обращаться – его принято называть адресом. Адреса соседних байтов отличаются на единицу, зато для двух 32-разрядных чисел, хранящихся в памяти «друг за другом», эта разница по понятным причинам равняется четырем. Практически при обращении к памяти задается адрес начального байта и их требуемое количество (см. 3.3 и 3.2 соответственно).

2. Задание размера данных в команде

В семействе процессоров Intel количество считываемых или записываемых байт определяется кодом машинной инструкции. Учитывая, что первые представители этого семейства имели разрядность 16, и лишь начиная с модели 80386 перешли к 32 разрядам, система задания требуемого количества байт выглядит немного запутано. Так, коды команд обращения к байту или слову (вполне естественным образом) отличаются одним битом. Например, байтовая команда MOV AL,1 имеет код B0 01, а двухбайтовая MOV AX,1 кодируется B8 01 00 (длина команды увеличилась из-за размера константы!); легко убедиться, что коды операций B0 и B8 действительно имеют отличие в единственном бите. Что касается четырехбайтовой команды MOV EAX,1, то код ее операции абсолютно такой же, как и у двухбайтовой команды (только константа 1 еще «длиннее» – 4 байта). Оказывается, что две эти одинаковые по кодам команды процессор различает по установленному режиму: при обработке 32-разрядного участка памяти константа заносится в полный регистр EAX, а 16-разрядного – в его младшую половину AX. Для изменения «режима по умолчанию» служит специальный префиксный код (так называемый префикс переключения разрядности слова, равный 66h), который для следующей за ним инструкции изменяет стандартный режим на противоположный. В результате при работе в 16-разрядном сегменте  код 66 B8 01 00 00 00 реализует именно 32-разрядную операцию записи в EAX единицы.

Примечание. Не пытайтесь проверить данное утверждение путем ввода в Debug команды MOV EAX,1 – к сожалению, отладчик «не понимает» мнемоник, содержащих расширенные регистры!

Таким образом, мы видим, что разрядность команды определяется ее кодом (и, может быть, некоторыми «внешними» по отношению к программе факторами). Полученный вывод позволяет нам в дальнейшем ограничиться рассмотрением методов адресации для данных какой-либо фиксированной длины: для остальных достаточно будет просто написать другой код операции.

3. Задание адреса данных в команде

В предыдущем разделе было показано, что для понимания методов адресации достаточно рассмотреть способы задания начального адреса при фиксированной длине данных. Поэтому в дальнейшем мы везде будем полагать, что данные имеют двухбайтовый размер. Для упрощения понимания идей адресации в большинстве примеров ограничимся также одной (самой простой!) инструкцией переписи данных, которая имеет мнемоническое обозначение MOV. Подчеркнем, что принятые допущения нисколько не ограничат общности наших знаний по описываемому вопросу.

Итак, перейдем к рассмотрению основных принципов обращения к данным, принятых в компьютерах семейства IBM PC на базе процессоров фирмы Intel.

3.1. Адресация простых данных

Под простыми данными принято понимать такие, которые хранят в себе только одно значение, например, целое число. Сложные данные, напротив, включают в себя несколько значений, причем даже не обязательно одного типа; простейшим примером «однородных» сложных данных является массив, о котором мы будем говорить позднее. Не следует путать сложные структуры, состоящие из нескольких более простых значений, в частности из набора целых чисел, с простыми данными, занимающими в памяти нескольких байт, например, с отдельно взятым 32-разрядным целым числом.

Будем пока рассматривать адресацию простых данных. Как выбрано выше, это будут целые 16-разрядные числа.

Простейшие и очень часто используемые инструкции обработки данных, которые выполняются в регистрах микропроцессора, настолько естественны, что легко понимаются на интуитивном уровне. В частности, речь идет о случаях, когда в регистр заносится копия содержимого другого регистра (MOV AX,BX) или константа (MOV AX,30). Тем не менее, с теоретической точки зрения это уже простейшие методы адресации данных, которые для процессоров семейства Intel принято называть регистровой и непосредственной адресацией соответственно.

Чуть более сложным является случай, когда данные извлекаются из конкретной ячейки памяти, например, MOV AX,[30]; такой метод получил название прямой адресации. Приведенная в качестве примера команда считывает из памяти два байта начиная с адреса 30 и помещает их в 16-разрядный регистр AX. Обязательно обратите внимание на наличие в записи квадратных скобок, которые всегда появляются при ссылке на содержимое памяти.

Подобно тому, как заключение в квадратные скобки константы приводит нас к появлению прямой адресации, аналогичный прием для регистра (например, MOV AX,[BX]) также порождает новый (и очень важный!) метод адресации – косвенный регистровый. Его суть заключается в том, что содержимое регистра рассматривается не как данные, а как адрес памяти, где эти данные расположены.

Для понимания сущности косвенной адресации можно рассмотреть следующую аналогию: при подготовке к экзамену ученик открывает свой конспект по требуемой теме, а там вместо текста для ответа видит запись: «материал по этому вопросу прочитать в § 25». Иными словами, вместо готовой информации дается ссылка на нее.

Или еще одна аналогия из книги: «косвенная адресация похожа на операцию "для передачи (кому-то)", выполняемую почтовой службой США, когда указанный адрес не является реальным адресом получателя, а является адресом друга или родственника».

Чтобы закрепить четыре изученных метода адресации, рассмотрим несложный пример, который складывает два целых числа с адресами 200 и 204. Его выполнение зафиксировано в протоколе 1 и состоит из нескольких действий: ввод программы (команда a) и ее вывод для контроля набора (u); ввод (e200) и вывод чисел (d200); контроль состояния регистров до выполнения программы (r); пошаговое выполнение четырех команд с выводом значений регистров после каждого шага (t4).

Надеемся, что вы без труда самостоятельно разберут приводимый протокол 1 и повторят соответствующий диалог в Debug. Не забудьте только о цели эксперимента – поработать с четырьмя различными способами адресации. Поэтому при анализе программы обязательно обратите внимание на то, какие методы использованы в каждой из команд.

Протокол 1


-a
1423:0100 mov ax,[204]
1423:0103 mov bx,200
1423:0106 mov cx,[bx]
1423:0108 add ax,cx
1423:010A
-u
1423:0100 A10402        MOV     AX,[0204]
1423:0103 BB0002        MOV     BX,0200
1423:0106 8B0F          MOV     CX,[BX]
1423:0108 01C8          ADD     AX,CX
1423:010A 0000          ADD     [BX+SI],AL
...
-e200 5 0 0 0 3 0
-d200

1423:0200  05 00 00 00 03 00 00 00-00 00 00 00 00 00 00 00   ................
...
-r
AX=0000  BX=0000 CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1423 ES=1423  SS=1423  CS=1423  IP=0100   NV UP EI PL NZ NA PO NC
1423:0100 A10402        MOV     AX,[0204]                         DS:0204=0003
-t4

AX=0003 BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1423 ES=1423  SS=1423  CS=1423  IP=0103   NV UP EI PL NZ NA PO NC
1423:0103 BB0002        MOV     BX,0200

AX=0003  BX=0200 CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1423 ES=1423  SS=1423  CS=1423  IP=0106   NV UP EI PL NZ NA PO NC
1423:0106 8B0F          MOV     CX,[BX]                           DS:0200=0005

AX=0003  BX=0200 CX=0005  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1423 ES=1423  SS=1423  CS=1423  IP=0108   NV UP EI PL NZ NA PO NC
1423:0108 01C8          ADD     AX,CX

AX=0008 BX=0200  CX=0005  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1423 ES=1423  SS=1423  CS=1423  IP=010A   NV UP EI PL NZ NA PO NC
1423:010A 0000          ADD     [BX+SI],AL                        DS:0200=05

Примечание. В очередной раз напоминаем, что по принятому в IBM PC соглашению байты данных хранятся в памяти «задом наперед», т.е. байты 05 00 следует расшифровывать как 0005.

Задание
Составить и  реализовать в Debug свою программу (аналогичную протоколу 1) в соответствии с вариантом таблицы 1

Таблица 1