Найти в Дзене
Разумный мир

Архитектура ЭВМ. Адресация и адресуемость

Оглавление

Мы достаточно подробно рассмотрели вычислительное ядро процессора, на уровне логических схем, и даже добавили специфические узлы для возможности реализации стековой архитектуры на базе ядра регистровой архитектуры. При этом предыдущая статья

Архитектура ЭВМ. Немного практики проектирования ядра процессора
Разумный мир10 июля 2023

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

Сегодня мы займемся поиском ответов на некоторые вопросы связанные с адресацией операндов. То есть, с получением доступа к операндам. Это касается и сигналов Addr_A и Addr_B, в том числе.

Адресуемость

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

Таким образом, память является множеством ячеек, каждая из которых имеет атрибуты: адрес и значение. Над каждой ячейкой можно выполнять одну из двух операций: чтение (получение значения) или запись (установка значения). Все иные операции являются производными от этих двух базовых или их комбинацией. Сегодня нас не будут интересовать конкретные операции с памятью, мы будем оперировать лишь обобщенной операцией "доступ".

Для получения доступа (выполнения операции доступ) к ячейке памяти нам сначала нужно указать адрес. Адрес ячейки в нашем блоке регистров, номер регистра, задают сигналы Addr_A и Addr_B. Откуда берется адрес ячейки внешней памяти мы пока не рассматривали, но сегодня рассмотрим.

  • Возможность указать (задать) адрес ячейки памяти, для получения доступа к ней, само наличие у ячейки адреса, называется адресуемостью.

Определение простое, но, как это всегда бывает, дьявол кроется в деталях. В нашем блоке регистров каждая ячейка (каждый регистр) имеет адрес, который может быть указан явно соответствующим сигналом Addr. То есть, все регистры являются адресуемыми. Причем в явном виде. Но так бывает не всегда.

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

Другими словами, аккумулятор в процессоре аккумуляторной архитектуры не является адресуемым. Не являются адресуемыми и ячейки аппаратного стека в процессоре стековой архитектуры. Отсутствие адресуемости не означает, что ячейки недоступны! Это очень важно понимать. Просто работа я не адресуемыми ячейками осуществляется по другому. Давайте разбираться.

Аккумулятор является регистром, набором триггеров. Для регистра, как и для триггера, операции выполняются с помощью служебных сигналов. Служебные сигналы могут быть разными, я приведу лишь один обобщенный пример

Регистр с набором сигналов данных и служебных сигналов. Иллюстрация моя
Регистр с набором сигналов данных и служебных сигналов. Иллюстрация моя

Такой регистр (не обязательно аккумулятор) не имеет адреса. Для работы с ним необходимо использовать сигнал CS. Обратите внимание, что сигнал CS является сигналом выбора, а не адресным сигналом. И этот сигнал существует лишь на уровне схемотехники. И логики. Почему он не является адресным? Например, он может использоваться для выделения временнОго окна, когда постоянно присутствующие на других выводах сигналы действительно могут воздействовать на регистр.

Если с регистром все понятно, то с регистровой памятью (набором регистров) все сложнее. Набор регистров, в виде одной микросхемы или функционального блока, неизбежно имеет входы адреса

Регистровая память с сигналами данных, адресными сигналами, служебными сигналами. Иллюстрация моя
Регистровая память с сигналами данных, адресными сигналами, служебными сигналами. Иллюстрация моя

Таким образом, с точки зрения схемотехники (что очень важно!), регистры в такой регистровой памяти являются адресуемыми. Но если мы используем такую регистровую память для построения аппаратной стековой памяти, эта адресуемость остается на нижнем уровне, а на более высоких уровнях адресуемости не будет

Блок стековой памяти построенный на базе регистровой памяти. Адресуемость ячеек на верхнем уровне, уровне стековой памяти, отсутствует. Иллюстрация моя
Блок стековой памяти построенный на базе регистровой памяти. Адресуемость ячеек на верхнем уровне, уровне стековой памяти, отсутствует. Иллюстрация моя

