Руководство по ассемблеру

Архитектура процессора

На 16-м уровне вы собираете 8-битный компьютер по гарвардской архитектуре с раздельной памятью команд и данных:

Панель ассемблера

При наличии ROM на схеме в правой панели появляется вкладка «Ассемблер». Она содержит:

Формат инструкции

Каждая инструкция — 1 байт. Старшие 4 бита (7:4) — opcode, младшие 4 бита (3:0) — operand (адрес 0–15).

 7 6 5 4  3 2 1 0
┌────────┬─────────┐
│ Opcode │ Operand │
└────────┴─────────┘

Система команд

МнемоникаOpcodeДействиеПример
NOP 0 No operation NOP0x00
ADD 1 Acc = Acc + RAM[X] ADD 30x13
SUB 2 Acc = Acc − RAM[X] SUB 70x27
AND 3 Acc = Acc & RAM[X] AND 10x31
OR 4 Acc = Acc | RAM[X] OR 20x42
LDA 5 Acc = RAM[X] LDA 50x55
STA 6 RAM[X] = Acc STA 100x6A
JMP 7 PC = X (безусловный переход) JMP 00x70
JZ 8 if Acc=0: PC = X (условный переход) JZ 70x87
HLT 15 Останов тактирования HLT0xF0

Правила синтаксиса

Пример программы: компиляция и выполнение

; Простейшая программа — 4 инструкции
LDA 5
ADD 3
STA 0
HLT

После нажатия ▶ Выполнить программа компилируется и сразу запускается. В панели лога появятся строки компиляции:

[AsmPanel] === Compile & Run ===
[Asm]  ROM[0] = 0x55  (LDA 5)
[Asm]  ROM[1] = 0x13  (ADD 3)
[Asm]  ROM[2] = 0x60  (STA 0)
[Asm]  ROM[3] = 0xf0  (HLT)
[Asm] Compile done: 4 instruction(s)
[Asm] ROM[0..3]: 0x55 0x13 0x60 0xf0

Затем — строки выполнения (только нечётные тики — rising edge):

[AsmPanel] PC=0, play
[CPU] Tick 1   PC=0  →  LDA 5   [0x55]
[CPU] Tick 3   PC=1  →  ADD 3   [0x13]
[CPU] Tick 5   PC=2  →  STA 0   [0x60]
[CPU] Tick 7   PC=3  →  HLT     [0xf0]
[HLT] PC=4 (prev=3) instruction=0xf0 → HALT detected, stopping

Важно: инициализация RAM

LDA 5 загружает значение из RAM[5], а не константу 5. Поскольку вся RAM при старте заполнена нулями, аккумулятор после LDA 5 будет равен 0. ADD 3 добавит RAM[3] = 0. Результат всегда 0.

Для осмысленной работы с данными инициализируйте RAM через консоль браузера (F12 → Console) перед нажатием «Выполнить»:

const ram = graph.findNodesByType('tc/RAM')[0];
ram.memory[5] = 5;   // RAM[5] = 5
ram.memory[3] = 3;   // RAM[3] = 3

После инициализации и выполнения LDA 5; ADD 3; STA 10; HLT в RAM[10] будет записано 8.

Пример: работа с данными

; Загрузить значение из RAM[10], удвоить, сохранить в RAM[11]
LDA 10    ; Acc = RAM[10]
ADD 10    ; Acc = Acc + RAM[10] = RAM[10] * 2
STA 11    ; RAM[11] = Acc
HLT

Пример: условный переход (JZ)

; Тест JZ: если аккумулятор = 0 — переход на адрес 5
LDA 0     ; Acc = RAM[0] = 0
ADD 0     ; Acc = 0 + 0 = 0 (Zero flag = 1)
JZ  5     ; Jump to addr 5 (срабатывает)
STA 15    ; ← пропускается
HLT       ; ← пропускается
NOP       ; адрес 5 — точка перехода
HLT       ; останов здесь

Чтение памяти через консоль

// Проверить содержимое RAM после выполнения программы
const ram = graph.findNodesByType('tc/RAM')[0];
console.log('RAM[10]:', ram.memory[10]);
console.log('RAM[11]:', ram.memory[11]);

// Проверить содержимое ROM после компиляции
const rom = graph.findNodesByType('tc/ROM')[0];
const hex = Array.from(rom.memory.slice(0, 8))
  .map(b => '0x' + b.toString(16).padStart(2, '0')).join(' ');
console.log('ROM[0..7]:', hex);

Как выполняется инструкция (2 тика на команду)

Каждая инструкция занимает ровно два такта Clock. На первом (фронт 0→1) происходит выборка и выполнение, на втором (спад 1→0) — фиксация результата:

Тик N   (0→1): PC выдаёт адрес → ROM → Splitter → Decoder → ALU/RAM
                  Результат готов, но ещё не записан в регистры.

Тик N+1 (1→0): Регистры захватывают данные. PC не меняется.

Именно поэтому в логе инструкции отображаются только на нечётных тиках (1, 3, 5, …) — это rising edge, когда инструкция реально выполняется.

Что пишется в лог-панель

ПрефиксКогда появляется
[Asm]Компиляция: каждая инструкция и итоговый дамп ROM
[AsmPanel]Нажатие ▶ Выполнить — этапы компиляции и запуска
[CPU]Каждый нечётный тик — выполняемая инструкция
[HLT]Обнаружение HALT — тактирование остановлено

Лог очищается при каждом нажатии ▶ Выполнить перед компиляцией. История между запусками не сохраняется.

Пример: безусловный переход (JMP)

; Бесконечный цикл между адресами 2 и 3
LDA 0
STA 15
JMP 2     ; ← возврат на JMP (цикл)
HLT       ; никогда не выполнится

Программа зациклится — HLT не сработает. Нажмите ⏸ Pause на панели Clock Control для остановки. В логе убедитесь, что PC зацикливается на 2.

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

При RAM[10] = 7 (установлено через консоль):

LDA 10    ; Acc = RAM[10]
ADD 10    ; Acc = Acc + RAM[10] = RAM[10] * 2
STA 11    ; RAM[11] = Acc
HLT
ТикPCИнструкцияАккRAM[10]RAM[11]
10LDA 10770
31ADD 101470
52STA 1114714
7HLT

Горячие клавиши

КлавишаДействие
F9Запустить проверку уровня
F12Открыть консоль разработчика
DeleteУдалить выделенный элемент

Известные ограничения

Перейти к симулятору →