В этом посте:

Ассемблер

Эмулятор СМ-1800 загружает образ памяти, внутри которого находится программа. Эта программа написана в виде машинного кода. Есть несколько вариантов, как создать этот машинный код.

Один из вариантов – это просто написать этот машинный код вручную. Это довольно неудобно для программиста: во-первых, большинство из опкодов не соответствуют клавишам на клавиатуре, и поэтому это необходимо писать в hex-редакторе; во-вторых, там нет места для комментариев; и вообще, это очень неудобно делать, хотя строго говоря и возможно.

Ещё во времена создания Intel 8080 было понимание, что писать машинный код вручную – это очень неудобно. Второй способ создавать машинный код – это написать его в промежуточном языке – ассемблере – который затем будет переведен в машинный код программой-ассемблером. (В русском языке оба понятия называются одним словом, что может быть непонятным; в английском языке программа называется assembler, а язык – assembly language. В этом тексте я буду называть язык “ассемблер”, а программу – “программа-ассемблер”.)

Третий вариант – использовать какой-то компилируемый язык, вроде C, и компилировать его в машинный код для данного процессора – наиболее удобен для разработки программ, но он уходит слишком далеко от сути работы с компьютером вроде СМ-1800. Чем более язык программирования высокоуровневый, тем больше он стремится скрыть детали того, как работает само оборудование компьютера, чтобы программист смог концентрироваться на решении сложной задачи.

Для образования же полезно спуститься вниз, на уровень, где внутреннее строение компьютера будет видно, чтобы разобраться в том, как он устроен. Ассемблер лишь на один шаг отдален от машинного кода, но C находится гораздо дальше от железа: понятия вроде “переменные” и “операторы” не существуют на уровне процессора, там есть только “регистры” и “опкоды” – а к ним получить доступ, работая в C, уже невозможно.

Несмотря на это, если бы вы попробовали улучшить ассемблер, добавляя к нему синтаксис для работы над переменными и операторами, то в итоге у вас бы получилось нечто, что было бы очень похоже на C. Недаром C иногда в шутку называют “портативным ассемблером”.

Мы же будем работать с обычным ассемблером, а именно с ассемблером для Intel 8080 – процессора, который лежит в основе компьютера СМ-1800.

Установка ассемблера Suite8080

Существует несколько разных ассемблеров для Intel 8080, для разных платформ и с разными спецификами. В этих постах я буду использовать ассемблер (и дисассемблер) из проекта Suite8080.

Эти инструкции предназначены для пользователей Windows, потому что сам эмулятор СМ-1800, который мы используем, работает на Windows. Ассемблер написан на Python, поэтому будет работать и на Linux, macOS и других более эзотеричных платформах, где есть интерпретатор Python – EXE-файлы создал я из исходного кода Python с помощью PyInstaller.

Программа EXE-файлы (для большинства пользователей) Исходный код (для продвинутых пользователей)
Ассемблер asm80.exe asm80.py

Использование ассемблера

Этот ассемблер имеет некоторые ограничения, которые могут вызывать неудобства в написании кода. Самое значительное неудобство в том, что строки, заданные с помощью директивы DB, не могут содержать символ запятой:

; это не будет работать
fail: DB 'Hello, world!', 0

Эта проблема будет решена в будущих версиях программы. Пока это не решено, вы можете вводить символ запятой как отдельный аргумент директивы DB. Запятая имеет код 0x2c.

; будет работать
ok: DB 'Hello', 0x2C, ' world!', 0

Если вы заметите какие-то ещё ошибки, вы можете открыть Issue в репозитории моей версии Suite8080.

Самый простой способ использования программы-ассемблера в Windows – это положить ее в какую-то удобную папку (например, в папку проекта, или на рабочий стол), и затем перетащить файл с исходным кодом на иконку этой программы. Это действие запускает программу-ассемблер, передавая как аргумент файл с исходным кодом. (Также можно запустить программу из командной строки – asm80.exe test.asm или python asm80.py test.asm.)

Если сборка прошла успешно, то рядом с исходным кодом появится файл с расширением .cmd – это образ памяти для эмулятора. Если же произошли какие-то ошибки, то в окне терминала будет вывод, который будет указывать на строку с ошибкой, и другой вывод, который может быть полезен. Например, здесь я создал в программе метку helloworld, но пытался использовать метку hello_world, а она не определена. Чтобы закрыть окно с выводом ошибки, можно нажать клавишу Enter, или кнопку “Закрыть” у окна.

Пример сообщения об ошибке

Для того, чтобы проверить, что программа-ассемблер работает корректно, вы можете скачать этот пример кода на ассемблере и собрать его. В той же папке должен появиться файл hello-world.cmd. После этого, запустите эмулятор и выберите пункт Открыть дамп памяти в меню Файл.

Открыть дамп памяти

Выберите файл hello-world.cmd и нажмите кнопку Открыть. После этого запустите программу, введя команду G4000. Если все прошло успешно, то вы увидите на экране несколько строк текста.

После того, как вы убедились, что программа-ассемблер работает корректно, вы можете начать писать свои программы на ассемблере. В следующей статье мы рассмотрим, какие приемы можно использовать, чтобы делать это.