Skip to main content

33. Программирование CPU

33. Программирование CPU

🎯 Цель урока
Научиться загружать программы в память и выполнять их на собранном процессоре.

🧠 Теория (10 мин)

Как программа попадает в CPU?

    1. Написать программу (ассемблер)
    2. Транслировать в машинный код
    3. Загрузить в RAM
    4. Сбросить PC в 0
    5. Запустить тактовый генератор

Память программ

В простейшем случае — DIP-переключатели или EEPROM:

    Адрес 0: [SW][SW][SW][SW][SW][SW][SW][SW] = 0x1E (LDA 14)
    Адрес 1: [SW][SW][SW][SW][SW][SW][SW][SW] = 0x2F (ADD 15)
    Адрес 2: [SW][SW][SW][SW][SW][SW][SW][SW] = 0xD0 (OUT)
    ...

🔧 Варианты памяти программ

Вариант 1: DIP-переключатели

    Для 16 байт RAM:
    - 16 × 8-позиционных DIP = 128 переключателей 😱
    
    Хорошо для отладки, плохо для реальных программ.

Вариант 2: EEPROM (AT28C16)

    AT28C16 — 2K × 8 EEPROM
    
    Программируется с помощью T48 программатора!
    
    ┌───────────────────┐
    │     AT28C16       │
    │                   │
    │  A0-A10 ◄── адрес │
    │  D0-D7 ──► данные │
    │  ~CE, ~OE         │
    └───────────────────┘

Вариант 3: Ручной ввод через кнопки

    [Адрес: 4-bit DIP] [Данные: 8-bit DIP] [WRITE кнопка]
    
    Процедура:
    1. Установить адрес
    2. Установить данные
    3. Нажать WRITE
    4. Повторить для следующего адреса

📋 Практика: Загрузка программы

Программа: Счёт 0-5

    ; Считать от 0 до 5 и остановиться
    
    0: LDI 0      ; 50 — A = 0
    1: OUT        ; D0 — вывести
    2: ADD 15     ; 2F — A += 1
    3: SUB 14     ; 3E — A -= 6 (сравнение)
    4: JZ 7       ; 87 — если 0, конец
    5: ADD 14     ; 2E — A += 6 (восстановить)
    6: JMP 1      ; 61 — повтор
    7: HLT        ; F0 — стоп
    
    ; Данные:
    14: 06        ; число 6
    15: 01        ; шаг 1

Машинный код

АдресHexДвоичный
0500101 0000
1D01101 0000
22F0010 1111
33E0011 1110
4871000 0111
52E0010 1110
6610110 0001
7F01111 0000
14060000 0110
15010000 0001

🔬 Пошаговое выполнение

Отладка: режим Single-Step

    CLK: ручной (кнопка) vs автоматический (555)
    
    В режиме single-step:
    1. Нажал кнопку → один такт
    2. Посмотрел состояние (PC, A, FLAGS, BUS)
    3. Нажал снова → следующий такт

Трассировка выполнения

ТактPCIRAШинаДействие
00XX50Fetch: IR=50
115000LDI 0: A=0
2100D0Fetch: IR=D0
32D00000OUT: display=0
42002FFetch: IR=2F
532F0101ADD 15: A=0+1=1

💡 Инструменты программирования

Ассемблер на Python

# Простейший ассемблер для SAP-1

opcodes = {
    'NOP': 0x0, 'LDA': 0x1, 'ADD': 0x2, 'SUB': 0x3,
    'STA': 0x4, 'LDI': 0x5, 'JMP': 0x6, 'JC': 0x7,
    'JZ': 0x8, 'AND': 0x9, 'OR': 0xA, 'XOR': 0xB,
    'NOT': 0xC, 'OUT': 0xD, 'INP': 0xE, 'HLT': 0xF
}

def assemble(line):
    parts = line.upper().split()
    if not parts:
        return None
    
    mnemonic = parts[0]
    operand = int(parts[1]) if len(parts) > 1 else 0
    
    return (opcodes[mnemonic] << 4) | (operand & 0xF)

# Пример:
program = [
    "LDI 0",
    "OUT",
    "ADD 15",
    "JMP 1",
]

for addr, line in enumerate(program):
    code = assemble(line)
    print(f"{addr:2d}: {code:02X}  ; {line}")

Вывод:

 0: 50  ; LDI 0
 1: D0  ; OUT
 2: 2F  ; ADD 15
 3: 61  ; JMP 1

📝 Программы для практики

Программа 1: Фибоначчи

    ; Вычислить числа Фибоначчи: 1, 1, 2, 3, 5, 8...
    
    0: LDI 1      ; A = 1 (первое число)
    1: STA 14     ; F1 = 1
    2: STA 15     ; F2 = 1
    3: OUT        ; Вывести F2
    4: ADD 14     ; A = F2 + F1
    5: STA 14     ; Сохранить в F1 (было F2)
       ... (обмен F1 ↔ F2)

Программа 2: Бегущий огонь

    ; Бит сдвигается: 1, 2, 4, 8, 16...
    
    0: LDI 1      ; A = 00000001
    1: OUT        ; Вывести
    2: ADD 15     ; A = A + A (сдвиг влево!)
    3: JC 0       ; Если переполнение, начать сначала
    4: JMP 1      ; Иначе повтор
    
    15: (data) = копия A (для удвоения)

Программа 3: Детектор простых чисел

    ; Проверить, является ли N простым
    ; (упрощённо: проверка делимости на 2 и 3)
    
    Сложно для 4-бит адресации!
    Но показывает пределы простой архитектуры.

🔧 Загрузка через T48

Если используем EEPROM:

  1. Написать программу в hex-файл
  2. Подключить AT28C16 к T48
  3. Записать hex-файл в EEPROM
  4. Установить EEPROM в панельку на плате CPU
  5. Запустить!
    Intel HEX формат:
    :10000000501F2FD061F00000000000000000000032
    :00000001FF

📝 Мини-задания

Сколько тактов нужно для одной инструкции?

Ответ: Минимум 2 (Fetch + Execute), может быть больше для сложных инструкций

Почему A = A + A эквивалентно сдвигу влево?

Ответ: В двоичной системе умножение на 2 = сдвиг влево на 1 бит

Как остановить бесконечный цикл?

Ответ: Нажать RESET или отключить тактовый генератор


✅ Чеклист

  • Могу транслировать программу в hex
  • Понимаю пошаговое выполнение
  • Могу загрузить программу в память
  • Отладил программу в single-step режиме

➡️ Следующий урок

34. 🏆 Финальный проект: 8-битный компьютер →