Указатели и индексные регистры (IX)

Допустим, нам нужно передвинуть хвост нашей Змейки, который занимает 10 ячеек памяти. С обычными командами (прямой адресацией) пришлось бы писать отдельную строчку кода для каждой ячейки: прочитай ячейку 1, запиши в 2, прочитай 2, запиши в 3... Это жутко неудобно, а если змейка вырастет до 100 ячеек, код просто не влезет в память!

Решение уровня «Указатели»: индексный регистр и косвенная адресация
Индексный регистр: авторское решение уровня

Чтобы работать с массивами данных, инженеры придумали косвенную адресацию и Индексный регистр (IX). В отличие от обычных команд, которые жёстко привязаны к конкретному адресу, команды для IX используют его как указатель.

Это как бегунок на линейке: держишь палец на делении 50, двигаешь его на 51, 52 — и каждый раз говоришь: «работай с тем местом, где сейчас палец».

Что такое косвенная адресация

Прямая адресация: STA 50 — адрес 50 записан прямо в инструкции. Косвенная адресация: STA [IX] — адрес лежит в регистре IX, а не в команде. Процессор смотрит, какое число в IX, и работает с этой ячейкой.

Ассемблер сам переводит STA [IX] в команду STAX (opcode 11), а LDA [IX] — в LDAX (opcode 10). Скобки — это договорённость: «адрес возьми из регистра». Набор команд мы разбирали в статье про ассемблер. Косвенную адресацию можно попробовать в песочнице с готовым процессором: LDX, STAX и LDAX там разведены полностью.

Команды индексного регистра

КомандаOpcodeЭффект
LDX N9IX = N — загрузить адрес в указатель
INX13IX = IX + 1 — сдвинуть указатель вперёд
LDA [IX]10 (LDAX)Acc = RAM[IX] — прочитать по указателю
STA [IX]11 (STAX)RAM[IX] = Acc — записать по указателю

Всего четыре команды — и в твоих руках весь массив памяти.

Указатель на числах

Пусть IX = 50. Команда STA [IX] записывает аккумулятор в RAM[50]. Затем INX — и IX = 51. Повторяем STA [IX] — данные ложатся в RAM[51]. Четыре шага — установить указатель, записать, сдвинуть, повторить — и ты обошёл всю память, не написав ни одного конкретного адреса в коде.

Как аппаратно выбирается адрес

За адрес RAM отвечает BusMUX: на один вход приходит операнд из ROM, на другой — выход регистра IX.Q. Переключает их сигнал UseIX от дешифратора. Если команда обычная — используется операнд из ROM; если LDAX или STAX — значение IX.

Одно устройство, два источника адреса, один переключатель. На уровне 2.21 ты впервые подключаешь BusMUX и знакомишься с индексным регистром — а в готовом компьютере именно такой мультиплексор выбирает источник адреса RAM.

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

Чистим 100 ячеек тремя командами

Классический пример — обнулить массив из 100 байт. Вместо 100 команд STA хватает трёх в цикле:

LDX 0       ; IX = 0 — стартовый адрес
loop:
LDA 0       ; Acc = 0 — значение для записи
STA [IX]    ; RAM[IX] = 0 — очистить ячейку
INX         ; IX = IX + 1 — следующий адрес
; проверка, не прошли ли мы 100 ячеек,
; и условный переход обратно на loop

Обрати внимание на ритм: STA [IX] пишет по текущему адресу, INX сдвигает указатель, и цикл повторяется. Условие выхода — проверку «IX дошёл до 100» и условные переходы — мы разберём в статье про ветвления и циклы.

Частые ошибки

1. Забыть LDX перед LDAX/STAX: указатель содержит мусор, и данные улетят неизвестно куда.

2. Путать LDAX и LDA: LDA [IX] читает по указателю, а не загружает число.

3. Сдвигать указатель до записи: сначала STA [IX], потом INX.

Резюме

1. Индексный регистр IX — 8-битный указатель на ячейку памяти.

2. LDX N устанавливает указатель, INX двигает его вперёд на 1.

3. LDA [IX] и STA [IX] читают и пишут по адресу из IX (это LDAX и STAX).

4. За выбор адреса отвечает BusMUX: операнд из ROM против IX.Q, управляет сигнал UseIX.

5. Один цикл из трёх команд очищает целый массив — без указателей это были бы сотни строк.

На уровне 2.21 тебе предстоит подключить первый BusMUX — он выбирает источник данных для АЛУ (RAM или операнд команды) — и выставить счётчику команд шаг +2. Адресный BusMUX, описанный выше, появится в готовой разводке следующих уровней — там LDAX и STAX заработают в полную силу.

Попробовать в симуляторе →