Блок стековой памяти я обвел пунктирной рамкой. Хорошо видно, что внутренняя логика такого блока памяти маскирует адресуемость отдельных ячеек регистровой памяти, с точки зрения внешнего мира.

Таким образом, говоря об адресуемости нужно уточнять, о каком именно уровне идет речь. Мы рассматриваем архитектуру ЭВМ, точнее, пока архитектуру процессора. И с этой точки зрения адресуемостью является возможность указания адреса ячейки памяти, включая адрес внутренних регистров, в машинных командах. Именно адрес в коде команды, а не просто упоминание регистра в мнемонической записи команды.

Адресность

Понятие адресности полностью отличается от понятия адресуемости, хоть и термин звучит очень похоже.

  • Адресность это количество адресов отдельных ячеек памяти (включая регистры), которое можно использовать в одной машинной команде.

В большинстве случаев в коде машинных команд можно указывать от нуля до трех различных адресов. Машинные команды, код которых не содержит ни одно явно указанного адреса называются безадресными или нуль-адресными. Безадресными командами является большинство команд стекового процессора, за исключением PUSH и POP. Например, стековая команда ADD является именно безадресной, хоть и работает с двумя верхними ячейками стека. Адреса этих ячеек нельзя задать явно, для получения доступа к ним используется регистр SP, который на последней иллюстрации реализован на базе счетчика CT.

Менее очевидно, что безадресной является, например, команда очистки (установки хранящегося в регистре значения равным нулю)

CLR A

ведь в ее мнемонической записи явно указан регистр-аккумулятор. Но в двоичном коде этой команды нет поля адреса. Что можно показать с помощью другой мнемонической записи

CLRA

Мнемоническая запись предназначена для человека, а не машины. И с точки зрения процессора оба эти варианта мнемонической записи абсолютно идентичны и соответствуют одной и той же команде, которая состоит только из кода команды без дополнительного поля адреса. Напомню, что в аккумуляторной архитектуре аккумулятор не является адресуемым.

Одноадресные команды требуют (именно требуют, а не позволяют!) указывать кроме кода команды еще и адрес одного операнда, одной ячейки памяти. Примеры одноадресных команд:

LDA mem

CLR R1

PUSH mem

Обратите внимание, что первая и третья команды выполняют операции с двумя операндами, один из которых задан неявно и по этой причине не требует указания адреса. Команда LDA неявно использует аккумулятор в качестве предопределенного второго операнда. При этом команда PUSH в качестве второго операнда использует одну из ячеек стека, адрес которой совсем не является предопределенным (задается содержимым SP). Команда CLR, в качестве адреса единственного операнда, использует номер регистра, но мы помним, что номер регистра в блоке регистров тоже является адресом ячейки в блоке регистровой памяти.

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

ADD R1, R2

ADD mem, R1

ADD mem_1, mem_2

Обратите внимание, адрес операнда может быть как адресом ячейки внешней памяти, так и номером (адресом!) внутреннего регистра. Так же обратите внимание, что адресность два означает лишь количество указываемых адресов операндов и не имеет никакого отношения к понятиям источник и приемник.

Трехадресные команды являются гораздо более редкими, если говорить о массовых процессорах. Я не буду приводить примеры таких команд, здесь нет ничего особо отличающего от уже рассмотренных случаев, кроме требования указывать три адреса. Чаще всего такие команды используются для возможности в явном виде задать адреса операндов источников и операндов приемников. Но еще раз подчеркну, что понятие адресности не связано с понятиями источник и приемник.

Могут существовать и команды с требованием указания большего количества адресов операндов, но они еще боле редки, чем трехадресные. Важно понимать, что адресность команды не тождественна количеству операндов в команде! Давайте рассмотрим это на простом примере. Команда ADD выполняет операцию сложения двух операндов. Эти операнды могут находиться в ячейках памяти (включая регистры). Это мы видели в примерах двухадресных команд. Но ведь команда ADD может выполнять сложение константы и содержимого ячейки памяти. Если константа находится в какой-либо ячейке памяти, то отличия от уже рассмотренных случаев нет. Но константа может находиться и прямо в коде команды, быть ее частью. В этом случае нам требуется указать адрес лишь одного операнда, а не двух. Вот небольшой пример

