awesome-everything EN
↑ Обратно к восхождению

Базовый CS с нуля

Регистры

Суть Регистры — это небольшой набор именованных, сверхбыстрых ячеек хранения, физически находящихся внутри CPU. CPU выполняет всю свою арифметику и логику над значениями, хранящимися в регистрах, а не в основной памяти. Счётчик команд — тоже регистр.
◷ 20 min

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

Эти слоты называются регистрами. Они — рабочая память CPU: значения, над которыми CPU работает прямо сейчас. Без регистров CPU приходилось бы обращаться в основную память за каждым промежуточным значением, что делало бы каждую программу в сотни раз медленнее.

Что именно такое регистры, сколько их у CPU и почему их существование ускоряет программы?

Цель

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

1

Что такое регистр. Регистр — это ячейка хранения, встроенная непосредственно в чип CPU, а не в отдельные чипы памяти (ОЗУ). Каждый регистр хранит ровно одно значение: на 64-битном CPU один регистр вмещает 64-битное (8-байтовое) значение.

Регистры сделаны из тех же транзисторных схем, что и логика внутри CPU. Они находятся на той же пластине кремния, в миллиметрах или даже микрометрах от АЛУ, выполняющего арифметику. Доступ к регистру занимает один или два такта — примерно долю наносекунды на современном CPU.

Основная память (ОЗУ), напротив, — это отдельный чип, соединённый шиной. Доступ к ОЗУ занимает 50–100 наносекунд — примерно в 100–300 раз дольше, чем доступ к регистру. Для повторяющихся вычислений эта разница огромна.

2

Почему существуют регистры: память далеко и медленная. Представь цикл, складывающий 1 миллион чисел. Если бы CPU должен был брать каждую промежуточную сумму из ОЗУ, обновлять её и записывать обратно, каждое сложение оплачивало бы стоимость доступа к памяти ~100 нс. Только на трафик памяти ушло бы 100 мс.

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

Это ключевой принцип: доставить данные в «окрестности» CPU, работать с ними там, затем отправить результат обратно. Регистры — это «окрестности».

3

Регистры общего назначения. Большинство регистров CPU — это регистры общего назначения (РОН, по-английски GPR — General-Purpose Register). У них нет фиксированного смысла — любая инструкция может использовать любой РОН для хранения любого значения. Программист (или компилятор) решает, какой регистр хранит какое значение в данный момент.

Реальные CPU имеют фиксированное количество РОН:

  • CPU x86-64 имеет 16 64-битных регистров общего назначения: RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP и R8–R15.
  • CPU ARM (AArch64) имеет 31 64-битный регистр общего назначения: X0–X30.
  • Упрощённые учебные CPU (например, в nand2tetris) могут иметь всего несколько: R0, R1, R2, R3.

Количество невелико и фиксировано конструкцией чипа. Если программе нужно больше живых значений, чем есть регистров, компилятор должен временно «выгружать» некоторые значения в память и загружать их обратно при необходимости — неизбежная цена, которую компиляторы стараются минимизировать.

Почему это работает

Зачем не добавить больше регистров? Добавление регистров означает больше транзисторов на чипе, что увеличивает потребление энергии и тепловыделение. Что ещё важнее, кодировка каждой инструкции должна указывать, какие регистры она использует; больше регистров требует больше битов в инструкции для их наименования. 4-битное поле регистра в инструкции называет 16 регистров, 5-битное — 32. Более широкие инструкции означают больший размер кода в памяти. Здесь действует закон убывающей отдачи: переход с 4 на 16 регистров даёт большой выигрыш; с 64 на 128 — значительно меньший, потому что компиляторы уже эффективно справляются с 64. Большинство архитектур останавливаются на 16–32 РОН.

4

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

  • Счётчик команд (СК, PC) — как ты узнал в предыдущем уроке, СК хранит адрес следующей инструкции для выборки. CPU обновляет его автоматически после каждой инструкции. Инструкция JUMP записывает новое значение в СК. Это регистр, как и любой другой, но он недоступен для общего использования.

  • Указатель стека (SP, Stack Pointer) — хранит адрес вершины стека вызовов в памяти. Операции push и pop автоматически изменяют указатель стека. Со стеком вызовов ты познакомишься в более позднем разделе.

  • Регистр флагов (Status Register) — набор однобитных флагов, фиксирующих результат последней операции: был ли результат равен нулю, был ли перенос из старшего бита (переполнение), был ли результат отрицательным и т. д. Инструкции условного JUMP проверяют флаги, чтобы решить, выполнять ли переход.

  • Регистр инструкций (РИ, IR) — хранит текущую выполняемую инструкцию после её выборки из памяти, как ты видел в цикле выборки–декодирования–исполнения.

