Архитектура процессора: от простых операций к системе команд и языку ассемблера

От простого сложения к управляемым операциям

В предыдущих частях мы заложили основу «Контрольной секции». Теперь настало время собрать всё воедино и реализовать первую полезную операцию — сложение содержимого регистров R0 и R1, которое мы рассматривали ранее.

Для этого необходимо соединить выходы 4, 5 и 6 степпера (устройства, задающего последовательность тактов) с управляющими входами регистров, как показано на схеме. Эта манипуляция позволяет на каждом из этих шагов активировать один бит разрешения на выход ('e') в левой части схемы и один бит разрешения на запись ('s') в правой. Таким образом, данные по шине передаются из одного регистра в другой в строго определённой последовательности.

Давайте детально разберём этот процесс. На шаге 4 активируется выход регистра R1 ('e') и вход временного регистра TMP ('s'). Данные из R1 копируются в TMP. На шаге 5 включается выход R0 ('e') и вход аккумулятора ACC ('s'), в результате чего число из R0 передаётся в ACC. На этом этапе нам не нужно задавать код операции (op-код) для арифметико-логического устройства (АЛУ), так как код сложения (ADD) по умолчанию равен 000. Для других операций пришлось бы выставить соответствующие биты 'op'. Наконец, на шаге 6 активируется выход ACC ('e') и вход R0 ('s'), что приводит к записи результата из аккумулятора обратно в регистр R0. Наглядная временная диаграмма этих сигналов представлена ниже.

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

Однако есть проблема: после шага 7 степпер сбрасывается и цикл повторяется с начала. На шаге 6 снова будет вычислена сумма R0 и R1, и так до бесконечности. Учитывая, что тактовая частота процессора измеряется миллионами герц, а наши регистры 8-битные, значение в R0 очень быстро достигнет максимума (255), после чего вычисления потеряют смысл.

Расширяем возможности: работа с памятью

Теперь рассмотрим более полезную операцию — сохранение данных из регистра в оперативную память (RAM). Предположим, нам нужно переместить число из R0 в ячейку RAM, адрес которой хранится в R2. Схема для этой операции ещё проще.

Здесь требуется всего два шага! На шаге 1 активируются выход R2 ('e') и вход регистра адреса памяти MAR ('s'), тем самым в MAR загружается адрес для обращения к RAM. На шаге 2 включаются выход R0 ('e') и управляющий вход RAM на запись ('s'), что приводит к копированию данных из R0 в указанную ячейку памяти.

Таким образом, мы можем выполнять множество действий: копировать данные, производить арифметические операции через АЛУ, сравнивать значения и т.д. Но ключевая проблема остаётся: любая операция будет бесконечно повторяться в цикле. Нам необходим механизм, который позволит выполнять одну инструкцию, затем другую, третью — то есть управлять последовательностью действий. Нужно научить контрольную секцию «понимать», какие соединения активировать после каждого сброса степпера.

Аналогия с программируемым автоматом

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

Допустим, у кассира есть 256 возможных элементарных действий. Каждому можно присвоить уникальный 8-битный код (байт). Тогда весь алгоритм его работы можно представить как последовательность таких байтов-инструкций. Например:

0000 0000 = Подойти к стойке

0000 0001 = Спросить: «Могу я принять ваш заказ?»

0000 0010 = Слушать ответ

0000 0011 = Нажать кнопку «бургер»

... и так далее.

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

Ключевое изобретение: система команд и счётчик инструкций

Жёсткая коммутация проводами даёт лишь одну повторяющуюся операцию. Решение — соединить все управляющие входы регистров и АЛУ со степпером не напрямую, а через логические элементы, управляемые специальным кодом. Но как выбирать этот код?

Великое изобретение заключается в следующем: инструкции будут храниться в оперативной памяти (RAM) в виде последовательности байтов, а процессор будет поочерёдно считывать и выполнять их. Для реализации этой идеи нужны три новых компонента:

  1. Регистр инструкций (IR — Instruction Register): в него загружается байт-команда из памяти. Биты этого регистра будут управлять логикой контрольной секции, определяя, какую операцию выполнять на шагах 4-6.
  2. Регистр-счётчик адреса инструкций (IAR — Instruction Address Register): хранит адрес в RAM, по которому находится следующая команда для выполнения. После выполнения каждой инструкции его значение увеличивается, чтобы перейти к следующей.
  3. Специальная логика в секции управления: обеспечивает цикл «выборка-выполнение». Она загружает команду из RAM (по адресу из IAR) в IR, увеличивает IAR на 1 и выполняет команду из IR. После выполнения степпер сбрасывается, и цикл повторяется для следующей инструкции.

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

