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

Архитектура ЭВМ. Аккумуляторная архитектура процессоров. Через стек к аккумулятору

Оглавление

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

Что такое аккумулятор?

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

А вот с гидроаккумулятором уже немного интереснее. Гидроаккумуляторы, например, в системах автономного водоснабжения, позволяют накопить некоторый объем воды. Но ведь тоже самое позволяет сделать обычная емкость, бочка, например, которую мы не называем гидроаккумулятором. В чем же отличие? В гидроаккумуляторе есть мембрана, которая разделяет воду и воздух, находящийся под некоторым давлением. Накачивая воду мы повышаем давление воздуха под мембраной. Поэтому гидроаккумулятор накапливает и хранит не только некоторый объем воды, но и энергию сжатого газа.

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

Но можем ли мы так же накапливать, преобразовывать, хранить, отдавать информацию? Конечно! Информацию хранит триггер, но мы же называем его аккумулятором. Почему? Триггер хранит, но не накапливает информацию. Как и собранный из триггеров регистр. Что же нужно, что бы регистр стал регистром-аккумулятором?

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

Архитектура ЭВМ. Стековая архитектура процессоров
Разумный мир22 июня 2023

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

Аккумулятор как предельный случай стека

В предыдущей статье я не стал приводить функциональную схему стекового процессора, но сегодня она нам понадобится

Очень сильно упрощенная функциональная схема фрагмента (АЛУ, SP, стек) стекового процессора. Иллюстрация моя
Очень сильно упрощенная функциональная схема фрагмента (АЛУ, SP, стек) стекового процессора. Иллюстрация моя

Это лишь фрагмент, причем очень упрощенный, но нам сегодня большего и не нужно. АЛУ, как мы видели в предыдущей статье, работает лишь со стеком. Регистр SP, который напрямую программисту не доступен, является лишь счетчиком, который может работать на увеличение или уменьшение. Вы же помните, что направление изменения внутреннего стека значения не имеет? Поэтому мы можем принять, например, что SP уменьшается на 1 при помещение объекта в стек и увеличивается на 1 при извлечении. Сброс регистра SP используется для его инициализации при сбросе процессора.

Стек, по своей сути, является просто оперативной памятью небольшого объема. Стоящий после счетчика (регистра SP!) дешифратор является дешифратором адреса памяти. Но зачем нужны два регистра между стеком и АЛУ? Дело в том, что данные с теке при выполнении операций не перемещаются, мы это разбирали с предыдущей статье, изменяется лишь содержимое указателя, регистра SP. Поэтому мы не можем просто подключить входы АЛУ к каким то двум ячейкам в стеке. Нам требуется две операции доступа к стеку, которые позволят получить содержимое двух соседних ячеек стека (причем начальный адрес может быть произвольным, он определяется SP). Эти значения и хранятся в двух вспомогательных регистрах.

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

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

Если у нас всего одна ячейка в стеке, то нам не нужен ни регистр SP, ни адресный дешифратор. Процессор уже заметно упрощается. Гораздо менее очевидно, что нам не требуется и промежуточный регистр между "стеком" и АЛУ. Еще одно упрощение. Но возникает и проблема... Для многих операций АЛУ требуется два операнда...

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

И у нас получается примерно такая функциональная схема того же самого узла, что мы рассматривали ранее

Очень сильно упрощенная функциональная схема фрагмента процессора аккумуляторной архитектуры. Иллюстрация моя
Очень сильно упрощенная функциональная схема фрагмента процессора аккумуляторной архитектуры. Иллюстрация моя

Радикальное упрощение! Один операнд для АЛУ всегда поступает из регистра-аккумулятора, который обозначен ACC, второй, если он нужен для выполнения операции, всегда из внешней памяти. Результат всегда помещается в регистр-аккумулятор. Разумеется у нас сохраняется возможность записать в аккумулятор данные из памяти или передать их из аккумулятора в память.

Вы обратили внимание, что я назвал регистр, который мы считаем одноуровневым стеком (состоящим из одной ячейки), аккумулятором? Но почему мы теперь имеем на это право? Имеем. Этот регистр не только используется для временного хранения, но и "накапливает" результат в цепочках вычислений. Более того, хранящаяся в регистре информация преобразуется АЛУ при выполнении операций.

Но может ли существовать одноуровневый стек? Да, как предельный случай стека в общем и целом. Команды PUSH и POP по прежнему применимы к такому стеку, хоть он и состоит лишь из одной вершины. Поскольку помещение объекта в такой стек является одновременно и загрузкой объекта в регистр, причем даже в гораздо большей степени, используются соответствующие мнемоники для команд.

  • LDA [addr] - load to accumulator, используется вместо мнемоники PUSH. Помещает в регистр аккумулятор данные из ячейки памяти.
  • STA [addr] - store from accumulator, используется вместо мнемоники POP. Помещает данные из регистра-аккумулятора в ячейку памяти.

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

ADD

требуется использовать

ADD [addr]

Одно-операндные команды остаются неизменными, например

NEG

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

XCHG [addr]

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

Давайте посмотрим, как будет выглядеть программа вычисления формулы a / (b + c), которую мы уже рассматривали в предыдущей статье

Сравнение программ процессоров стековой и аккумуляторной архитектур. Иллюстрация моя
Сравнение программ процессоров стековой и аккумуляторной архитектур. Иллюстрация моя

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

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

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

Обратите внимание, что не требуется прямой доступ к регистру-аккумулятору! Он неявно используется всеми командами (почти всеми), но знать его адрес программисту не нужно. Даже команды LDA и STA используют аккумулятор неявно.

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

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

Пример программы вычисления суммы элементов массива использующей специальные команды и дополнительные регистры. Иллюстрация моя
Пример программы вычисления суммы элементов массива использующей специальные команды и дополнительные регистры. Иллюстрация моя

Обратите внимание, что эта программа использует два дополнительных регистра, прямого доступа к которым нет. Первый, регистр адреса начала массива (адреса начала цепочки). Второй, регистр количества элементов (длина цепочки). Доступ к этим регистрам обеспечивают команды SETADR и SETCNT, причем содержимое загружается из аккумулятора. Команда ADDS, причем неявно (!!!), использует все три регистра. Результат накапливается в аккумуляторе.

Считаете, что эти дополнительные регистры служебные? А если обозначить их B и C, а работать с ними можно командами SETx и GETx? Не правда ли, все становится очень похоже на регистры bx и cx в процессоре 8086? За одним важнейшим отличием - в 8086 эти регистры можно адресовать в разных командах и они имеют адреса (точнее, номера), а в нашем процессоре у этих регистров адресов нет.

Такое расширение аккумуляторной архитектуры, еще немного расширенное, приводит нас к архитектуре регистровой. Но об этом в другой раз.

Заключение

Аккумуляторная архитектура гораздо более распространена и известна практически всем. Поэтому что-либо новое про нее действительно сложно сказать. Тем не менее, под нестандартным углом зрения можно заметить, что эта архитектура существует не сама по себе, а имеет некоторые общие корни со стековой архитектурой. Хоть это и не так просто заметить. И не случайно я начал рассказ именно со стековой архитектуры.

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

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