ADD #123, R1

Здесь 123 это собственно константа, данные, а не адрес ячейки памяти. Это показано символом '#' предшествующим числу в мнемонической записи команды. Таким образом, данная команды является одноадресной, хоть и остается двухоперандной!

  • Адресность процессора равна максимальной адресности выполняемых им машинных команд.

Режимы адресации

Однако, возможность указания адреса операнда это еще не все. Дело в том, что такая интерпретация ответственных за адреса полей команды существенно ограничивает функциональность. В частности, мы лишены возможности последовательного перебора ячеек памяти одной и той же командой внутри программного цикла. То есть, нам необходима возможность интерпретации, не человеком, а процессором, операндов не только как данные или непосредственные адреса. А это приводит нас к понятию "режим адресации". Я уже рассматривал этот вопрос в старой статье

Микроконтроллеры для начинающих. Часть 8. Режимы адресации операндов
Разумный мир16 января 2020

Но там режимы адресации рассматривались с точки зрения относительно высокого уровня, а сегодня нам требуется гораздо более низкий уровень.

Раз адрес операнд в коде команды может иметь разное семантическое значение, значит нам нужно как то указывать для процессора, как именно нужно с ним поступать. Поэтому мы заменим поля операндов в коде машинных команд на поля режимов адресации, но сделать это не так просто. Рассматривать будем на примере процессора регистровой архитектуры.

Для начала попробуем разделить ситуации, когда внутренний регистр процессора может содержать как собственно данные, так и адрес ячейки внешней памяти. То есть, введем два режима адресации:

  • Регистровый режим адресации. Содержимое регистра процессора является данными, которые непосредственно участвуют в операции.
  • Косвенный регистровый режим адресации. Содержимое регистра процессора является адресом ячейки внешней памяти, которая и содержит участвующие в операции данные.

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

Поле операнда в команде состоит из двух частей, кода режима адресации и номера регистра. Иллюстрация моя
Поле операнда в команде состоит из двух частей, кода режима адресации и номера регистра. Иллюстрация моя

Нам сейчас не важны остальные поля кода команды. Часть "адрес регистра" является непосредственным источником сигналов Addr_A и Addr_B для нашего примера ядра процессора. А часть "режим адресации" является источником сигналов SEL_A и SEL_B. Но этого недостаточно, так как если сигнал SEL_x переключает мультиплексор на "блок работы с ОЗУ", нам необходимо передать в этот блок содержимое регистра и дождаться окончания его работы с памятью. Это мы будем рассматривать позже.

При мнемонической записи регистровый и косвенный регистровый режимы адресации различают по способу записи:

Rn - регистровая адресация

(Rn) или @Rn - косвенная регистровая адресация

Но у нашей структуры поля операнда есть один недостаток - не предусмотрена возможность указания адреса ячейки памяти. Действительно, размер ОЗУ во много раз превышает размер блока регистровой памяти процессора и полный адрес просто не поместится в отведенное для номера регистра место. Решить проблему достаточно просто если указать в поле операнда несуществующий регистр. Конечно, при этом поле"адрес регистра" должно быть больше, чем требуется для адресации всех регистров процессора. Как вариант, мы можем отвести под поле "режим адресации" еще один бит. А сам операнд (значение операнда) мы разместим после команды. Получается примерно так

Поле операнда с расширенным полем режима адресации позволяет размещать значение операнда после кода команды. Более того, это значение операнда мы можем интерпретировать либо как данные (литерал), либо как адрес ячейки памяти содержащей данные. Иллюстрация моя
Поле операнда с расширенным полем режима адресации позволяет размещать значение операнда после кода команды. Более того, это значение операнда мы можем интерпретировать либо как данные (литерал), либо как адрес ячейки памяти содержащей данные. Иллюстрация моя

