Арифметико-логическое устройство (АЛУ) — это фундаментальная часть любого компьютера, выполняющая операции сложения, вычитания и логические операции, однако принцип его работы для многих остаётся загадкой. Я провёл реверс-инжиниринг схемы АЛУ микропроцессора 8085 и в этой статье объясняю, как она устроена. АЛУ 8085 — это на удивление сложная схема, которая на первый взгляд выглядит как непонятное нагромождение логических элементов, но её можно понять, если не бояться немного углубиться в булеву логику.

На следующей диаграмме показано расположение АЛУ внутри 8085. АЛУ имеет разрядность 8 бит, при этом старший разряд расположен слева. Файл регистров — это крупный блок под АЛУ. Регистры имеют разрядность 16 бит и состоят из пар 8-битных регистров. Интересно, что в файле регистров старший разряд находится справа, то есть порядок противоположен порядку в АЛУ.

The 8085 microprocessor, showing the location of the 8-bit ALU.
Микропроцессор 8085, на котором показано расположение 8-битного АЛУ. Полная версия по ссылке.

АЛУ принимает два 8-битных входа, которые я буду обозначать как A и X, и выполняет одну из пяти базовых операций: ADD, OR, XOR, AND и SHIFT-RIGHT. Кроме того, если вход X инвертирован, АЛУ может выполнять вычитание и операцию дополнения. Можно заметить, что в этом списке отсутствует SHIFT-LEFT. Однако он реализуется просто: число складывается само с собой, что эквивалентно сдвигу влево на один бит в двоичном представлении. Обратите внимание, что арифметические операции в 8085 очень простые. Умножение и деление отсутствуют — они появились только в 8086.

АЛУ состоит из 8 почти одинаковых блоков, по одному на каждый бит. При сложении каждый такой блок складывает соответствующие входные биты, вычисляя сумму A + X + входной перенос, формируя бит суммы и бит выходного переноса. То есть каждый бит АЛУ реализует полный сумматор. Логические операции работают непосредственно с двумя входными битами: A AND X, A OR X, A XOR X. Операция сдвига вправо просто выводит бит A из соседнего блока справа.

Схема АЛУ

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

Schematic of one bit of the ALU in the 8085 microprocessor.
Схема одного бита АЛУ в микропроцессоре 8085.

Инверсия

В нижней части схемы находится сложный логический элемент, обозначенный как Negation («Инверсия»). Этот элемент при необходимости выбирает инвертированный второй аргумент, подавая либо XN, либо /XN. (XN — это N-й бит второго аргумента, который я обозначаю как X. Символ / означает дополнение.) Для упрощения дальнейшего объяснения будем считать, что XN не инвертирован.

Операция

Над блоком выбора дополнения расположены несколько логических элементов с меткой Operation («Операция»), которые выполняют нужную двухвходовую операцию. Элемент НЕ-И (NAND) слева формирует либо A NAND X, либо 1 — в зависимости от управляющей линии select_op1. Элемент ИЛИ (OR) справа формирует либо A OR X, либо 1 — в зависимости от управляющей линии select_op2. Объединение этих сигналов через NAND даёт четыре возможных результата:

select_op1

select_op2

Результат

0

0

A NOR X

0

1

0

1

0

A NXOR X

1

1

A AND X

Обратите внимание, что вместо операций OR и XOR на этом этапе получается их инвертированное значение. Это будет скорректировано на следующем шаге.

Комбинирование с переносом

Над блоком операций расположен следующий узел, обозначенный как Combine with carry («Объединение с переносом»). Он формирует выход АЛУ, объединяя входной перенос с результатом операции с помощью XOR.

Чтобы понять работу этого узла, сначала рассмотрим простой элемент XOR, который используется в АЛУ несколько раз. Его логика довольно проста: если оба входа равны 0 (верхний случай) или оба равны 1 (нижний случай), то на выходе получается 0.

An XOR gate can be implemented by a NOR gate and an AND-NOR gate. This circuit is used in the 8085 ALU.
Логический элемент XOR может быть реализован с помощью логического элемента NOR и логического элемента AND-NOR. Эта схема используется в АЛУ 8085.

Если временно не учитывать схему сдвига вправо, этот блок логики фактически представляет собой XOR. При этом XOR с 0 ничего не меняет, а XOR с 1 инвертирует значение. Выражение A XOR X XOR CARRY соответствует младшему биту суммы A, X и CARRY.

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

Op

Результат операции

Перенос

Результат

or

A NOR X

1

A OR X

add

A NXOR X

/перенос

A XOR X XOR CARRY

xor

A NXOR X

1

A XOR X

and

A AND X

0

A AND X

shift right

0

0

A(N+1)

complement

A NOR /X

1

A OR /X

subtract

A NXOR /X

/перенос

A XOR /X XOR CARRY

