Указатели и индексные регистры (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 N | 9 | IX = N — загрузить адрес в указатель |
| INX | 13 | IX = 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 заработают в полную силу.