Обратите внимание, что " после кода команды" означает лишь то, что это поле (значение операнда) является дополнительным и может отсутствовать, если используется один из регистровых режимов адресации. С точки зрения процессора это дополнительное поле значения операнда является частью команды. Дополнительный бит в поле режима адресации позволяет нам задавать два дополнительных режима адресации:

  • Непосредственная адресация, она же литеральная. Дополнительное поле команды содержит данные, которые непосредственно участвуют в операции.
  • Прямая адресация. Дополнительное поле команды содержит адрес ячейки внешней памяти, которая и содержит участвующие в операции данные.

Обратите внимание, что литерал и адрес памяти это просто разная интерпретация содержимого дополнительного поля команды. Причем адрес памяти можно рассматривать как косвенную адресацию с использованием литерала. Это нашло отражение и в кодировании режима адресации на последней иллюстрации. Посмотрите внимательнее и все увидите. Очень важно, что в этих режимах адресации содержимое поля "номер регистра" просто игнорируется.

В мнемонической записи два дополнительных режима адресации различают тоже по форме записи:

#value - непосредственный режим адресации (литерал)

value - прямой режим адресации

Обратите внимание, что литерал, с точки зрения АЛУ является размещенным в памяти операндом. Но эта память не обязательно является ОЗУ данных. Это может быть и памятью команд в Гарвардской архитектуре. При этом нам не требуется адрес литерала в памяти (в любой памяти). Литерал не должен быть адресуемым. Но может быть таковым.

Однако, мы не до конца использовали предоставляемые дополнительным полем команды возможности. Ведь это дополнительное поле можно использовать для реализации индексного режима адресации. Достаточно просто не игнорировать содержимое поля "номер регистра".

  • Индексный режим адресации. Содержимое указанного регистра складывается с содержимым дополнительного поля команды. Результат сложения используется в качестве адреса ячейки внешней памяти, которая и содержит участвующие в операции данные.

Участвующий в вычислении адреса регистр называется индексным регистром. И вот здесь опять из деталей начинает выглядывать дьявол... В некоторых процессорах такой режим адресации называется базовым. Название "базовый" является достаточно обоснованным. Ведь дополнительное поле команды можно считать адресом начала некоторого блока памяти, базовым адресом. А содержимое регистра смещением от этого базового адреса.

Нужно сделать важно уточнение, что индексный, он же базовый, режим адресации очень похож на адресацию массивов, но таковым не является! Указание адреса элемента массива действительно осуществляется с помощью индекса, но в вычислении адреса ячейки памяти учитывается и размер одного элемента массива. Косвенная/базовая адресация в машинных командах при вычислении адреса не учитывает размер элемента, просто складываются два значения. Одно из дополнительного поля команды, второе из регистра.

Поскольку индексная/базовая адресация является косвенной по своей природе, в мнемонической записи используется форма основанная на косвенной регистровой адресации

value(Rn) - индексная/базовая адресация

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

Расширение поля режима адресации позволяет ввести дополнительный, индексный, режим адресации. Иллюстрация моя
Расширение поля режима адресации позволяет ввести дополнительный, индексный, режим адресации. Иллюстрация моя

Обратите внимание, что у нас поле режима адресации получилось избыточным. Мы можем этим воспользоваться для добавления новых режимов адресации. Но важнее другое, теперь это поле содержит не отдельные биты, управляющие работой разных узлов процессора, а код режима адресации. И в процессоре появляется дополнительный узел "дешифратор режима адресации". Мы будем рассматривать этот узел в составе блока работы с ОЗУ в следующей статье.

Но теперь у нас возникает вопрос, а почему возможен только косвенный регистровый режим адресации? Почему мы не можем рассматривать ячейку памяти, которая содержит не данные, а адрес другой ячейки памяти, содержимое которой уже и будет являться данными? Да, это усложнит выполнение команды процессором, но такой режим адресации вполне возможен:

  • Косвенный режим адресации. Содержимое дополнительного поля команды содержит адрес ячейки памяти, содержимое которой интерпретируется не как данные, а как адрес еще одной ячейки памяти, которая и будет содержать участвующие в операции данные.