Частая ошибка

Распространённая путаница: воспринимать регистры и память (ОЗУ) как две версии одного и того же, отличающиеся только скоростью. Они отличаются по природе. ОЗУ — это большой, адресуемый массив байтов, сохраняющий своё содержимое: оно переживает вызовы функций и разделяется между разными программами (через ОС). Регистры — крошечный, именованный, неадресуемый набор слотов, принадлежащих целиком текущему потоку инструкций. Регистр нельзя «адресовать» адресом памяти — он называется напрямую в кодировке инструкции. И когда программа сохраняет состояние в файл или отправляет данные по сети, данные должны пройти через память — они никогда не проходят через регистр напрямую.

42
R0
7
R1
0
R2
108
СК
0100
РИ
0010
Флаги
Регистровый файл CPU: R0 = 42, R1 = 7 (активные операнды), R2 = 0 (сюда запишется результат). СК = 108 (адрес следующей инструкции). РИ хранит кодировку текущей инструкции. Флаги хранят биты состояния.
Разбор примера

Отслеживание состояния регистров через три инструкции.

Начальное состояние: R0 = 0, R1 = 0, R2 = 0, СК = 100.

Память (хранящиеся значения):

  • Адрес 200: значение 25
  • Адрес 201: значение 17

Инструкция по адресу 100: LOAD R0, 200

  • Исполнение: читаем адрес памяти 200, получаем 25. Сохраняем 25 в R0.
  • После: R0 = 25, R1 = 0, R2 = 0, СК = 104.

Инструкция по адресу 104: LOAD R1, 201

  • Исполнение: читаем адрес памяти 201, получаем 17. Сохраняем 17 в R1.
  • После: R0 = 25, R1 = 17, R2 = 0, СК = 108.

Инструкция по адресу 108: ADD R2, R0, R1

  • Исполнение: АЛУ вычисляет 25 + 17 = 42. Результат сохраняется в R2.
  • После: R0 = 25, R1 = 17, R2 = 42, СК = 112.

Наблюдение: на протяжении всех трёх циклов счётчик команд тоже менялся: 100 → 104 → 108 → 112. Именно он управляет шагом выборки. Остальные регистры изменялись только тогда, когда конкретная инструкция указывала их как цель.

Практика 0 / 5

Доступ к регистру занимает примерно 1–2 такта. Доступ к ОЗУ — примерно 100–300 тактов. Во сколько раз быстрее доступ к регистру, чем к ОЗУ (используй нижнюю границу)? Введи число.

CPU x86-64 имеет сколько 64-битных регистров общего назначения? Введи число.

Каждый регистр общего назначения на 64-битном CPU вмещает сколько бит? Введи число.

Какой специальный регистр хранит адрес следующей инструкции для выборки? Введи 1 (счётчик команд) или 2 (регистр флагов).

После выполнения LOAD R0, 200, где оказывается значение из адреса памяти 200? Введи 1 (в регистре R0) или 2 (в регистре R1).

Проверь себя
Викторина

Почему CPU хранит рабочие значения в регистрах, а не читает и записывает основную память при каждом вычислении?

Итог

Регистр — сверхбыстрая, именованная ячейка хранения, физически находящаяся внутри чипа CPU. В отличие от основной памяти (ОЗУ), регистры не адресуются адресом памяти — они называются напрямую в кодировке инструкций (R0, R1, RAX и т. д.). Регистры в 100–300 раз быстрее ОЗУ, поскольку находятся на той же кремниевой пластине, что и АЛУ. CPU выполняет свою реальную работу — арифметику, логику, вычисление адресов — над значениями в регистрах, а не над значениями в памяти напрямую. Регистр общего назначения (РОН) может хранить любое значение в любой момент; какой регистр хранит какое значение — решает компилятор. Специальные регистры выполняют фиксированные аппаратные роли: счётчик команд хранит адрес следующей инструкции, указатель стека отслеживает стек вызовов, регистр флагов фиксирует результаты операций. Важно: счётчик команд сам является регистром — инструкция, которая его обновляет, — это обычное обновление СК, происходящее в каждом цикле.

Продолжить восхождение ↑Машинный код
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.