Обратите внимание, что линия входного переноса должна принимать корректное значение для получения нужного результата. При сложении она передаёт инвертированный перенос от одного разряда к следующему. Для операций OR и XOR она устанавливается в 1. Для AND и SHIFT_RIGHT — в 0. Как будет показано ниже, схема формирования переноса обеспечивает нужное значение для каждой операции.

Последний элемент этой схемы — блок сдвига вправо. При нулевом значении операционного входа, нулевом переносе и активном сигнале shift_right на выход подаётся бит из соседнего правого разряда: A(N+1).

Формирование переноса

Слева расположен узел Generate carry («Формирование переноса»), который вычисляет выходной перенос. Он может выдавать три варианта: 1, 0 или (инвертированный) перенос от суммы. Если активна линия select_op2, перенос принудительно устанавливается в 0. Если активна линия force_ncarry_1, перенос устанавливается в 1. В противном случае перенос вычисляется для суммы A + X + входной перенос по стандартной логике: если входной перенос равен 1 и хотя бы один из входных битов равен 1, возникает перенос. Если оба входных бита равны 1, перенос также возникает.

Флаги

В 8085 есть флаг чётности, который равен 1, если количество единичных битов чётное, и 0 — если нечётное. Флаг чётности формируется путём применения XOR ко всем битам результата (с последующим инвертированием). Каждый бит последовательно объединяется по XOR с накопленным значением чётности младших разрядов с помощью схемы чётности, расположенной в верхней части схемы. При этом используется тот же XOR-элемент, который был описан ранее.

Флаг нуля вычисляется с помощью простой схемы: каждый бит результата управляет транзистором, который притягивает линию нуля к низкому уровню, если этот бит равен 1. В результате получается элемент НЕ-ИЛИ (NOR) с восемью входами, распределённый по всему АЛУ.

Управляющие линии

Как видно на схеме, в 8085 используется несколько управляющих линий для управления работой АЛУ. Всего АЛУ поддерживает 7 различных операций, и в таблице ниже приведены управляющие сигналы, используемые для каждой из них. Также указаны коды операций (opcode), которые задействуют соответствующую функцию АЛУ.

Операция

select_neg

select_op1

select_op2

shift_right

force_ncarry_1

Коды операций

or

0

0

0

0

1

ORA,ORI (и по умолчанию)

add

0

1

0

0

0

INR,DCR,RLC,DAD,RAL,DAA,ADD,ADC,ADI,ACI (а также недокументированные LDSI, LDHI, RDEL)

xor

0

1

0

0

1

XRA,XRI

and

0

1

1

0

1

ANA,ANI

shift right

0

0

1

1

1

RRC,RAR (ARHL)

complement

1

0

0

0

1

CMA

subtract

1

1

0

0

0

SUB,SBB,SUI,SBI,CMP,CPI (DSUB)

Управляющие линии АЛУ формируются из кода операции с помощью программируемой логической матрицы (programmable logic array, PLA). В частности, это выходы блока PLA F, расположенного справа от АЛУ. Более подробно это описано в моей статье о PLA.

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

The PLA in the 8085

Реверс-инжиниринг АЛУ

Эта информация основана на реверс-инжиниринге микропроцессора 8085, выполненном командой visual 6502. Эта команда растворяет микросхемы в кислоте, чтобы удалить корпус, а затем делает множество детальных фотографий кристалла. Павел Зима (Pavel Zima) преобразовал эти фотографии в изображения слоёв масок, построил на их основе транзисторную схему и написал симулятор 8085 на уровне транзисторов.

Я взял эту транзисторную модель и использовал её, чтобы разобраться в работе АЛУ. Сначала я преобразовал транзисторную схему в логические элементы. Затем определил, какие из них относятся к АЛУ, и собрал из них принципиальную схему. После этого я проанализировал работу схемы для разных операций и в итоге понял, как она устроена.

Заключение

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

АЛУ 8085 реализовано совершенно иначе, чем АЛУ в 6502 (о котором я напишу позже). В 6502 используются достаточно простые схемы, которые параллельно вычисляют значения SUM, AND, XOR, OR и SHIFT, а затем применяется простой мультиплексор на проходных транзисторах для выбора нужной операции. В отличие от этого, АЛУ 8085 формирует только одно — требуемое — значение.

Другие выпуски от Ken Shirrif

Если хочется посмотреть на похожий инженерный подход уже на современных технологиях, ниже — несколько открытых уроков про внутреннее устройство систем, поведение кода и архитектурные решения на практике.

  • 23 апреля в 20:00. «Многопоточность в C++: как писать быстрые и безопасные приложения». Записаться

  • 4 мая в 20:00. «Интерфейсы в Golang изнутри». Записаться

  • 19 мая в 20:00. «Асинхронность под капотом». Записаться

Полный список бесплатных уроков от преподавателей курсов уже доступен в календаре мероприятий.

Комментарии (0)