По сути, это дополнительный уровень косвенной адресации над литералом, размещенным в дополнительном поле команды. И введение косвенной адресации не требует дополнительных изменений формата наших команд. Просто используем один из неиспользуемых ранее кодов режима адресации

Добавление косвенной адресации не требует изменения формата наших машинных команд. Иллюстрация моя
Добавление косвенной адресации не требует изменения формата наших машинных команд. Иллюстрация моя

Мы можем продолжить расширение возможных режимов адресации, наше поле "код режима адресации" это позволяет сделать. Например, мы можем ввести:

  • Индексно-базовый режим адресации. Первое дополнительное поле команды содержит адрес ячейки памяти, содержимое которой складывается со вторым дополнительным полем команды. Результат сложения используется как адрес ячейки памяти содержащей данный участвующие в выполнении команды.

Это просто расширение индексного/базового режима адресации, когда в качестве индекса используется не регистр, а ячейка памяти. Нам не требуется расширять поле кода режима адресации, но у нас появляется еще одно дополнительное поле в команде. Давайте присвоим этому режиму адресации код 110. Я не буду отдельно иллюстрировать этот режим адресации, для вас не должно представлять сложности нарисовать иллюстрацию самостоятельно.

Пожалуй, остановимся с добавлением режимов адресации. Количество реализованных в процессоре режимов адресации зависит от его функционального назначения и уровня сложности (что влияет и на стоимость процессора). В простых процессорах могут быть реализованы только, например, непосредственный, регистровый, косвенный регистровый, прямой, индексный/базовый. В более сложных процессорах могут быть добавлены косвенный и индексно-базовый. Но даже наличие в процессоре какого-либо режима адресации не означает, что для него не будет никаких ограничений.

Оптимизация

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

Архитектура регистр-регистр, регистр-память, память-память

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

Архитектура память-память

Является наиболее универсальной. Для двухадресных команд оба операнда могут располагаться в памяти. Естественно, при этом и источники данных, и приемники, располагаются в памяти. Регистры или не используются совсем, или только в качестве индексных.

Архитектура память-регистр

Является ограниченным вариантом архитектуры память-память. Один из операндов может находиться только в регистре. Иногда вводят дополнительное ограничение, когда приемником результата операции может быть только регистр. То есть, ячейка памяти может быть только источником данных, но не приемником. За исключение команд пересылки, разумеется.

Архитектура регистр-регистр

Эта архитектура вовсе не является шуткой! Отсутствие возможности вообще обращаться к памяти отнюдь не означает, что процессор никуда не годен! Представьте, что объем регистровой памяти процессора относительно большой, например, 64 регистра. И часть этих регистров являются не набором триггеров, как мы ранее рассматривали, а регистрами каких либо внешних устройств. Например, АЦП, ЦАП, устройств ввода/вывода дискретных сигналов, и т.д. Специализированный процессор вполне может выполнять программу, причем не обязательно простейшую, ограничиваясь обращением только к регистрам, без использования ОЗУ. Да, это больше относится к микроконтроллерам. Но ведь любой микроконтроллер содержит процессор. Так что это совсем не шутка.

Блок выборки операндов

Если сложить все, что мы сегодня рассматривали, то становится понятным, что наш процессор должен содержать не просто блок регистров с набором коммутаторов, как мы рассматривали в предыдущих статьях, а полноценный блок выборки операндов. И это блок может базироваться на блоке регистровой памяти или являться параллельной ему структурой.

Блок выборки операндов, по сути своей, является маленьким специализированным процессором, который выполняет операции с адресами памяти и обеспечивает последовательное и предсказуемое получение и передачу операндов (и результатов). Он взаимодействует с блоком регистровой памяти и блоком работы с ОЗУ. И блок выборки операндов может иметь свое собственное маленькое АЛУ. А может использовать основное АЛУ процессора.

Как блок выборки операндов может быть устроен и как он может включаться в состав процессора мы рассмотрим в следующей статье. В ней же коснемся и понятия адресного пространства.

Заключение

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

До новых встреч!

Наука
7 млн интересуются