На схеме показан процессор с добавленными регистрами IR и IAR. У IAR, как и у обычных регистров, есть вход ('s') и выход ('e'). У IR же есть только вход ('s'), так как его выход не подключён к шине данных — он управляет только логикой секции управления.

Цикл «выборка-выполнение»

Работа процессора теперь представляет собой непрерывный цикл. Первые три шага степпера отведены под выборку (fetch) инструкции, последующие три — под её выполнение (execute).

Рассмотрим фазу выборки подробнее:
Шаг 1 (сложный): Происходят две операции параллельно. Во-первых, значение из IAR (адрес следующей команды) копируется в MAR (регистр адреса памяти). Во-вторых, АЛУ, которому ещё не задана операция (по умолчанию ADD — сложение), прибавляет к значению в шине (это IAR) константу 1 (подаётся через специальную линию BUS1) и записывает результат (IAR+1) в аккумулятор ACC.
Шаг 2: Активируется чтение из RAM по адресу в MAR. Считанный байт (инструкция) помещается в шину и записывается в регистр IR.
Шаг 3: Значение «IAR+1», которое было вычислено на шаге 1 и хранится в ACC, переписывается обратно в IAR. Теперь IAR указывает на следующую ячейку памяти для будущей инструкции.

После этого на шагах 4, 5 и 6 выполняется инструкция, биты которой сейчас находятся в IR. По завершении шага 6, на шаге 7 степпер сбрасывается, и цикл начинается заново, но уже со следующим адресом команды в IAR.

Проектирование системы команд

8-битный регистр IR теоретически позволяет закодировать до 256 различных инструкций. Для нашего учебного процессора разработаем девять, которых будет достаточно для базовых операций: перемещения данных и работы с АЛУ.

Арифметико-логические инструкции

Это самый мощный класс команд. Наше АЛУ поддерживает 8 операций (ADD, SUB, AND, OR, XOR, NOT, SHL, SHR, CMP). Инструкция должна указать, какую операцию выполнить и с какими двумя регистрами (их у нас четыре: R0, R1, R2, R3).

Формат такой инструкции:
Бит 0: Всегда '1', признак команды АЛУ.
Биты 1-3: Код операции АЛУ (3 бита = 8 вариантов).
Биты 4-5: Номер первого регистра-источника (Reg A).
Биты 6-7: Номер второго регистра-приёмника (Reg B).
Например, код 1000 0110 означает: выполнить операцию ADD (000) над регистрами R1 (01) и R2 (10), результат поместить в R2.

Для реализации выбора произвольного регистра (а не только жёстко заданных R0 и R1) в контрольной секции используются дешифраторы и логические элементы И. Дешифратор, управляемый битами 4-5 из IR, активирует выход только одного из четырёх регистров в нужный момент времени (например, на шаге 5 для Reg A).

Схема выполнения команды АЛУ, например, ADD R1, R2, выглядит так:
Шаг 4: Содержимое Reg B (R2) копируется во временный регистр TMP.
Шаг 5: Содержимое Reg A (R1) помещается на шину. АЛУ получает два числа (из TMP и шины) и код операции из IR. Результат вычисления записывается в ACC.
Шаг 6: Результат из ACC копируется обратно в Reg B (R2).
Исключение — операция сравнения CMP, которая лишь устанавливает флаги, но не сохраняет результат в регистр.

Рождение языка ассемблера

Запоминать и записывать программы в виде двоичных кодов, вроде 1000 0110, неудобно. На помощь приходит символическое представление — язык ассемблера. Для наших инструкций АЛУ он будет выглядеть так:

Теперь команда ADD R1, R2 интуитивно понятна. Программист пишет код на ассемблере, а специальная программа-ассемблер переводит его в двоичные коды инструкций, которые уже можно загрузить в память компьютера для выполнения.

#компьютеры #наука и техника #образование #начинающим радиолюбителям #электроника начинающим #процессоры

Часть 7 - Назад Далее - Часть 9

Еще по теме здесь: Новости науки и техники.

Источник: Как устроен компьютер? Часть 8 (Как работают инструкции).