Skip to content

Ассемблер на Python: язык для своей машины

Паспорт модуля

ПараметрЗначение
Аудитория🟡🔴; пройден М13; Python на уровне функций и словарей
Аутентичная задачаизбавиться от ручной адресации навсегда: писать программы с метками, транслировать в .hex и заливать в машину одной командой
Объём4 занятия × 90 мин
ОборудованиеПК с Python 3, машина из М13, RP2350-загрузчик
Ограничения
Аутентичная задача. После модуля обучающиеся смогут: пройти полный тулчейн prog.asm → asm.py → prog.hex → загрузка → исполнение и объяснить, зачем ассемблеру два прохода, — на примере боли из М13.

Цели

Обучающиеся …Блум—АндерсонМиллерПроверка
1объясняют проблему прямых ссылок и идею двух проходовпониматьзнаетквиз
2реализуют ассемблер: мнемоники, метки, .org, .byte, вывод .hexсоздаватьделаеттест-набор из 6 исходников, включая ошибочные
3реализуют эмулятор ISA и сверяют его с железомсоздавать/анализироватьделаетФибоначчи: эмулятор и машина дают одинаковую последовательность OUT
4проектируют осмысленные сообщения об ошибкахоценивать/создаватьделаетревью: 3 класса ошибок диагностируются с номером строки

Оценивание

Тест-набор трансляции (итог): корректные исходники → байт-в-байт эталонные .hex; исходники с неизвестной мнемоникой / дублем метки / переходом на несуществующую метку → внятная ошибка со строкой, а не трейсбек. Кросс-проверка эмулятор↔железо — обязательный пункт: расхождение считается находкой (чаще всего оно вскрывает недокументированное поведение микрокода — ценнейший разговор).

Путь и ядро

ТемаРазминкаЯдро
1Два прохода«почему сдвинулся halt» (М13)worked example: проход 1 собирает таблицу меток, проход 2 генерирует байты
2Ассемблертаблица опкодов по памятиреализация + тест-набор
3Эмулятор3 вопроса зан. 2цикл fetch-decode-execute на Python — те же фазы, что в микрокоде: третья встреча с ISA
4Тулчейнкумулятивный квиз М12–М14связка с загрузчиком М10; Фибоначчи с метками — сравнить читабельность с листингом М13

Скелет (учебный, обучающиеся достраивают):

OPS = {"NOP":0x00,"LDA":0x01,"ADD":0x02,"SUB":0x03,"STA":0x04,
       "LDI":0x05,"JMP":0x06,"JC":0x07,"JZ":0x08,"OUT":0x0E,"HLT":0x0F}
NOARG = {"NOP","OUT","HLT"}

def assemble(lines):
    labels, pc = {}, 0
    for ln in cleaned(lines):                 # проход 1: адреса меток
        if ln.endswith(":"): labels[ln[:-1]] = pc
        else: pc += 1 if ln.split()[0] in NOARG else 2
    out, pc = bytearray(), 0
    for ln in cleaned(lines):                 # проход 2: кодогенерация
        if ln.endswith(":"): continue
        op, *arg = ln.split()
        out.append(OPS[op])                   # + диагностика KeyError -> "строка N: неизвестная мнемоника"
        if op not in NOARG:
            out.append(resolve(arg[0], labels))  # число 0x.. или метка
    return out
Методический стержень: это третья реализация одной ISA (микрокод → эмулятор → далее Verilog). Интервальный возврат встроен в архитектуру программы: обучающийся не «повторяет материал», а переизобретает его в новом медиуме — глубочайшая форма retrieval practice.
Типичные ошибки: пути меток считаются во втором проходе «на лету» — прямые ссылки ломаются (возврат к идее двух проходов); LDI с адресом вместо константы — семантика перепутана (в тест-наборе есть ловушка на это); эмулятор флагов «почти как железо»: C после SUB — сверить с реальным поведением АЛУ М4 (нет заёма → C=1), расхождение эмулятора и макетки здесь — запланированный обучающий конфликт.

Уровни

Глоссарий