SjASMPlus 1.20.2 справочная информация [2023-02-14]


1. Вступление
Лицензия
Что это?
Основные характеристики
Благодарности
Обратная связь
Список изменений
2. Где взять и как использовать программу
Исполняемые файлы и исходники
Опции командной строки
Предупреждения с идентификатором
Формат исходного файла
3. Метки
Метки
Локальные метки
@ Метки
Временные метки
4. Константы, выражения и другие функции
Числовые константы
Символьные и строковые константы
Выражения
Язык ассемблера
Нестандартные инструкции
Режим эмуляции реального устройства
Предопределенные определения
5. Псевдо-операции (псевдо-инструкции, директивы и т.д.)
Простой пример использования
Псевдо-операции
Условная компиляция
Макросы
6. Структуры
Что такое структуры?
Описание структуры
STRUCT инструкции
Применение описанной структуры
Примеры
7. Написание сценариев на Lua
Почему?
Как использовать?
Привязки функций SjASMPlus к Lua
Встроенные библиотеки сторонних производителей
Примеры
8. Руководство по SAVENEX
Формат файлов NEX
Подробное описание команд SAVE NEXT
Примеры
9. Данные отладки на уровне источника (SLD)
Что это?
Применение
Как написать "не хитрый" исходный код
Описание формата SLD файла (версия "1")
Предметный указатель

Глава 1. Введение

Лицензия

SjASMPlus лицензируется по лицензии BSD.

Что это?

SjASMPlus - это кросс-компилятор языка ассемблера Z80. Он доступен для систем Win32, Linux и FreeBSD (в основном 5.x). Он основан на sjAsm исходный код от Sjoerd Martijn(http://xl2s.tk).

Основные характеристики

  • Полный исходный код ассемблера доступен по лицензии BSD, модифицируйте и расширяйте по своему усмотрению

  • Поддержка документированных и недокументированных кодов операций процессоров Z80/R800/Z80N/i8080/LR35902

  • Макроязык, определения, массив определений

  • Встроенный скриптовый движок Lua

  • Условная сборка, повторяющийся блок

  • Модули (пространства имен), локальные и временные метки

  • Source and binary file inclusion, include paths

  • Вывод нескольких файлов, обновление файлов, различные типы экспорта

  • Структуры для легкой работы со структурированными данными в памяти

  • Генератор данных перемещения для поддержки символьного перемещения исполняемых файлов

  • Режим виртуального устройства для обычных машин: ZX 128, ZX Next, Amstrad CPC, ... (псевдо-операционное УСТРОЙСТВО)

  • Директивы, специфичные для ZX Spectrum, и псевдо-операции (SAVESNA, SAVETAP, SAVEHOB, INCHOB, INCTRD,...)

  • Специфические функции и директивы ZX Spectrum Next (Z80N, подкачка памяти 8ki, СОХРАНИТЬ ДАЛЕЕ)

  • Специальные директивы Amstrad CPC 464/6128 (SAVECPCSNA)

  • Корректность обеспечивается Cirrus-CI с более чем 400 автоматизированными тестами (это также более 400 примеров использования!)

  • Специальные инструкции, такие как LD HL,DE (LD H, D:LD L, E) и многое другое

  • Code inlining through colon (LD A,C:INC A:PUSH AF:IFDEF FX:LD A,D:ENDIF). Позволяет писать несколько команд в строке

  • Очень быстрая компиляция: 1 миллион строк за 2-3 секунды на современном компьютере

  • Многострочный блок комментариев и сообщений пользователя

Участники проекта

Особая благодарность Sjoerd Mastijn,автору sjAsm.

Aprisobal - основное программирование, документация и т.д.

Thanks to:

  • Kurles/HS/CPU, Alexander Kovalenko, Ped7g, Dart Alver, Oli Wilkinson - дополнительное программирование;

  • Krystian Wlosek <kwlosek(at)gmail.com> - исправления ошибок, makefile для Linux;

  • Ric Horne <Ric.Hohne@eads-ts.com> - исправления ошибок.

  • breeze <breeze@tut.by> - исправления ошибок.

  • psndcj <psndcj.tbk@gmail.com> - сообщения об ошибках, бета-тестирование.

  • elfh <elphecy@gmail.com> - сообщения об ошибках.

  • bugsy <bugsy@ya.ru> - сообщения об ошибках.

  • skrju <sq-@mail.ru> - сообщения об ошибках.

  • Tygrys, UB880D, Cizo, mborik, z00m - очистка ошибок компиляции и предупреждений, создание файлов, тестирование.

  • Antipod, boo_boo, PulkoMandy, Busy, Liniya, LVD - исправления ошибок, тестирование.

  • CKirby - Экспорт SLD и поддержка в его инструментах.

  • Simon Brattel - за создание матери всех ассемблеров Zeus и принесение всего добра и мира человечеству, бесконечное вдохновение авторам sjasmplus, которые украли его невероятно удивительные функции, даже не поставив ему в заслугу - до сих пор исправлено (не уверен, какой конкретный список функций был скопирован с Zeus, я думаю, DG / DH, Я полагаю, что некоторые другие сходства скорее скопированы с ALARM, у которого было много функций до Zeus, но кто знает, слишком поздно отслеживать все это точно, что произошло в 90-х и когда).

Большое спасибо всем людям, которые помогали в разработке компилятора!

Обратная связь

WWW: https://github.com/z00m128/sjasmplus (более новые версии, поддерживаемые z00m и другими)

WWW: https://sourceforge.net/projects/sjasmplus/ (оригинальный источник Aprisobal)

E-Mail: zoom@centrum.sk, my@aprisobal.by

Что нового?

14.2.2023 - 1.20.2
- добавлен необязательный второй аргумент для `DUP` имеющую индексную переменную
- опция `--exp` создаст файл, даже если `EXPORT` не используется
- исправлен конфликт имен переменных при компиляции с musl-libc
- Обновлен LuaBridge, немного обновлены CMake и Makefile
- незначительные исправления / улучшения в синтаксическом анализаторе в конкретных крайних случаях
29.7.2022 - 1.20.1
- разбор десятичных  числовых констант с предупреждением (для упрощения работы с Lua 5.4)
- добавлено `SAVEAMSDOS` (как, например, SAVEBIN с заголовком AMSDOS)
- добавлен "умный" синтаксис SMC offset для меток с самоизменяющимся кодом: `abc+*: или 123`
- добавлен `DEFDEVICE` для определения пользовательских устройств
- Очистка Makefile
13.6.2022 - 1.20.0
- Lua: upgrade to 5.4, обновление до версии 5.4, замена привязок tolua++ библиотекой LuaBridge2.6, расширение некоторых привязок
- Lua: слегка изменены привязки (требуется при обновлении), обновлены документы, добавлено тестовое покрытие
- Lua: сторонние расширения (кстати, не работающие уже много лет) устарели в версии 5.4 и удалены
- Lua: более точное местоположение ошибок / предупреждений, сообщаемое даже в сложных случаях
- предупреждения: добавлено -Wall, --help=warnings shows on/off status, rdlow выключен по умолчанию
- Добавлен Высший приоритет для relocation data generator генератор данных о перемещении (режим перемещения только для MSB)
- многие "фатальные" ошибки при открытии файла становятся "нефатальными", сборка будет продолжена
- удалены устаревшие функции: --syntax=m, метка `abs` в выражениях
- `--color=auto` останется no-color, когда env.var. `NO_COLOR` определен
- рефакторинг, улучшение некоторых сообщений об ошибках и синтаксического анализа, небольшие исправления в логике синтаксического анализа
- исправлен список sj.parse_code Lua (eol-комментарии), исправлены незначительные утечки памяти
- исправлено перемещение временных меток в выражениях
- недопустимые параметры CLI отображаются как обычные ошибки (также изменяется код выхода)
- ошибки окрашиваются аналогично gcc (только ключевое слово имеет цвет), имя ввода консоли - `<stdin>`
31.3.2022 - 1.19.0
- добавлены устройства Amstrad CPC("AMSTRADCPC464", "AMSTRADCPC6128") - автор: Оли Уилкинсон
- добавлены Amstrad CPC для сохранения моментального снимка и CDT(`SAVECPCSNA`, `SAVECDT`) -автор: Оли Уилкинсон
- добавлен `SAVE3DOS` (как, например, SAVE BIN с заголовком +3DOS)
- устаревшее подавление предупреждения "ok" удалено, используйте комментарий "<warning-id>-ok" или -Wno-...
- новые temporary label синтаксис суффикса временных меток  "_b" и "_f", позволяющий использовать их для всех выражений
- - исправлен режим `--long ptr` для сохранения адреса 32 битных чисел при использовании `DS 0`
- добавлены псевдоинструкции adc|add|sbc|sub de,bc|de|hl|sp
- dec|inc|pop|push также будут принимать многозначные символы с одной запятой в режиме --syntax=a
- - DUP /REPORT теперь также будет принимать нулевое количество (пропуская блок)
- Метки DEFL могут быть определены даже на последнем проходе
- - исправлены ошибки (макросы, список, имена файлов с ошибками, обратные всплывающие данные SLD)
29.8.2021 - 1.18.3
- добавлен режим `--color` чтобы включить/отключить ANSI-раскраску ошибок/предупреждений
- добавлен режим `--syntax=s` для отключения подстановки вложенных слов в DEFINEs
- добавлен префикс at-sign macro local labels для локальных меток макросов, чтобы действовать как локальная метка, не относящаяся к макросу
- `SAVETRD` принимает имена, содержащие точку ("z.x.B" - это "z.x" с расширением "B") - автор Dart Alver
- `SAVETRD` имеет необязательный аргумент для сохранения BASIC с переменными (length_minus_variables)
- незначительные исправления ошибок (анализатор условных блоков)
14.2.2021 - 1.18.2
- [может нарушить работу старых исходников] новый оператор exist exist operator для проверки существования метки
- режим --syntax=i теперь также делает синтаксический анализ регистра нечувствительным к регистру
- незначительные исправления ошибок (предопределенные значения, загрузчик savenext BMP менее строг в отношении содержимого "colors used")
23.1.2021 - 1.18.1
- Поддержка хостов Big-Endian (экспериментальная и не тестируемая постоянно)
- добавлены команды "list all", "list act" OPT - для переключения между типами списков
- `WHILE` имеет необязательный аргумент для установки защиты счетчика (максимальное количество итераций)
- `ASSERT` имеет необязательный аргумент (для добавления описания / примечаний к выражению)
- `SLOT` и `MMU` теперь будет приниматься также начальный адрес слота вместо его номера
- исправлено: опция --sym не экспортировала метки, начинающиеся с подчеркивания
- исправлено: ошибка SAVE NEXT BMP, когда некоторые сборки sjasmplus не могли открывать файлы BMP
- исправлено: после экземпляра STRUCT метка "main" не загрязняется последним полем STRUCT
- незначительные исправления в синтаксическом анализаторе, windows cmake-сборки теперь имеют значок
- документы: добавление раздела "Индекс"
- документы: добавление некоторой недостающей информации (__DATE__, __TIME__), исправление имен привязок HTML
12.12.2020 - 1.18.0
- [может нарушать работу старых исходников] двоеточие между концом  EQ/DEFL/=выражение  и инструкцией обязательно
- [может нарушать работу старых исходников] новый abs оператор для вычисления абсолютного целого значения
- новая система предупреждений (и подавление), комментарии "; ok" теперь не рекомендуются
- `DISPLAY` теперь имеет также двоичное форматирование и форматирование символов
- добавлено `DEFINE+`  позволяет [повторно] определить идентификатор без сообщений об ошибке
- `ELSEIF` добавлен в арсенал условной сборки
- `WHILE` добавлено для условных циклов
- добавлено устройство "NOSLOT64K" с 2 Мб виртуальной памяти
- `LABELSLIST` имеет новый необязательный аргумент для вывода 16-битных "виртуальных меток" в файл
- `CSPECTMAP` экспортирует символы STRUCT  с более подробной информацией (метки экземпляров с физическим адресом)
- SMC offset синтаксис для самоизменяющихся меток кода для краткости исходного кода
- добавлен префикс восклицательного знака для labels чтобы не влиять на следующие локальные метки
- добавлена команда "list mc" для OPT - перечислять только строки с байтами машинного кода
- добавлено `--lstlab=sort` способ размещения символов в списках в определенном порядке
- незначительные исправления в синтаксическом анализаторе и перечислении-нумерации строк, переработанная реализация символов / меток
- Добавлен example (chargfx2asm)  - как использовать sjasmplus в качестве байтового процессора для двоичных файлов
- SLD data улучшения, основанные на отзывах Maziac's совместимости с  DeZog 
8.8.2020 - 1.17.0
- `STRUCT` имеет новые `TEXT` псевдо-инструкция для определения "DB-подобных" данных (Issue #93)
- блок инициализатора `STRUCT`  теперь может быть многострочным (при правильном заключении в фигурные скобки)
- `EQU` теперь допускает необязательное переопределение номера страницы, присвоенного новому символу
- новые $$$ и $$$$ операторы  позволяют получить "физический" адрес/страницу внутри блока DISP
- команда `out (c),0` теперь выдает предупреждение (может быть подавлена комментарием "; ok")
- исправлено перечисление структур с использованием длинных блочных (BLOCK) полей (машинный код был правильным, но перечисление нет)
- исправлены некоторые утечки памяти, неопределенное поведение и несогласованный доступ к памяти
27.7.2020 - 1.16.0
- `LUA` новое предупреждение об эмиссии (версия v1.15.1) теперь можно отключить
- Предопределенные определения расширены и переименованы (в соответствии с gcc / clang)
- добавлен генератор перемещаемых данных  (аналогично функции WinAPE), проверьте также пример
- исправления / улучшения в синтаксическом анализаторе, такие как: за операторами "not", "low", "high" также может следовать "("

Смотри CHANGELOG.md с полным списком изменений

Глава 2. В Где взять и как использовать

Пакеты

The Последняя версия этой версии программы sjasmplus variant доступна по ссылке: https://github.com/z00m128/sjasmplus/releases/latest - доступен zip-архив с двоичным файлом Windows (внизу страницы), и zip архив с исходным кодом компилятора sjasmplus.

Пакет Win32 имеет:

  • sjasmplus.exe - исполняемый файл Win32.

  • каталог примеров - некоторые примеры использования

  • каталог документации - документация в различных форматах

Возможно, вы захотите также загрузить полный исходный пакет, поскольку он содержит более 400 автоматизированных тестов используются для проверки корректности исполняемого файла, и они часто могут быть полезны для лучшего понимания того, как работает конкретная функция sjasmplus, и как её использовать эффективно.

Linux, Unix, MacOS и BSD версия может быть собрана из полного архива исходных текстов. Вы можете скомпилировать его с помощьюGCC и приложенного Makefile. Возможно использовать CMake для компиляции. Смотри подробности в файле INSTALL.md.

Исполняемые файлы Windows компилируются в среде MinGW приложенным Makefile.win файлом.

Вы можете получить более старые (до версии v1.07) исполняемые файлы и исходные тексты на странице проекта SourceForge: https://sourceforge.net/projects/sjasmplus/

Командная строка

Использование:

sjasmplus  [параметры]  исходный файл(ы)

Параметры применяются следующим образом:

  -h или --help[=warnings] Помощь
  --version                Основная информация (с --nologo только строка необработанной версии)
  --zxnext[=cspect]        Включить расширения ZX Next Z80 (эмулятор CSpect содержит дополнительные псевдо инструкции "exit" DD00 и "break" DD01)
  --i8080                  Использовать только инструкции i8080 (+ никаких псевдоинструкций)
  --lr35902                Режим инструкций процессора Sharp LR35902/SM83 (+ без псевдоинструкций)
  --outprefix=<path>       Префикс для сохранения/вывода/.. имен файлов в директивах
Примечание: если префиксом является папка, то папка должна существовать перед компиляцией. Префикс применяется только к именам файлов, определенным в исходном коде (не к аргументам CLI).
  -i<path> или -I<path> или --inc=<path> ( --inc без "=" чтобы очистить список) Включить путь (позже определенный с более высоким приоритетом)
  --lst[=<filename>]       Сохраните список в <filename> (<source>.lst по умолчанию)
  --lstlab[=sort]          Добавить таблицу символов [отсортированных] к файлу листинга
  --sym=<filename>         Сохраните таблицу символов в  <filename>
  --exp=<filename>         Сохраните экспорт в  <filename> (смотри псевдооперацию EXPORT)
  --raw=<filename>         Машинный код, сохранять также в <filename> (- это STDOUT)
  --sld[=<filename>]       Сохранить отладочные данные на уровне исходного кода в  <filename>
                           Имя по умолчанию: "<первое введенное имя файла>.sld.txt"
  Примечание: используйте OUTPUT, LUA/END LUA и другие псевдооперации для управления выводом
Логи:
  --nologo                 Не показывать сообщение о запуске
  --msg=[all|war|err|none|lst|lstlab]  Детализация сообщений Stderr (по умолчанию используется "все")
  Примечание: "lst" или "lst lab" превратят STDERR в файл списка (это приведет к конфликту с
  `--lst`, используйте только один из вариантов) и некоторые диагностические сообщения типа "все"
  опущены, поскольку они не являются частью списка файлов. "lst lab" выполняет сортировку символов.

  --fullpath               Показывать полный путь к файлу при ошибках
  Примечание: "полный путь" начинается с текущего рабочего каталога, а не с
корневой файловой системы (сборка MS_VS была исправлена таким образом, начиная с версии v1.15.0)
  --color=[on|off|auto]    Включить или отключить ANSI-раскраску предупреждений/ошибок
  Примечание: автоматическое обнаружение проверяет наличие переменной окружения TERM, и ее
содержимое проверяется на наличие подстроки "color" (например, "xterm-256color").

 Другое:
  -D<NAME>[=<value>]       Определить <NAME> как <value>
  -W[no-]<warning_id>      Отключает/включает определенный тип предупреждения
  -                        Считывает STDIN как исходный код (даже между обычными файлами)
  --longptr                Нет устройства: счетчик программ $ превысил 0x10000
  --reversepop             Включить обратный порядок всплывающих окон (как в базовой версии sjAsm)
  --dirbol                 Включить обработку директив с начала строки
  --nofakes                Отключить псевдоинструкции (то же, что и --syntax=F)
  --dos866                 Закодировать с кодовой таблицей Windows в DOS 866 (кириллица)
  --syntax=<...>           Отрегулируйте синтаксический анализ, подробнее читайте ниже.

Опция --lstlab=sort приведет к сортировке также других дампов символов (по списку): --sym, CSPECTMAP и LABELSLIST. Параметр --msg=lstlab всегда устанавливает сортировку "вклвключено" (опция "несортированный" отсутствует).

Значение параметра --syntax может состоять из нескольких букв, при пропуске буквы для конкретной функции будет использоваться значение по умолчанию:

  a      Разделитель с несколькими аргументами ",," (по умолчанию ",") (но dec|inc|pop|push также принимает ",")
  b      Круглые скобки всего выражения разрешены только для доступа к памяти (по умолчанию = immediate или memory)
  B      требуются скобки для доступа к памяти [] (по умолчанию = relaxed syntax (упрощенный синтаксис)), [] допускается в качестве дополнительного)
  f F    Псевдо инструкции: предупреждение / отключено (по умолчанию = включено)
  i      Инструкции/директивы без учета регистра (по умолчанию = требуется тот же регистр)
l L    Метки ключевых слов (регистры, инструкции, ...): предупреждение / ошибка (по умолчанию = без звука)
  M      Псевдоним "m" и "M" для "(hl)", чтобы использовать синтаксис, подобный 8080: ADD A,M
  s      Используйте только "простые" замены целых слов, без вложенных слов (начиная с версии v1.18.3)
  w      Опция предупреждений: сообщать о предупреждениях как об ошибках
  m      * УДАЛЕНО * в версии v1.20.0 используйте -Wno-rdlow

Незавершенная работа: опции "l" и "L" еще не реализованы, следующий пример также работает некорректно.

Т.е. --syntax=faBil изменит синтаксический анализатор для обработки исходной строки

hl:  Ld a,(hl),,de,hl

таким образом, можно выдавать предупреждения об использовании ключевого слова "hl" для метки, об использовании псевдо инструкции (ld de,hl) и компилировать (hl) в качестве числового выражения, а не доступа к памяти. Предупреждения о псевдо инструкциях могут быть подавлены для конкретной строки путем добавления любого комментария в конце строки, содержащего строку "fake", т.е. строка "ld de,hl ; fake DE=HL" будет компилирована без предупреждения. Опция "F" идентична опции "--no fakes"" и является предпочтительной.

Рекомендуемая настройка для новых проектов --syntax=abfw которая делает синтаксис более строгим, поэтому некоторые опечатки и ошибки легче обнаружить, например:

        OPT reset --syntax=abfw
label:  dw 15
        ld b,(label)
        sub a,b

выдаст сообщение: Illegal instruction (can't access memory) : (label)" ("ошибка: недопустимая инструкция (не удается получить доступ к памяти) ) сообщение для ld b,(label) и для sub a,b выдаст только команду sub b (чтобы предоставить мульти-аргумент sub с синтаксическим параметром "a", строка должна быть sub a,,b).

Ассемблер также прочитает переменную окружения SJASMPLUSOPTS (если она доступна) и обработает ее содержимое как часть параметров командной строки (перед фактическими параметрами), так что вы можете предварительно настроить определенные параметры в своей среде, например:

export SJASMPLUSOPTS="--zxnext=cspect --msg=war"
sjasmplus --lst --lstlab example.asm

сборка будет выполнена так, как если бы использовалась командная строка "sjasmplus --zxnext=cspect --msg=war --lst --lstlab example.asm". Известная проблема: анализатор переменной окружения разделяет каждый параметр любым символом пробела, поэтому параметр, содержащий символ пробела, будет неправильно проанализирован (например, "-Ifile-path с пробелом" приведет к сбою и нет способа экранировать / заключить путь в кавычки в переменной SJASMPLUSOPTS чтобы заставить его работать).

Предупреждения с идентификатором

Некоторые предупреждения имеют собственный "идентификатор" - их можно отключить или подавить для определенной строки. Механизм подавления строк требует, чтобы вы добавили комментарий в конце строки со текстом "id-ok" где-то в комментарии (исключение: для фиктивных инструкций и режима --syntax=f) слово "fake" достаточно без суффикса -ok) (механизм подавления комментариев "ok" из предыдущей версии sjasmplus удалены начиная с версии v1.19.0).

Предупреждение об идентификаторе выдается вместе с его идентификатором в скобках:

    ld a,(10-2)    ; считанный адрес памяти 8 - выдает предупреждение  "rd low" - "низкий уровень rd"
    ld a,(10-2)    ; та же инструкция, но подавляет предупреждение: rdlow-ok

file.asm(1): warning[rdlow]: Reading memory at low address: 8 (Чтение памяти по низкому адресу: 8)

Чтобы перечислить все идентификаторы предупреждений, их включение и выключение, краткое описание каждого предупреждения, введите строку:

<command line>$ sjasmplus --help=warnings

Большинство дополнительных предупреждений по умолчанию включены, но для включения / отключения всех из них вы можете использовать (также в исходном коде с директивой OPT):

<command line>$ sjasmplus -Wall
<command line>$ sjasmplus -Wno-all

Чтобы отключить конкретное предупреждение глобально, вы можете использовать опцию -Wno-<id>, либо в командной строке, либо из исходного кода, используя OPT:

<command line>$ sjasmplus -Wno-out0

; в исходном коде:
    OPT -Wno-trdext -Wno-trdext3 ; запретить предупреждения "trdext" и "trdext3"
        SAVETRD "image.trd", "file.txt", 30000, 100
    OPT -Wtrdext3                ; повторно включить предупреждение "trdext3" для следующего кода
; ...

Предупреждения без идентификатора не могут быть заблокированы и, как правило, должны появляться только тогда, когда исходный код содержит фактическую ошибку (по нашему мнению) и может быть изменен, чтобы исправить предупреждение, или когда вы выходите за пределы архитектуры и / или реализации sjasmplus.

Если вы считаете, что подавляете предупреждение без идентификатора для правильного исходного кода, которое можно безопасно игнорировать (созданный машинный код стабилен и соответствует ожиданиям), опубликуйте проблему на github с примером исходногокода, чтобы мы могли присвоить предупреждению новый идентификатор (или объяснить, почему это проблематично :) ).

Предупреждения с идентификатором обычно сигнализируют об ошибке в коде (в обычных сценариях), но могут вводить в заблуждение в более специализированных случаях - решение остается за автором, изменять ли код, чтобы избежать предупреждения, или подавлять его и использовать результирующий машинный код "как есть".

Формат файла с исходным кодом

Строки в исходном файле должны иметь следующий формат:

Метка Команда Операнд Комментарий

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

      Команда Операнд:Команда Операнд:Команда Операнд ... Комментарий

Комментарий начинается ';' или '//'. Блок комментариев нвчинается с'/*' и заканчивается '*/' (возможны "вложенные" комментарии, т.е. блок комментариев, начатый внутри блока комментариев, также должен быть завершен до завершения основного блока комментариев).

Пример 2.1.B 

; комментарий
// коментарий
 ld /* comment */ a,80
/*
 комментарий /* вложенный комментарий*/
*/
 ld /*
 но это не будет командой ld a,3!
 */ a,3


Глава 3.B Метки

Метки

Метки чувствительны к регистру и могут быть любой разумной длины, то есть примерно до 70 символов. Определения меток должны начинаться с начала строки, но за ними не обязательно должно следовать двоеточие ':'. Как правило, метки должны начинаться с буквы или символа подчеркивания ('_'), следующие символы могут быть выбраны из букв, цифр и следующих специальных символов: '_', '.', '!', '?', '#' и '@'. Обратите внимание, что '.' имеет особое значение, поскольку оно используется между именами модулей, метками и локальными метками. Все перечисленные ниже названия являются корректными и отличающимися друг от друга:

Kip
KIP
Kip@@
MAIN.loop?

В качестве меток можно использовать мнемонику, псевдооперации и имена регистров, но не рекомендуется этого делать (ключевое слово expression operator, используемое в качестве метки, выдаст предупреждение, и это также не рекомендуется). Также обратите внимание, что идентификаторы, определенные с помощью псевдо-операции DEFINE, используют другое пространство имен.

(начиная с версии v1.18.0) сразу после метки (перед необязательным двоеточием) вы можете написать дополнительное "Смещение SMC" (Self Modify Code offset) в виде знака плюс и одной десятичной цифры. Определенная метка станет равной текущему адресу плюс смещение SMC:

                                ; Синтаксис SMC - offset очень строгий, без пробелов, одинарный '+', единственная цифра
answer+1:   ld      a,13        ; "ответ" указывает на второй байт кода операции
                                ; это помогает сохранить SMC-метку вместе с целевой инструкцией
            ld      hl,answer
            ld      (hl),42     ; исправляем немедленно в `ld a,*` для правильного ответа
                                ; сравните с классическим синтаксисом:
classic equ $+1 : ld a,7        ; часто даже разделяется на две строки

(начиная с версии v1.20.1) добавлены Smart метки SMC: вы можете написать "плюс звездочка", чтобы позволить sjasmplus настроить самоизменяющуюся метку на наиболее вероятное смещение для следующей инструкции. Это работает только для инструкций с "очевидным" целевым непосредственным значением:

                                ; синтаксис smart-SMC очень строгий, без пробелов, одинарный '+', одинарный '*'
answer+*:   ld      a,13        ; "answer" указывает второй байт кода операции
                                ; это помогает сохранить SMC-метку вместе с целевой инструкцией
            ld      hl,answer
            ld      (hl),42     ; исправляем немедленно в `ld a,*` для правильного ответа
                                ; еще несколько примеров, на какой байт будет нацелен "smart SMC" в коде операции
jptarget+*: jp      nz,12345    ; "jptarget" указывает на второй байт кода операции (значение слова 12345)
ixvalue+*:  ld      ix,12345    ; "ixvalue" указывает на третий байт кода операции (значение слова 12345)
nxtrval+*:  nextreg $44,123     ; "nxtrval" указывает на четвертый байт кода операции (значение байта 123)
                                ; неподдерживаемая ситуация приведет к ошибке
invalid1+*: inc     (ix+123)    ; IXY перемещения не учитываются (недостаточно значительны)
invalid2+*: cpl : ld a,14       ; учитывается только первая инструкция после метки

Локальные метки

Когда есть определение модуля все метки (кроме тех, которые начинаются с '@') являются локальными для этого модуля. Чтобы использовать метку извне модуля, используйте module_name.label_name, например: 'vdp.Cls'. Метки, начинающиеся с '.', также являются локальными по отношению к предыдущей нелокальной метке.

(начиная с версии v1.18.0) Если вы начнете метку с ! (восклицательный знак), это не повлияет на следующие локальные метки (тот же синтаксис, что и sjasm).

(начиная с версии v1.18.3) Локальная метка внутри макроса с префиксом @ (в знаке) действует как обычная локальная метка, в противном случае (более старое поведение) локальная метка является локальной для экземпляра каждого макроса.

Пример В 3.1.В docs_examples/s_local_labels.asm

    MODULE main             ; module "main"
Main:                       ; main.Main
        CALL SetScreen      ; SetScreen
        CALL vdp.Cls        ; main.vdp.Cls
.loop:                      ; main.Main.loop
        LD A,(.event)       ; main.Main.event
        CALL ProcessEvent   ; label not found: main.ProcessEvent
        DJNZ .loop          ; main.Main.loop

        MODULE vdp          ; module "main.vdp"
@SetScreen:                 ; SetScreen
.loop:                      ; main.vdp.SetScreen.loop
            RET
Cls:                        ; main.vdp.Cls
!KeepClsForLocal:           ; main.vdp.KeepClsForLocal (since v1.18.0)
.loop:      DJNZ .loop      ; main.vdp.Cls.loop
            RET
        ENDMODULE

Main.event DB 0             ; main.Main.event
    ENDMODULE


Пример В 3.2.В local labels inside macro

  macro test
.kip0       ; это локально для каждого экземпляра макроса
@.kip1      ; синтаксис добавлен в версии v1.18.3
  endm

  module main
hoi test    ; определены метки: main.hoi, 0>kip0, main.hoi.kip1
  endmodule


@ Метки

Метки, начинающиеся с "@", не затрагиваются обработкой меток и используются "как есть". Смотрите раздел "SetScreen" в предыдущем примере кода.

Пример В 3.3.В docs_examples/s_at_labels.asm

    MODULE xxx
Label      ; xxx.Label
.Local     ; xxx.Label.Local
@Label     ; Label
.Local     ; xxx.Label.Local => duplicate label error
@Label2    ; Label2
.Local     ; xxx.Label2.Local
@yyy.Local ; yyy.Local
yyy.Local  ; xxx.yyy.Local


Временные метки

Чтобы количество используемых меток было разумным, в качестве меток можно использовать цифры. Эти метки можно использовать только в качестве меток для перехода. Чтобы перейти к этим меткам, используйте число, за которым следует "F" для прямых ветвей или "B" для обратных ветвей. Временные метки должны определяться в одном и том же порядке на каждом этапе сборки, но они могут использоваться внутри макроса или повторяющихся блоков (старые версии sjasmplus не допускали использования внутри макроса).

Поскольку в версии v1.19.0 существует альтернативный синтаксис, использующий подчеркивание перед 'B' и 'F', этот альтернативный подчеркнутый суффикс позволяет использовать временные метки также для обычных инструкций (во всех выражениях, так же, как и другие метки).

ExampleВ 3.4.В docs_examples/s_temp_labels.asm

        ADD A,E
        JR NC,1F
        INC D
1       LD E,A
2       LD B,4
        LD A,(DE)
        OUT (152),A
        DJNZ 2B

        MACRO zing
            DUP 2
                JR 1F
1               DJNZ    1B
            EDUP
        ENDM

        .4 zing

        ; since v1.19.0
        ld hl,1B        ; *старый* HL = двоичное число 1, НЕ временная метка
        ld hl,1_B       ; *новый* HL = предыдущая временная метка 1
        ld hl,1_B*3     ; *новое* работает также в выражениях


Глава B 4.В Константы, выражения и другие функции

Числовые константы

Числовые константы всегда должны начинаться с цифры или $, # или %.Поддерживаются следующие форматы:

12     десятичная
12d    десятичная
0xc    16-ричная
$c     16-ричная
#c     16-ричная
0ch    16-ричная
0b1100 двоичная (v1.12.1)
%1100  двоичная
1100b  двоичная
0q14   восьмеричная (v1.12.1)
14q    восьмеричная
14o    восьмеричная

(с версии v1.12.1) Необязательные одинарные кавычки (') могут быть вставлены между цифрами в качестве разделителя (например: ld a,%11'01'11'00 ). Ассемблер игнорирует их.

(с версии v1.20.1) десятичные части теперь анализируются и игнорируются (с необязательным предупреждением), вместо того, чтобы вызывать синтаксическую ошибку - это должно облегчить жизнь при форматировании значений из скрипта Lua. Также возможно исправить все скрипты Lua так, чтобы они выдавали только целочисленные значения, но если вы предпочитаете молча игнорировать дополнительную десятичную часть, вы можете это сделать.

Символьные и строковые константы

Символьные константы - это символы, заключенные в одинарные кавычки. В некоторых случаях можно использовать двойные кавычки, но в целом лучше использовать одинарные кавычки. Строковые константы - это символы, заключенные в двойные кавычки. При использовании двойных кавычек распознаются следующие escape-последовательности:

\\ 92
\? 63
\' 39
\" 34
\0 0     ; since v1.11
\A 7
\B 8
\D 127
\E 27
\F 12
\N 10
\R 13
\T 9
\V 11

Внутри одинарных кавычек две кавычки друг за другом принимаются как апостроф (начиная с версии v1.11).

Пример В 4.1.В 

    BYTE "stringconstant\n" ; кобавляет к константе escape последовательность "новая строка"
    BYTE 'stringconstant\n' ; \n компилируется буквально в виде двух байтов: '\', 'n'
    LD HL,'hl'  ; hl = 0x686C = 'l', 'h'
    LD HL,"hl"  ; hl = 0x686C = 'l', 'h'
    LD A,"7"    ; не рекомендуется (но работает)
    LD A,'8'    ; рекомендуется
    LD A,'\E'   ; предупреждение + усечение значения до 'E' (0x45)
    LD A,'"'    ; A = 0x22
    LD A,"'"    ; A = 0x27
    LD A,''''   ; A = 0x27 ; с версии v1.11


Выражения

Выражения вычисляются как 32 битные числа со знаком в этой версии SjASMPlus (если явно не указано значение без знака, например, оператор ">>>"), поэтому промежуточные значения имеют диапазон от -2147483648 до +2147483647.

'$' представляет текущее значение программного счетчика. '$$' представляет текущую страницу в текущем слоте в режиме эмуляции реального устройства, '$$label' вычисляет номер страницы, на которой была определена "метка" (только обычные метки имеют значимое значение, метки, определенные в режиме DISP, могут возвращать страницу, указанную в самом DISP, EQUAL/DEFL/... будет выдавать в основном нерелевантные значения). '$$$' и '$$$$' могут использоваться внутри блока DISP для извлечения "физического" адреса памяти и страницы (куда записан перемещенный машинный код). '{address}' может использоваться для считывания СЛОВА из памяти виртуального устройства (правильное значение считывается только при последнем проходе сборки, при ранних проходах всегда возвращается нулевое значение), '{b address}' считывает только байт.

Можно использовать круглые скобки '(' и ')', чтобы переопределить приоритет операторов. В выражениях могут использоваться следующие операторы:

norel norel L  Метка/символ L будет рассматриваться как неперемещаемый
exist exist L  определена ли метка/ символ L в исходном коде (даже если он не используется) (начиная с версии v1.18.2)

!     !x       логическое НЕ
~     ~x       дополнение
+     +x       делает "ничего", может быть использован для синтаксического анализа "+ (...)" как значения (не как памяти)
-     -x       минус
low   low x    младшие 8 бит из 16-битного значения или младший регистр из пары регистров
high  high x   старшие 8 бит из 16-битного значения или старший регистр из пары регистров
not   not x    логическое НЕ
abs   abs x    абсолютное значение (начиная с версии v1.18.0)

*     x*y      умножение
/     x/y      деление
%     x%y      остаток от деления X на Y
mod   x mod y  остаток от деления X на Y

+     x+y      сложение
-     x-y      вычитание

<<    x<<y     сдвиг влево
>>    x>>y     сдвиг вправо со знаком
>>>   x>>>y    сдвиг вправо без знака
shl   x shl y  сдвиг влево
shr   x shr y  сдвиг вправо со знаком

<?    x<?y     минимум
>?    x>?y     максимум

<     x<y      меньше, чем
>     x>y      больше, чем
<=    x<=y     меньше или равно
>=    x>=y     больше или равно

=     x=y      равно
==    x==y     равно
!=    x!=y     не равно

&     x&y      побитное И
and   x and y  побитное И

^     x^y      побитное ИСКЛЮЧАЮЩЕЕ ИЛИ
xor   x xor y  побитное ИСКЛЮЧАЮЩЕЕ ИЛИ

|     x|y      побитное ИЛИ
or    x or y   побитное ИЛИ

&&    x&&y     логическое И

||    x||y     логическое ИЛИ

$     $        текущее значение счетчика команд
$$    $$       текущая значение страницы на счетчике программ (в режиме виртуального устройства)
$$$   $$$      "физическое" значение счетчика программ (внутри блока DISP)
$$$$  $$$$     страница "физической" памяти (внутри блока DISP в режиме виртуального устройства)
label label    значение метки (она же символ), обычно адрес памяти
$$lab $$lab    страница метки "lab" (в режиме виртуального устройства)
{}    {x}      считывает СЛОВО с адреса x (в режиме виртуального устройства, в последнем проходе)
{b}   {b x}    считывает БАЙТ с адреса x (в режиме виртуального устройства, в последнем проходе)

Язык ассемблера

Эта версия поддерживает только мнемонику Z80. Есть некоторые дополнения к тому, что я считаю стандартом Z80:

  • '[' и ']' можно использовать вместо '(' и ')' для косвенного указания. Таким образом, LD A,[HL] совпадает с LD A,(HL) (не применяется к портам ввода/ вывода, они должны использовать форму '(...)')

  • IN F,(C) и OUT (C),0 и SLL/SLI могут быть использованы (внимание: в некоторых версиях процессоров Z80 значение OUT (C),0 работает как OUT (C),255).

  • IXL (или LX, XL), IYL (или LY, YL), IXH (или HX, XH) и IYH (или HY, YH) регистры поддерживаются.

  • Вы можете писать код через двоеточие: ORG 100h:LD A,10:LD B,10:SUB B:RET:IFDEF AA:.....

  • JP HL, JP IX и JP IY может использоваться вместо JP (HL), и т.д..

  • EX AF,AF или EX AF или EXA может использоваться вместо EX AF,AF'.

  • Распознаются HULU и HULU от R800 (но, конечно, не будут работать на Z80:)

  • Режимы Z80N, i8080 и LR35902 (SM83) используют идентичный синтаксис Z80 sjasmplus (!), для получения правильных (и неправильных) примеров синтаксиса расширенных кодов операций, пожалуйста, проверьте тестовые файлы: Z80N test 1 test 2 и LR35902 (SM83) test 1 test 2 (также для примеров синтаксиса Z80 вы можете проверить Z80 tests).

  • Добавлены недокументированные инструкции: RLC, RRC, RL, RR, SLA, SRA, SLL (SLI), RES, SET.

    SET 4,(IX+4),C ; (он же LD C,SET 4,(IX+4)) это LD C,(IX+4) / SET 4,C / LD (IX+4),C
    RRC (IY),A     ; (он же LD A,RRC (IY+0))   - это LD A,(IY)   / RRC A   / LD (IY),A
  • PUSH и POP могут принимать списки регистров:

    PUSH AF,BC  ; push af / push bc
    POP  AF,BC  ; pop  af / pop  bc
  • и многие другие инструкции поддерживают этот синтаксис "с несколькими аргументами":

    LD A,B,B,D,D,H
   /* this is:
     LD A,B
     LD B,D
     LD D,H
   */
   ;или вы можете написать  LD A,B:LD B,D:LD D,H

   ; начиная с версии v1.13.1 возможно и * рекомендуется* изменить разделитель с несколькими аргументами
   ; на ",,", чтобы избежать некоторых двусмысленностей с определенными инструкциями.
   OPT --syntax=a
   LD A,B,,B,D,,D,H ; то же, что и в примере выше, с синтаксисом по умолчанию
   SUB A,B,,C  ; = SUB B, SUB C (синтаксис по умолчанию используется для  SUB A,B два SUB!)

   ; начиная с версии v1.19.0 DEC|INC|POP|PUSH также принимает одинарную запятую в --syntax=a mode
   POP bc,de,hl,,af ;  обе одинарные/ двойные запятые работают для этих четырех инструкций

Нестандартные инструкции

Конечно, Z80 - это всего лишь 8-разрядный процессор, но иногда ld hl,de было бы здорово. SjASMPlus теперь "подделывает" некоторые подобные инструкции. Это улучшает читаемость исходного кода, но, возможно, это не самый быстрый способ получить результат. Также, возможно, некоторые "новые" инструкции по загрузке влияют на флаги таким образом, которого вы не ожидали. Вы можете использовать опцию --syntax=f получать предупреждения при использовании нестандартных инструкций, чтобы избежать их случайного использования. Вот список:

  rl bc           ; rl c : rl b
  rl de           ; rl e : rl d
  rl hl           ; rl l : rl h
  rr bc           ; rr b : rr c
  rr de           ; rr d : rr e
  rr hl           ; rr h : rr l
  sla bc          ; sla c : rl b
  sla de          ; sla e : rl d
  sla hl          ; add hl,hl
  sll bc          ; sli c : rl b
  sll de          ; sli e : rl d
  sll hl          ; sli l : rl h
  sli bc          ; sli c : rl b
  sli de          ; sli e : rl d
  sli hl          ; sli l : rl h
  sra bc          ; sra b : rr c
  sra de          ; sra d : rr e
  sra hl          ; sra h : rr l
  srl bc          ; srl b : rr c
  srl de          ; srl d : rr e
  srl hl          ; srl h : rr l

  ld bc,bc        ; ld b,b : ld c,c
  ld bc,de        ; ld b,d : ld c,e
  ld bc,hl        ; ld b,h : ld c,l
  ld bc,ix        ; ld b,xh : ld c,xl
  ld bc,iy        ; ld b,yh : ld c,yl
  ld bc,(hl)      ; ld c,(hl) : inc hl : ld b,(hl) : dec hl
  ld bc,(ix+nn)   ; ld c,(ix+nn) : ld b,(ix+nn+1)
  ld bc,(iy+nn)   ; ld c,(iy+nn) : ld b,(iy+nn+1)

  ld de,bc        ; ld d,b : ld e,c
  ld de,de        ; ld d,d : ld e,e
  ld de,hl        ; ld d,h : ld e,l
  ld de,ix        ; ld d,xh : ld e,xl
  ld de,iy        ; ld d,yh : ld e,yl
  ld de,(hl)      ; ld e,(hl) : inc hl : ld d,(hl) : dec hl
  ld de,(ix+nn)   ; ld e,(ix+nn) : ld d,(ix+nn+1)
  ld de,(iy+nn)   ; ld e,(iy+nn) : ld d,(iy+nn+1)

  ld hl,bc        ; ld h,b : ld l,c
  ld hl,de        ; ld h,d : ld l,e
  ld hl,hl        ; ld h,h : ld l,l
  ld hl,ix        ; push ix : pop hl
  ld hl,iy        ; push iy : pop hl
  ld hl,(ix+nn)   ; ld l,(ix+nn) : ld h,(ix+nn+1)
  ld hl,(iy+nn)   ; ld l,(iy+nn) : ld h,(iy+nn+1)

  ld ix,bc        ; ld xh,b : ld xl,c
  ld ix,de        ; ld xh,d : ld xl,e
  ld ix,hl        ; push hl : pop ix
  ld ix,ix        ; ld xh,xh : ld xl,xl
  ld ix,iy        ; push iy : pop ix

  ld iy,bc        ; ld yh,b : ld yl,c
  ld iy,de        ; ld yh,d : ld yl,e
  ld iy,hl        ; push hl : pop iy
  ld iy,ix        ; push ix : pop iy
  ld iy,iy        ; ld yh,yh : ld yl,yl

  ld (hl),bc      ; ld (hl),c : inc hl : ld (hl),b : dec hl
  ld (hl),de      ; ld (hl),e : inc hl : ld (hl),d : dec hl

  ld (ix+nn),bc   ; ld (ix+nn),c : ld (ix+nn+1),b
  ld (ix+nn),de   ; ld (ix+nn),e : ld (ix+nn+1),d
  ld (ix+nn),hl   ; ld (ix+nn),l : ld (ix+nn+1),h

  ld (iy+nn),bc   ; ld (iy+nn),c : ld (iy+nn+1),b
  ld (iy+nn),de   ; ld (iy+nn),e : ld (iy+nn+1),d
  ld (iy+nn),hl   ; ld (iy+nn),l : ld (iy+nn+1),h

  ldi bc,(hl)     ; ld c,(hl) : inc hl : ld b,(hl) : inc hl
  ldi bc,(ix+nn)  ; ld c,(ix+nn) : inc ix : ld b,(ix+nn) : inc ix
  ldi bc,(iy+nn)  ; ld c,(iy+nn) : inc iy : ld b,(iy+nn) : inc iy

  ldi de,(hl)     ; ld e,(hl) : inc hl : ld d,(hl) : inc hl
  ldi de,(ix+nn)  ; ld e,(ix+nn) : inc ix : ld d,(ix+nn) : inc ix
  ldi de,(iy+nn)  ; ld e,(iy+nn) : inc iy : ld d,(iy+nn) : inc iy

  ldi hl,(ix+nn)  ; ld l,(ix+nn) : inc ix : ld h,(ix+nn) : inc ix
  ldi hl,(iy+nn)  ; ld l,(iy+nn) : inc iy : ld h,(iy+nn) : inc iy

  ldi (hl),bc     ; ld (hl),c : inc hl : ld (hl),b : inc hl
  ldi (hl),de     ; ld (hl),e : inc hl : ld (hl),d : inc hl

  ldi (ix+nn),bc  ; ld (ix+nn),c : inc ix : ld (ix+nn),b : inc ix
  ldi (ix+nn),de  ; ld (ix+nn),e : inc ix : ld (ix+nn),d : inc ix
  ldi (ix+nn),hl  ; ld (ix+nn),l : inc ix : ld (ix+nn),h : inc ix

  ldi (iy+nn),bc  ; ld (iy+nn),c : inc iy : ld (iy+nn),b : inc iy
  ldi (iy+nn),de  ; ld (iy+nn),e : inc iy : ld (iy+nn),d : inc iy
  ldi (iy+nn),hl  ; ld (iy+nn),l : inc iy : ld (iy+nn),h : inc iy

  ldi a,(bc)      ; ld a,(bc) : inc bc
  ldi a,(de)      ; ld a,(de) : inc de
  ldi a,(hl)      ; ld a,(hl) : inc hl
  ldi b,(hl)      ; ld b,(hl) : inc hl
  ldi c,(hl)      ; ld c,(hl) : inc hl
  ldi d,(hl)      ; ld d,(hl) : inc hl
  ldi e,(hl)      ; ld e,(hl) : inc hl
  ldi h,(hl)      ; ld h,(hl) : inc hl
  ldi l,(hl)      ; ld l,(hl) : inc hl
  ldi a,(ix+nn)   ; ld a,(ix+nn) : inc ix
  ldi b,(ix+nn)   ; ld b,(ix+nn) : inc ix
  ldi c,(ix+nn)   ; ld c,(ix+nn) : inc ix
  ldi d,(ix+nn)   ; ld d,(ix+nn) : inc ix
  ldi e,(ix+nn)   ; ld e,(ix+nn) : inc ix
  ldi h,(ix+nn)   ; ld h,(ix+nn) : inc ix
  ldi l,(ix+nn)   ; ld l,(ix+nn) : inc ix
  ldi a,(iy+nn)   ; ld a,(iy+nn) : inc iy
  ldi b,(iy+nn)   ; ld b,(iy+nn) : inc iy
  ldi c,(iy+nn)   ; ld c,(iy+nn) : inc iy
  ldi d,(iy+nn)   ; ld d,(iy+nn) : inc iy
  ldi e,(iy+nn)   ; ld e,(iy+nn) : inc iy
  ldi h,(iy+nn)   ; ld h,(iy+nn) : inc iy
  ldi l,(iy+nn)   ; ld l,(iy+nn) : inc iy

  ldd a,(bc)      ; ld a,(bc) : dec bc
  ldd a,(de)      ; ld a,(de) : dec de
  ldd a,(hl)      ; ld a,(hl) : dec hl
  ldd b,(hl)      ; ld b,(hl) : dec hl
  ldd c,(hl)      ; ld c,(hl) : dec hl
  ldd d,(hl)      ; ld d,(hl) : dec hl
  ldd e,(hl)      ; ld e,(hl) : dec hl
  ldd h,(hl)      ; ld h,(hl) : dec hl
  ldd l,(hl)      ; ld l,(hl) : dec hl
  ldd a,(ix+nn)   ; ld a,(ix+nn) : dec ix
  ldd b,(ix+nn)   ; ld b,(ix+nn) : dec ix
  ldd c,(ix+nn)   ; ld c,(ix+nn) : dec ix
  ldd d,(ix+nn)   ; ld d,(ix+nn) : dec ix
  ldd e,(ix+nn)   ; ld e,(ix+nn) : dec ix
  ldd h,(ix+nn)   ; ld h,(ix+nn) : dec ix
  ldd l,(ix+nn)   ; ld l,(ix+nn) : dec ix
  ldd a,(iy+nn)   ; ld a,(iy+nn) : dec iy
  ldd b,(iy+nn)   ; ld b,(iy+nn) : dec iy
  ldd c,(iy+nn)   ; ld c,(iy+nn) : dec iy
  ldd d,(iy+nn)   ; ld d,(iy+nn) : dec iy
  ldd e,(iy+nn)   ; ld e,(iy+nn) : dec iy
  ldd h,(iy+nn)   ; ld h,(iy+nn) : dec iy
  ldd l,(iy+nn)   ; ld l,(iy+nn) : dec iy

  ldi (bc),a      ; ld (bc),a : inc bc
  ldi (de),a      ; ld (de),a : inc de
  ldi (hl),a      ; ld (hl),a : inc hl
  ldi (hl),b      ; ld (hl),b : inc hl
  ldi (hl),c      ; ld (hl),c : inc hl
  ldi (hl),d      ; ld (hl),d : inc hl
  ldi (hl),e      ; ld (hl),e : inc hl
  ldi (hl),h      ; ld (hl),h : inc hl
  ldi (hl),l      ; ld (hl),l : inc hl
  ldi (ix+nn),a   ; ld (ix+nn),a : inc ix
  ldi (ix+nn),b   ; ld (ix+nn),b : inc ix
  ldi (ix+nn),c   ; ld (ix+nn),c : inc ix
  ldi (ix+nn),d   ; ld (ix+nn),d : inc ix
  ldi (ix+nn),e   ; ld (ix+nn),e : inc ix
  ldi (ix+nn),h   ; ld (ix+nn),h : inc ix
  ldi (ix+nn),l   ; ld (ix+nn),l : inc ix
  ldi (iy+nn),a   ; ld (iy+nn),a : inc iy
  ldi (iy+nn),b   ; ld (iy+nn),b : inc iy
  ldi (iy+nn),c   ; ld (iy+nn),c : inc iy
  ldi (iy+nn),d   ; ld (iy+nn),d : inc iy
  ldi (iy+nn),e   ; ld (iy+nn),e : inc iy
  ldi (iy+nn),h   ; ld (iy+nn),h : inc iy
  ldi (iy+nn),l   ; ld (iy+nn),l : inc iy

  ldd (bc),a      ; ld (bc),a : dec bc
  ldd (de),a      ; ld (de),a : dec de
  ldd (hl),a      ; ld (hl),a : dec hl
  ldd (hl),b      ; ld (hl),b : dec hl
  ldd (hl),c      ; ld (hl),c : dec hl
  ldd (hl),d      ; ld (hl),d : dec hl
  ldd (hl),e      ; ld (hl),e : dec hl
  ldd (hl),h      ; ld (hl),h : dec hl
  ldd (hl),l      ; ld (hl),l : dec hl
  ldd (ix+nn),a   ; ld (ix+nn),a : dec ix
  ldd (ix+nn),b   ; ld (ix+nn),b : dec ix
  ldd (ix+nn),c   ; ld (ix+nn),c : dec ix
  ldd (ix+nn),d   ; ld (ix+nn),d : dec ix
  ldd (ix+nn),e   ; ld (ix+nn),e : dec ix
  ldd (ix+nn),h   ; ld (ix+nn),h : dec ix
  ldd (ix+nn),l   ; ld (ix+nn),l : dec ix
  ldd (iy+nn),a   ; ld (iy+nn),a : dec iy
  ldd (iy+nn),b   ; ld (iy+nn),b : dec iy
  ldd (iy+nn),c   ; ld (iy+nn),c : dec iy
  ldd (iy+nn),d   ; ld (iy+nn),d : dec iy
  ldd (iy+nn),e   ; ld (iy+nn),e : dec iy
  ldd (iy+nn),h   ; ld (iy+nn),h : dec iy
  ldd (iy+nn),l   ; ld (iy+nn),l : dec iy

  ldi (hl),mm     ; ld (hl),mm : inc hl
  ldi (ix+nn),mm  ; ld (ix+nn),mm : inc ix
  ldi (iy+nn),mm  ; ld (iy+nn),mm : inc iy

  ldd (hl),mm     ; ld (hl),mm : dec hl
  ldd (ix+nn),mm  ; ld (ix+nn),mm : dec ix
  ldd (iy+nn),mm  ; ld (iy+nn),mm : dec iy

  adc de,bc       ; ex de,hl : adc hl,bc : ex de,hl
  adc de,de       ; ex de,hl : adc hl,hl : ex de,hl         ;; рассмотрите альтернативу: rl e : rl d (-7T)
  adc de,hl       ; ex de,hl : adc hl,de : ex de,hl
  adc de,sp       ; ex de,hl : adc hl,sp : ex de,hl

  add de,bc       ; ex de,hl : add hl,bc : ex de,hl
  add de,de       ; ex de,hl : add hl,hl : ex de,hl         ;; рассмотрите альтернативу: srl e : rl d (-3T)
  add de,hl       ; ex de,hl : add hl,de : ex de,hl
  add de,sp       ; ex de,hl : add hl,sp : ex de,hl

  sbc de,bc       ; ex de,hl : sbc hl,bc : ex de,hl
  sbc de,de       ; ex de,hl : sbc hl,hl : ex de,hl
  sbc de,hl       ; ex de,hl : sbc hl,de : ex de,hl
  sbc de,sp       ; ex de,hl : sbc hl,sp : ex de,hl

  sub de,bc       ; or a : ex de,hl : sbc hl,bc : ex de,hl
  sub de,de       ; or a : ex de,hl : sbc hl,hl : ex de,hl  ;; рассмотрите альтернативу: ld de,0 (-17T)
  sub de,hl       ; or a : ex de,hl : sbc hl,de : ex de,hl
  sub de,sp       ; or a : ex de,hl : sbc hl,sp : ex de,hl
  sub hl,bc       ; or a : sbc hl,bc
  sub hl,de       ; or a : sbc hl,de
  sub hl,hl       ; or a : sbc hl,hl                        ;; рассмотрите альтернативу: ld hl,0 (-9T)
  sub hl,sp       ; or a : sbc hl,sp

  ; Z80N only
  mul             ; mul de ; чтобы избежать предупреждения, укажите регистры

LDI увеличивает указатель на данные после доступа к данным, так что LDI A,(HL) это то же самое, чтоLD A,(HL):INC HL. Также, LDD A,(DE) заменяет LD A,(DE):DEC DE.

Режим эмуляции реального устройства

Чтобы включить этот режим, вы должны использовать псевдо-операциюDEVICE.

В этом режиме компилятор компилирует программу в виртуальную память (как у Max's WBASS2, ZX-Spectrum GENS, ZEUS, ALARM и т.д.). После всего этого вы можете использовать новые псевдо-операции в качестве SAVEBIN, SAVEDEV SAVEHOB, SAVETRD, SAVETAP, PAGE, SLOT, MMU, LABELSLIST, используйте специальные функции в Lua скрипте и используйте операторы {address}, {b address} чтобы прочитать СЛОВО/БАЙТ из виртуальной памяти.

Если во всем исходном пакете используется только одно устройство, устройство становится "глобальным" и будет влиять также на источник, предшествующий линейке УСТРОЙСТВ.

Пример В 4.2.В docs_examples/s_realdevice.asm

    DEVICE ZXSPECTRUM128
    ; в этом устройстве слотом по умолчанию является слот 3, в который вставлена страница 0.

    ORG 32768
StartProg:
    JP $

    DEVICE NONE
    ;сделайте что-нибудь, если вы не хотите испортить виртуальныую
    ;память с другим кодом, например, загрузчиком кода.
    ;...code...

    ;вернитесь на наше виртуальное устройство:
    DEVICE ZXSPECTRUM128

    SAVESNA "snapshotname.sna", StartProg


Предопределенные устройства:

NONE

Отключение режима эмуляции реального устройства. По умолчанию.

ZXSPECTRUM48

Имеет 4 слота (0-3) размером 4000h, 4 страницы (0-3) размером 4000h. Слот 3 (он начинается с 0C000h) по умолчанию включен в текущий режим.

ZXSPECTRUM128

Имеет 8 страниц оперативной памяти (0-7) размером 4000h. Слот по умолчанию равен 3.

ZXSPECTRUM256

То же, что и русский клон Scorpion 256. Имеет 16 страниц оперативной памяти (0-15) размером 4000h.

ZXSPECTRUM512

То же, что и российские клоны ATM Turbo 512 и Pentagon 512. Имеет 32 страницы оперативной памяти (0-31) размером 4000h.

ZXSPECTRUM1024

То же, что и российские клоны ATM Turbo 2 и Pentagon 1024 SL. Имеет 64 страницы оперативной памяти (0-63) размером 4000h.

ZXSPECTRUM2048

Подобно другим устройствам spectrum, имеет 128 страниц оперативной памяти (0-127) размером 4000 h.

ZXSPECTRUM4096

Подобно другим устройствам spectrum, имеет 256 страниц оперативной памяти (0-255) размером 4000h.

ZXSPECTRUM8192

Подобно другим устройствам spectrum, имеет 512 страниц оперативной памяти (0-511) размером 4000 h.

ZXSPECTRUMNEXT

ZX Spectrum Next имеет 8 слотов (0-7) размером 0x2000 и 224 страницы оперативной памяти (0-223) общим объемом 1,75 Мбайт.Распределение памяти по умолчанию аналогично ZX128, подкачка в: {14, 15, 10, 11, 4, 5, 0, 1} страницы. Слот по умолчанию равен 7 (диапазон памяти 0xE000..0xFFFF). Вся память обнуляется во время инициализации.

NOSLOT64K

Имеет только один слот размером 64 Кб (слот 0), охватывающий весь диапазон адресации процессора Z80. Доступно 32 страницы памяти, по умолчанию отображается страница 0. Таким образом, в общей сложности доступно 2 Мбайт памяти (32 * 64 кб = 2 МБайт).

AMSTRADCPC464

Имеет 4 слота (0-3) размером 0x4000 и 4 страницы (0-3) размером 0x4000, общим объемом 64 КБ. Эти страницы отображаются линейно в виде { 0, 1, 2, 3 }.

AMSTRADCPC6128

Имеет 4 слота (0-3) размером 0x4000 и 8 RAMpages (0-7) размером 0x4000 (всего 128 Кб). Сопоставление страниц по умолчанию является { 0, 1, 2, 3 }.

Если вы хотите посмотреть другие устройства, вы должны написать нам. Смотрите главу Обратная связь.

Предопределенные определения

SjASMPlus имеет предопределенные определения.

__SJASMPLUS__ = <24-х битное число>

Номер текущей версии программы разделен на три 8-битных значения, т.е. 0x010F02 для "1.15.2".

__VERSION__ = "строка, содержащая номер версии"

Строковое значение (с кавычками вокруг него) текущей версии программы, например "1.15.2".

__ERRORS__ = <число>

Количество ошибок.

__WARNINGS__ = <число>

Количество предупреждений.

__DATE__ = "YYYY-MM-DD"

Дата компиляции (временная метка перед первым проходом).

__TIME__ = "hh:mm:ss"

Время компиляции (отметка времени перед первым проходом, форма 24 часа).

__PASS__ = <число>

Текущий проход компилятора (1, 2 или 3).

__INCLUDE_LEVEL__ = <число>

Текущий уровень вложенности include.

__BASE_FILE__ = <имя базового файла>

Имя базового файла (включает нулевой уровень).

Это необработанное значение без кавычек, практически непригодное для использования в asm-источнике, но LUA предоставляет средства для работы с таким строковым значением.

__FILE__ = <имя текущего файла>

Имя текущего файла

Это необработанное значение без кавычек, практически непригодное для использования в asm-источнике, но LUA предоставляет средства для работы с таким строковым значением.

__LINE__ = <число>

Текущий номер строки.

__COUNTER__ = <увеличивающееся число>

Увеличивается при каждом использовании (начиная со значения 0). В настоящее время трудно использовать для меток / символов, потому что начальная буква "_" имени define предотвращает замену в середине слова, будет иметь больше смысла с новыми правилами замены (если когда-либо выйдет sjasmplus v2.x, это будет слишком большим изменением для v1.x). Прямо сейчас позовите LUA на помощь.

Пример В 4.3.В __COUNTER__ использование в скрипте LUA

    DB __COUNTER__   ; DB 0
    LUA ALLPASS
        sj.insert_label("label_" .. sj.get_define("__COUNTER__"), sj.current_address)
                -- creates "label_1" at "$" (0x0001)
        sj.insert_label("label_" .. sj.get_define("__COUNTER__"), _c("$+10"))
                -- creates "label_2" at "$+10" (0x000B)
    ENDLUA
label__COUNTER__: ; НЕ заменяет в текущей версии sjasmplus, извините
    DB __COUNTER__   ; DB 3

    ; также можно использовать подстановку аргументов макроса
    MACRO createLabelWithSuffix label?, suffix?
label?_suffix? ; определиние глобальной метки
    ENDM
    createLabelWithSuffix label, __COUNTER__    ; label_4
    createLabelWithSuffix label, __COUNTER__    ; label_5

Устаревшие предопределенные значения от sjasmplus до версии 1.15.1:

Предопределенные значения были переименованы и расширены, чтобы больше походить на предопределенные значения gcc / clang, следующие значения являются устаревшими оригиналами.

_SJASMPLUS = 1

Устарел, рассмотрите возможность использования аналогичного __SJASMPLUS__

Пример В 4.4.В 

   IFDEF _SJASMPLUS
     ;код для sjasmplus
   ELSE
     ;код для других компиляторов
   ENDIF


_VERSION = "версия"

Устарел, переименован в __VERSION__

Пример В 4.5.В 

   IF _VERSION = "1.07"
     ;код для 1.07
   ELSE
     ;код для остальных версий
   ENDIF


_RELEASE = номерРелиза

Устарел, рассмотрите возможность использования аналогичного __SJASMPLUS__

Пример В 4.6.В 

   IF _RELEASE = 1 ; 0 - является стабильной версией
     ;код для Release Candidate 1
   ELSE
     ;код для остальных версий
   ENDIF


_ERRORS = <число>

Количество ошибок. Устарел, переименован в __ERRORS__

_WARNINGS = <число>

Количество предупреждений. Устарел, переименован в __WARNINGS__

Глава B 5.В Псевдо-операции (они же псевдо-инструкции, директивы и т.д.)

Простой пример использования

     .SOMEPSEUDOOP ; или
     SOMEPSEUDOOP  ; или
     somepseudoop

Ниже приведен [почти] полный список псевдо-операций:

Псевдо-операции

.<количество повторов> <одна инструкция>

Повтор <одна инструкция> <количество повторов> раз. Не работает в начале строки. The <количество повторов> должно быть либо простым целым числом, либо выражением, полностью заключенным в круглые скобки.

Пример В 5.1.В docs_examples/po_dot_repeat.asm

    .3          INC A    ;будет скомпилировано как INC A:INC A:INC A
len             EQU 10
    .(12-len)   BYTE 0   ;будет скомпилировано как BYTE 0,0
    .2 .3       RET      ;будет скомпилировано как  6x RET


ABYTE <смещение> <байты>

Определяет байт или строку байтов. Смещение прибавляется к каждому из следующих байтов.

Пример В 5.2.В 

    ABYTE 2 4,9    ; компилируется как  BYTE 6,11
    ABYTE 3 "ABC"  ; компилируется как BYTE "DEF"


ABYTEC <смещение> <байты>

Определяет байт или строку байтов, где в последнем байте строки будет установлен бит 7. Смещение добавляется к каждому из следующих байтов.

Пример В 5.3.В 

    ABYTEC 0 "KIP"        ; компилируется как "KI",'P'|128
    ABYTEC 1 "ABC",0,"DE" ; компилируется как BYTE "BC",'D'|128,1,'E','F'|128


ABYTEZ <смещение> <байты>

Определяет байт или строку байтов, за которой следует ноль. Смещение добавляется к каждому из следующих байтов.

Пример В 5.4.В 

    ABYTEZ 0 "KIP"        ; компилируется как BYTE "KIP",0


ALIGN [<выражение, равное to 1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384 или 32768>[, <байт>]]

Выравнивание продвигается к ближайшему адресу, где остаток от деления <новый адрес>на <выражение> (по умолчанию 4) равно 0 (по возможности остается на текущем адресе).

Если указан <байт>, то им заполняется свободное место в памяти.

Пример В 5.5.В 

    ALIGN         ; => ALIGN 4 - просто выровняйте на 4
    ALIGN 2       ; выравнивает на 2 (сохраняет значение в памяти "устройства")
    ALIGN 2,0     ; + заполняет память нулем


ASSERT <Выражение>[, <Что угодно>]

Ошибка 'assertion failed' ("утверждение не выполнено") выдается, если выражение равно нулю. Параметр "Что угодно" (необязательный аргумент начиная с версии v1.18.1) также отображается в сообщении об ошибке, поэтому вы можете добавить туда описание / примечания о выражении.

Пример B 5.6.В

STACKPOINTER=0D500H
    ASSERT END_OF_PROGRAM < УКАЗАТЕЛЬ СТЕКА, программный код просачивается в область стека
END_OF_PROGRAM


BINARY <имя_файла>[,<смещение>[,<длина>]]

Синоним INCBIN.

BLOCK <длина>[,<заполняющий_байт>]

Задает область памяти. За оператором необхидимо указать число байт для резервирования, необязательный параметр - заполняющий байт.

Пример В 5.7.В

    BLOCK 500     ; определяет блок из 500 нулевых байт
    BLOCK 500,0   ; определяет блок из 500 нулевых байт
    BLOCK 400,-1  ; определяет блок из 500 байт заполненый числами 255


BPLIST <имя_файла> [unreal|zesarux]

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Открывает файл для экспорта информации о точках останова непосредственно из источника ASM, в настоящее время поддерживаются два варианта экспорта: unreal (по умолчанию) и zesarux. Для последних версий эмуляторов Unreal используйте имя файла "bpx.ini", затем вы можете загрузить файл из эмулятора UI. Для ZEsarUX файл будет содержать параметры командной строки, которые вы можете добавить в команду при запуске эмулятора.

(текущая версия ZEsarUX не будет перехватывать самую первую инструкцию только что загруженного файла snapshot/NEX/... , или она даже отключит точки останова при изменении параметров машины и проигнорирует опцию --enable-breakpoints - надеемся, в будущем она будет улучшена)

Пример В 5.8.В 

    BPLIST "bpx.ini" unreal  ; открыть список точек останова в формате "Unreal"
    ; или (можно указать только один файл для каждой сборочной единицы)
    BPLIST "cmd_line_options.txt" zesarux ; открыть список точек останова в формате "ZEsarUX"


BYTE <байты>

Определяет байт или строку байтов. Каждое значение должно быть в диапазоне от -129 до 256.

Пример В 5.9.В 

    BYTE 0x56
    BYTE 1,-78,'@'
    BYTE "Format C:? ",0h


CSPECTMAP [<имя_файла>]

Полезно для эмулятора ZX-Spectrum #CSpect от Mike Dailly.

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Сохраняет список меток в формате:

HEXA_16BIT_ADDRESS HEXA_LONG_ADDRESS TYPE LABELNAME

где TYPE: 00 = обычная метка, 01 = EQU или определенная структура, 02 = DEFL, 03 = ROM страница/"пустое" устройство, 04 = STRUCT.

Если имя файла не указано, значение по умолчанию создается путем добавления расширения ".map" к имени источника.

D24

Определяет три байта 24-х битной константы. Значения должны находиться в диапазоне от -16777217 до 16777216.

Пример В 5.10.В 

    D24 0x123456   ; задаем 3 байта: 0x56, 0x34, 0x12


DB

Синоним директивы BYTE.

DC

Такой же, как BYTE, но для каждого последнего символа строки будет установлен бит 7.

Пример В 5.11.В 

    DC "kip" ; аналогичная директиве BYTE "ki",'p'|128


DD

Синоним DWORD.

DEFARRAY <имя_массива> <список значений>

Массив значений.

Используйте имя_массива[#] для получения текущего размера массива.

Пример В 5.12.В docs_examples/po_defarray.asm

    DEFARRAY myarray 10*20,"A",20,</D,40>,50,70
CNT DEFL 0 ;или CNT=0
    DUP myarray[#]      ; 6
    DISPLAY myarray[CNT]
CNT DEFL CNT+1 ;или CNT=CNT+1
    EDUP


DEFARRAY+ <имя_массива> <список добавляемых значений>

Добавление дополнительных значений из списка к уже определенному массиву

Пример В 5.13.В 

    DEFARRAY   myarray 'A', 'B', 'C'
    DEFARRAY+  myarray 'D', 'E'            ; теперь массив "myarray" содержит 5 значений
    DUP 3 : DEFARRAY+ myarray '!' : EDUP   ; в массив "myarray" добавлено 3x '!'


DEFB

Сноним для BYTE.

DEFD

Синоним для DWORD.

DEFDEVICE <имя_устройства>, <размер_слота $100..$10000>, <число_страниц 1..1024>[, <начальная_страница_слота_0>[, ...]]

(начиная с версии v1.20.1) Добавление определенного пользователем устройства. Адресное пространство 64 кБ Z80 равномерно разделено на N размер_слота слотов, а общая память устройства равна размер_слота * число_страниц байтов.

Начальные страницы неявно переходят от 0 до число_страниц-1 (повторяя страницу число_страниц-1 для оставшихся слотов, когда страниц недостаточно), но вы можете указать начальный макет страницы явно.

Используйте DEVICE для выбора нового определенного устройства.

DEFG

Синоним DG.

DEFH

Синоним DH.

DEFINE+ <идентификатор> <замена>
DEFINE <идентификатор> <замена>

<идентификатор> будет заменен на <замена>. Директива DEFINE+ (начиная с версии v1.18.0) также переопределит <идентификатор> если он уже существует. Замена может быть опущена, в таком случае все еще возможно проверить, был ли идентификатор определен с помощью IFDEF или IFNDEF..

Пример В 5.14.В 

    DEFINE str_honderd "Honderd"
    BYTE str_honderd,0             ; BYTE "Honderd",0
    DEFINE+ do_stuff set 4,e
    do_stuff                       ; set 4,e
    DEFINE+ do_stuff set 2,e
    do_stuff                       ; set 2,e


<метка> DEFL <выражение>

Присваивает значение <выражение> символу <метрка>. Новая метка, определенная DEFINE, помечается внутренне как "изменяемая", что позволяет повторно присваивать ей новые значения с помощью дальнейших инструкций DEFL (вы также можете использовать = вместо DEFL).

Пример В 5.15.В 

counter DEFL 0
    DUP 4
        DB 0xAA, counter
counter = counter + 1
    EDUP
; созданный машинный код: AA 00 AA 01 AA 02 AA 03


DEFM

Аналогичен BYTE.

DEFS

Аналогичен BLOCK.

DEFW

Аналогичен WORD.

DEPHASE

Аналогичен ENT.

DEVICE <имя_устройства>[, <RAMTOP>]

Включает режим эмуляции реального устройства по его идентификатору. Если во всем исходном пакете есть только одна директива DEVICE, она становится "глобальной", и устройство влияет на все строки источника, в противном случае DEVICE применяется для следующих за ним строк.

FДля устройств, подобных ZXSPECTRUM (за исключением ZX Next), вы можете указать значение RAMTOP, которое инициализирует память устройства аналогично тому, как это было бы сделано "CLEAR <RAMTOP>" в BASIC, поместив верхнюю часть поддельного стека по адресу RAMTOP. Значение оперативной памяти по умолчанию начиная с версии v1.15.0 равно 0x5D5B (раньше оно было 0xFF57).

Список предопределенных идентификаторов устройств:

 NONE ; off real device emulation mode
 ZXSPECTRUM48   ; ZX-Spectrum 48 (4 слота, 4 страницы, размер слота/страницы 0x4000, карта по умолчанию: 0, 1, 2, 3)
 ZXSPECTRUM128  ; ZX-Spectrum 128 (как ZX-Spectrum 48 с 8 страницами, карта по умолчанию: 7, 5, 2, 0)
 ZXSPECTRUM256  ; например, Scorpion 256 (бывший клон ZX-Spectrum 128 из СССР)
 ZXSPECTRUM512  ; например, ATM-Turbo 512 (другой клон)
 ZXSPECTRUM1024
 ZXSPECTRUM2048
 ZXSPECTRUM4096
 ZXSPECTRUM8192
 ZXSPECTRUMNEXT ; ZX Spectrum Next (8 слотов, 224 страницы, размер слота 0x2000 = 1,75 МБ оперативной памяти)
                ; (карта страниц по умолчанию: 14, 15, 10, 11, 4, 5, 0, 1) ( слот по умолчанию: 7 (0xE000..0xFFFF))
 NOSLOT64K      ; Один слот (слот 0), охватывающий полный диапазон адресов Z80 в 64 КБ, 32 страницы
 AMSTRADCPC464  ; Amstrad CPC 464 (4 слота, 4 страницы, размер слота/страницы 0x4000, карта по умолчанию: 0, 1, 2, 3)
 AMSTRADCPC6128 ; Amstrad CPC 6128 (аналогично  Amstrad CPC 464 но с 8 страницами)

 ;отключить устройство:
   DEVICE NONE
 ;включить устройство:
   DEVICE ZXSPECTRUM128
DG <данные, закодированные в битах>

Данные состоят из набора символов, кратных 8 каждый блок из 8 символов преобразуется в байт.

Дефис '-' (также '.' и '_') преобразуется в 0, а любой другой символ, не содержащий пробелов, преобразуется в 1. Пробелы игнорируются, используйте их для форматирования, если хотите. Внимание, "DG 10100001" имеет значение 255, потому что символ "0" не является тире "-". (начиная с версии v1.11)

Пример В 5.16.В 

    DG 1-1----1  ; преобразуется в 161 в текущей локации
    DG ...# #... .##. .... ;преобразуется в 2 байта: 0x18, 0x60


DH "<строка1>"[,"<строка2>"...]

Преобразует строку из четного количество шестнадцатеричных цифр в множество байт. Вы можете добавлять пробелы между парами по своему усмотрению. (начиная с версии v1.11)

Пример В 5.17.В 

    DH "0123456789ABCDEF"   ; преобразуется в 8 байт: #01 #23 ...
    DH "01 23  45 67"       ; преобразуется в 4 байта: #01 #23 #45 #67


DISP <адрес>[,<номер_страницы>]

Установливает адрес, по которому должна работать часть кода. PHASE и TEXTAREA работают аналогично DISP. ENT восстанавливает текущий адрес. UNPHASE, DEPHASE и ENDT аналоги ENT. Блоки DISP не могут быть вложенными, и для изменения адреса перемещения внутри текущего DISK блока используйте обычную ORG. В режиме устройства вы можете указать фиксированное значение для "поддельной" страницы выдаваемых инструкций и обычных меток, но, чтобы избежать предупреждения, вы также должны отобразить целевую страницу в целевой слот памяти. (MMU). Если фиксированная страница в DISP не указана, используется текущее сопоставление страниц памяти.

Пример В 5.18.В docs_examples/po_disp.asm

    DEVICE ZXSPECTRUM48
SCREEN  EQU $4000
        ORG $8000
        LD HL,BEGIN
        LD DE,SCREEN
        LD BC,ENDOFPROG-BEGIN
        LDIR
        JP SCREEN
BEGIN   DISP SCREEN ;код будет скомпилирован для адреса $4000, но для текущей организации
MARKA       DEC A
            HALT
            JP NZ,MARKA
            DI
            HALT
        ENT
ENDOFPROG

    ASSERT $800E == BEGIN && $8015 == ENDOFPROG && $4000 == MARKA
    ASSERT $76 == {B $800F}     ; инструкция HALT записывается по адресу $800F (BEGIN+1)


DISPLAY <байты>

Эта псевдо-операция аналогична операции ассемблера ALARM компьютера ZX-Spectrum.

Выводит на консоль строку байтов. Каждое значение должно быть в диапазоне от -129 до 256. Ключи /D, /B, /C, /H и /A задают формат вывода чисел:

/D - вывод только в десятичном формате
/B - вывод только в двоичном формате (усекает число до 8 бит)
/C - выводится как символ в апостроф (усекает число до 8 бит)
/H - вывод только в шестнадцатеричном формате
/A - вывод как в шестнадцатеричном, так и в десятичном виде

Пример В 5.19.В docs_examples/po_display.asm

    ORG 100h
TESTLABEL:
    ;...какой-то код...
    RET
    DISPLAY "--эта программа - написана  мной"
    DISPLAY "TESTLABEL address is:",/A,TESTLABEL
/*
будет выводить на консоль строки:
> --эта программа - написана  мной
> TESTLABEL address is:0x100, 256
*/


DM

Аналогична директиве BYTE.

DS

Аналогична директиве BLOCK.

DUP <число_повторов>[, <индексируемая_переменная>]

DUP указывает количество повторов строк, которые расположены до псевдо-операции EDUP. DUP может быть использован в макросах.

Необязательным вторым аргументом (начиная с версии v1.20.2) является имя метки (переменной), чтобы внутри повторяющихся блоков к этим меткам (переменным)были добавлены индексы повторения (значения 0, 1, 2, 3, ...).

ExampleВ 5.20.В 

    DUP 3 ; нулевое значение счетчика позволило бы пропустить весь блок
    NOP
    EDUP

/* будет представлено как:
    NOP
    NOP
    NOP
*/


DW

Аналогична директиве WORD.

DWORD

Определяет так называемое двойное слово. Значения должны быть между -2147483649 и 4294967296.

Пример В 5.21.В 

    DWORD 4000h,0d000h
    DWORD 4


DZ

То же, что и BYTE, но в конце будет добавлен дополнительный ноль.

Пример В 5.22.В 

    DZ 1      ; аналогично BYTE 1,0
    DZ "kip"  ; аналогична BYTE "kip",0


EMPTYTAP <имя_файла_магнитофонной_записи>

Полезно только для пользователей ZX-Spectrum

Создайте новый или перезапишите существующий стандартный файл магнитофонной записи для эмуляторов ZX-Spectrum. Смотрите пример SAVETAP.

EMPTYTRD <имя_файла_образа_TRD>[,<имя_диска>]

Полезно только для пользователей ZX-Spectrum

Создайте пустой TRD-образ для эмуляторов ZX-Spectrum. Смотрите пример SAVETRD.

ENCODING <кодировка>

Полезно только для пользователей, не владеющих английским языком

Установить текущую кодировку символов, т.е. если вы установите "DOS", SjASMPlus автоматически преобразует строки из ANSI в DOS-866. Кодировка может быть "DOS" (DOS-866) или "WIN" (ANSI/Win1251). Значение по умолчанию - "WIN".

Пример В 5.23.В 

    ENCODING "WIN"
    DB "тексттекст" ;will be тексттекст
    ENCODING "DOS"
    DB "тексттекст" ;will be ⥪бв⥪бв


END [<стартовый_адрес>]

На указанном адресе ассемблер остановится. Псевдо-операция AND не работает в начале строки (даже с --dirbol). Можно использовать необязательный аргумент SAVEZNA, SAVECPCSNA, SAVE TAPE и SAVE NEXT.

ENDLUA

Смотри LUA для получения дополнительной информации.

ENDMOD

Аналогичен ENDMODULE.

ENDMODULE

Служит для указания конца модуля (см. MODULE).

ENDT

Аналогичен ENT.

ENT

Восстанавливает текущий адрес. СмотриDISP для получения дополнительной информации.

<метка> EQU <выражение>[,<номер_Страницы>]

Присваивает метке значение, отличное от текущего значения счетчика команд. Метка не должна быть определена ранее (вы можете присвоить ей только одно значение). Необязательный параметр номер_Страницы может принудительно ввести явное значение страницы для метки (для оператора$$label). Для изменяемых меток, содержащих временные значения, используйте DEFL.

Пример В 5.24.В 

Label EQU 3
Kip   EQU 0x23*256 + low $


EXPORT <метка>

Именованная метка будет записана в экспортный файл в виде 'метка: EQUAL значение'. Таким образом, экспортный файл может быть включен в другие источники. Порядок меток в файле соответствует порядку инструкций EXPORT.

Пример В 5.25.В 

DRIE=3
    EXPORT DRIE  ; добавляет в файл экспорта строку: "DRIE: EQU 0x00000003"


FPOS <позиция>

Директива FPOS позволяет установить положение файла в любом месте выходного файла. Значение позиции без знака используется в качестве устанавливаемого абсолютного значения, позиция, начинающаяся со знака + или -, будет использоваться в качестве относительного положения.

В сочетании с OUTPUT <имя_файла>,r можно перезаписать существующие файлы.

Пример В 5.26.В 

; Результатом этого примера будет файл длиной в один байт:
    BYTE 0
    FPOS 0
    BYTE 1
    END


HEX

Аналогичен DH, обычно используется без кавычек вокруг данных.

INCBIN <имя_файла>[,<смещение>[,<длина>]]

Записывает двоичный файл в выходной файл. Смещение и длина необязательны. Добавлено в версии v1.12.1: если указано отрицательное смещение или длина, они отсчитываются относительно конца файла.

Пример В 5.27.В 

    INCBIN "gfx.scc",7        ; записывает файл gfx.scc, пропустив первые 7 байт
    INCBIN "rantab.com",3,256 ; записывает 256 байт из указанного файла со смещением 3 байта от начала
    INCBIN gfx.scc ,,7        ; аписывает 7 байт со смещением 0 (имя файла без кавычек должно заканчиваться пробелом)
    INCBIN "48.rom",-768,-256 ; включить (из файла 48.rom) 512 байт 15616..16127


INCHOB <имя_файла>[,<смещение>[,<длина>]]

Записывает данные из файла hobeta в выходной файл. Смещение и длина необязательны.

Пример В 5.28.В 

    INCHOB "gfx.$c",7        ; включает gfx.scc, пропустив первые 7 байт
    INCHOB "sprs.$c",3,256   ; включает 256 байт из файла со смещением 3 байта
    INCHOB gfx.$c ,7        ; обратите внимание на пробел между именем файла и ',7' :)


INCLUDE <имя_файла>

Включает другой исходный файл в текущий. Исходные файлы могут быть вложены на глубину 20 уровней. Если файл не может быть найден в текущем каталоге (текущий каталог - это каталог, из которого поступает текущий файл asm!), поиск файла будет произведен в каталогах, указанных в командной строке. При использовании угловых скобок поиск в каталогах командной строки выполняется перед текущим каталогом.

Каталог, используемый для запуска процесса сборки, автоматически добавляется в список (как если бы "-i." был добавлен в командную строку вручную) (версии v1.14.0 и v1.14.1 его не добавляют, возвращены обратно для версии v1.14.2). Если вы хотите начать с полностью пустого списка включаемых путей, используйте вначале опцию "--inc" (порядок имеет значение) без "=", чтобы очистить текущий список, например: sjasmplus --inc --inc=path1 --inc=path2 file.asm

Пример В 5.29.В 

    INCLUDE <VDP.I>     ; ищет файл "VDP.I" во включенных каталогах, затем в текущем
    INCLUDE MORE.I      ; ищет файл "MORE.I" в текущем каталоге, затем во включенных каталогах
    INCLUDE "MORE.I"


INCLUDELUA <имя_файла>

Добавляет другой LUA-скрипт в первый проход(!). Если файл не может быть найден в текущем каталоге (текущий каталог - это каталог, из которого поступает текущий файл), поиск файла будет произведен в каталогах, указанных в командной строке. При использовании угловых скобок поиск в каталогах командной строки выполняется перед текущим каталогом.

Пример В 5.30.В 

    INCLUDELUA <mylibrary1.lua>
    INCLUDELUA mylibrary2.lua
    INCLUDELUA "library_for_zx.lua"


INCTRD <имя_файла_TRD_образа>,<имя_файла_в_TRD_образе>[,<смещение>[,<длина>]]

Добавляет файл из TRD образа в выходной файл. Смещение и длина необязательны.

Пример В 5.31.В 

    INCTRD "test.trd","mygfx.C" ; добавить файл mygfx.C из образа test.trd
    INCTRD "test.trd","mygfx.C",12 ; добавить mygfx.C из образа test.trd, пропустив первые 12 байт


INSERT <имя_файла>[,<смещение>[,<длина>]]

INSERT аналогичен команде INCBIN. Смотри выше.

LABELSLIST <имя_файла>[,<виртуальные метки>]

Полезно только для эмулятора ZX-Spectrum UNREAL SPECCY.

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Сохраняет список меток в формате:

NN:ADDRESS LABELNAME

где NN - номер страницы памяти, а АДРЕС усечен до диапазона 0000..3FFF

Если <виртуальные метки> отличны от нуля, то номер страницы NN не является частью выходных данных, а АДРЕС усекается до диапазона 0000..FFFF.

Пример В 5.32.В 

    LABELSLIST "x:/somepath/user.l"


LUA [pass]

Используя псевдо-операции LUA и END LUA, вы можете вставлять скрипты Lua. Смотрите больше в главе "Lua скрипты".

Параметр необязателен. Это может быть:

PASS1 - интерпретирует Lua-скрипт только при первом проходе.
PASS2 - интерпретирует Lua-скрипт только со второго прохода.
PASS3 - интерпретирует Lua-скрипт только на третьем проходе. По умолчанию.
ALLPASS - интерпретирует Lua-скрипт во всех проходах. Это необходимо, если вы генерируете какой-то код Z80.

Приимер В 5.33.В 

    LUA
-- некоторые комментарии
        print "Hi, man! This is Lua!"
    ENDLUA
; теперь немного кода:
    LUA ALLPASS
        _pl("LABEL LD A,10")
        _pc("RET")
    ENDLUA


MEMORYMAP

Пока недоступно.

MMU <номер первого слота или адрес> [<номер последнего слота или адрес>|<опция с одним слотом>], <номер страницы>[,<адрес>]

Сопоставляет страницу(ы) памяти со слотом(ами), аналогично комбинации СЛОТ + СТРАНИЦА, но позволяет настроить весь диапазон последовательных слотов (с последовательными страницами памяти). Или, если указан только один слот, можно использовать дополнительную опцию для расширения функциональности конкретного слота. Поведение слота будет оставаться заданным на текущем УСТРОЙСТВЕ до тех пор, пока другой MMU не сбросит его, указав тот же слот (даже как часть диапазона, что приведет к сбросу параметра до "по умолчанию").

Необязательный третий аргумент - это адрес директивы ORG.

(начиная с версии v1.18.1) Вы также можете использовать начальный адрес конкретного слота вместо его номера, т.е. для ZX128: MMU $8000,3 - это псевдоним MMU 2,3

Опция с одним слотом (состояние по умолчанию: без ошибок / предупреждений и нет переноса = ничего особенного):

e = ошибка при записи за пределы последнего байта слота
w = предупреждение о записи за пределы последнего байта слота
n = перенести адрес обратно в начало слота, отобразить следующую страницу

Пример В 5.34.В docs_examples/po_mmu.asm

    DEVICE ZXSPECTRUM128 : LABELSLIST "po_mmu.lbl"  ; сохранить список меток для контроля
    MMU 1 3, 5      ; поменять слоты 1, 2, 3 со страницами 5, 6, 7
    ORG 0xBFFF
label1_p6: scf      ; последний байт страницы 6 (в слоте 2)
label2_p7: scf      ; первый байт страницы 7 (в слоте 3)

    MMU 3 e, 0      ; страница 0 в слот 3, запись за пределы слота приведет к ошибке
    ORG 0xFFFF
    ld  a,1         ; ошибка: Запись за пределы слота памяти: 65536 (65536 = внешний адрес)

    MMU 3 n, 1      ; страница 1 в слот 3, сделайте так, чтобы она автоматически переносилась + отображалась следующая страница
    ORG 0xFFFF      ; ! также адрес $ был усечен MMU с $10001 до $0001 !
label3_p1: scf      ; последний байт страницы 1, затем перенос обратно в 0xC000 со страницей 2
label4_p2: scf      ; первый байт страницы 2 в 0xC000


MODULE <имя>

Метки должны быть уникальными только внутри текущего модуля (модуль добавляется к ним в качестве префикса). Также обратите внимание на использование оператора '@' для подавления всей этой обработки меток. Модули могут быть вложенными, и модуль должен заканчиватьсяENDMODULE.

Пример В 5.35.В docs_examples/po_module.asm

    MODULE xxx
Kip:                ; метка xxx.Kip
    ld  hl,@Kip     ; глобальная переменная Kip
    ld  hl,@Kop     ; глобальная переменная  Kop
    ld  hl,Kop      ; xxx.Kop
Kop:                ; метка xxx.Kop
    ld  hl,Kip      ; xxx.Kip
    ld  hl,yyy.Kip  ; yyy.Kip
    ld  hl,nested.Kip   ; xxx.nested.Kip
        MODULE nested
Kip:        ret     ; метка xxx.nested.Kip
        ENDMODULE
    ENDMODULE

    MODULE yyy
Kip:    ret         ; метка yyy.Kip
@Kop:   ret         ; метка Kop (глобальный, без префикса модуля)
@xxx.Kop: nop       ;ОШИБКА: повтор: метка xxx.Kop
    ENDMODULE

Kip     ret         ; глобальная метка Kip


Начиная с версии v1.14.0 модуль <имя> НЕ МОЖЕТ содержать символ точки. Вы можете использовать вложенные модули, чтобы получить идентичный идентификатор, как в старых версиях, или, пожалуйста, переименуйте с подчеркиванием:

    ; недействителен с версии v1.14.0
        MODULE older.version
fn1:        ret        ; окончательная метка: @older.version.fn1
        ENDMODULE
    ; может быть заменен с версии v1.14.0 на
        MODULE new
            MODULE version
fn1:            ret    ; окончательная метка: @new.version.fn1
            ENDMODULE
        ENDMODULE

Начиная с версии v1.14.0MODULE и ENDMODULE также сбрасывает текущий "нелокальный" префикс метки обратно на "_":

Kep:    ; "Kep" метка (глобальная), а также работает как "нелокальный" префикс для локальных меток
    MODULE zzz
.local: ; в версии v1.14.0 это будет метка "zzz._.local", ранее это была метка "zzz.Keep.local".
Kup:    ; это "zzz.Kup", но также определяет "нелокальный" префикс как "Kup".
.local  ; это "zzz.Kup.local"
    ENDMODULE
.local: ; в версии v1.14.0 это будет метка "_.local", ранее это была "Kup.local".

OPT [push] [reset] [listoff] [liston] [listall] [listact] [listmc] [<опции командной строки>]

OPT pop

Позволяет сбросить и изменить параметры влияющие на синтаксис и синтаксический анализ (для строк исходного кода, следующих за OPT). Варианты, разрешенные для OPT, следующие: -W[no-]<warning_id>, --syntax, --zxnext, --reversepop и --dirbol.

Перед опциями вы можете использовать команды OP: push, pop, reset, listoff, liston, listall, listact, listmc. Команда "push" сделает выбор в пользу сохранения текущего состояния опций. Команда "reset" приведет к возврату параметров, связанных с выбором, в состояние по умолчанию. Команда "listoff" приостановит отображение списка для следующих строк до тех пор, пока не будет использована команда "liston" (доступность списка является частью состояния push /pop, поэтому для отключения списка "nest" вы можете использовать "OPT pushlist off : ... код ... :OPT pop" кодовую последовательность). Команды "listall", "listact" и "listmc" выберут фильтр для включения в список. В "listmc" перечислены только строки, содержащие байты машинного кода, "listact" удалит "пропущенные" блоки (например, ложные блоки условной сборки IF/ELSE или внутренние определения макросов и структур), "listall" переключится обратно на список по умолчанию без фильтрации.

Затем применяются предоставленные параметры. Значения по умолчанию: поддельные инструкции включены (без предупреждения), разделитель с несколькими аргументами равен ",", для доступа к памяти можно использовать скобки () и [], метки могут иметь любое имя, инструкции ZX Next отключены, POP с несколькими аргументами не отменяет их и псевдо-операции в начале строки выключены (чтобы просто вернуться к этим значениям по умолчанию, вы можете использовать OPT reset).

Команда "pop": восстанавливается ранее сохраненное состояние опций (состояния сохраняются в "стеке", поэтому дальнейший выбор с помощью "pop" восстановит более старые состояния).

Состояние системы с предупреждением об идентификаторе не сохраняется/не восстанавливается с помощью опций OPT push/pop/reset и может быть изменено только с помощью опции -W.

Пример В 5.36.В docs_examples/po_opt.asm

    POP bc, hl   ; вначале выполняется pop BC
    OPT push reset --reversepop --syntax=af
    POP bc,,hl   ; вначале выполняется pop HL
    LD  bc,hl    ; предупреждение о поддельной инструкции
    LD  bc,hl    ; предупреждение подавлено строчным словом "fake" в этом комментарии
    OPT reset --syntax=a
    POP bc,,hl   ; pop BC первое (опция --reversepop сброшена)
    OPT pop      ; восстановление синтаксиса в исходное состояние

ORG <адрес>[,<номер_страницы>]

Установите программный счетчик на определенный адрес. Если указан второй аргумент, это изменит страницу памяти в текущем слоте, см. PAGE и SLOT (он предупредит вас, когда <адрес> находится за пределами этого).

При использовании внутри блока DISP, затрагивается только виртуальный счетчик "смещенных" программ, но машинный код по-прежнему будет последовательно выдаваться в исходном физическом местоположении и будет выдано предупреждение.

Пример В 5.37.В docs_examples/po_org.asm

    ORG 100h ; or 0x100, or $100, or #100

    ; полезный макрос, дополняющий код
    MACRO PADORG addr
         ; добавить отступы
         IF $ < addr
         BLOCK addr-$
         ENDIF
         ORG addr
    ENDM

    MACRO PADORG2 addr ; замена "FORG" z80asm
         ; добавить отступ + отобразить предупреждение
         IF $ > addr
           ; без отступов
           DISPLAY /L, "Warning! PADORG failed! ", $, " is more than ", addr
         ELSE
           ; добавить отступы
           BLOCK addr-$
         ENDIF
         ORG addr
    ENDM


OUTEND

Завершает генерацию выходных данных компилятора в файл, указанный в OUTPUT, и сбрасывает значение SIZE на значение по умолчанию "нет".

OUTPUT [<имя_файла>[,<режим>]]

С помощью OUTPUT можно создать несколько файлов из одного источника. Все нижеследующие инструкции будут собраны в этот файл. Он также закроет close (OUTEND) и завершит все ранее открытые выходные данные.

Существует три возможных режима вывода: "truncate" - усечение (перезапись существующих файлов, это значение по умолчанию), "rewind" - перемотка назад (открывает и выполняет FPOS 0) и "append" - добавление (открывает и оставьте указатель на файл в конце файла).

OUTPUT <имя_файла>,t  ; truncate (по умолчанию)
OUTPUT <имя_файла>,r  ; rewind
OUTPUT <имя_файла>,a  ; append

Пример В 5.38.В bigfile.asm

    OUTPUT loader.com
    ORG 100H
    INCLUDE loader.asm
    INCLUDE bios.asm

    OUTPUT bigfile.dat
    ORG 4000H
    INCLUDE main.asm
    ORG 8000H
    INCLUDE data.asm
    OUTEND
    INCLUDE next.asm


Это создаст два файла: loader.com и bigfile.dat.

PAGE <номер>

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Устанавливает текущую страницу памяти в текущий слот.

ExampleВ 5.39.В 

    PAGE 7 ; установить 7 страницу
    SAVEBIN "ram7.bin",$C000,$4000 ;- записать $4000 байт из ОЗУ с адреса  $C000 в указанный файл


PHASE

Аналогичен DISP.

RELOCATE_END

Завершает блок кода, для которого создаются данные о перемещении (начинается с RELOCATE_START). Чтобы получить сами данные о перемещении, используйте RELOCATE_TABLE и связанные с ними символы.

Для получения более подробной информации / примеров ознакомьтесь с examples/relocation, examples/SymbOS_nslookup и relocation tests.

RELOCATE_START [HIGH]

Отмечает начало блока, для которого создаются данные о перемещении. Любая * обычная* метка (не символы EQUAL/DEFL), определенная внутри блока RELOCATE_START .. RELOCATE_END будет рассматриваться как метка "перемещаемый". Любая инструкция/директива внутри блока, для которой требуется скорректировать результирующий код операции при перемещении на другой адрес, создаст данные перемещения для RELOCATE_TABLE.

Команда RELOCATE_START HIGH проверяет только перемещение старших байтов. Созданная таблица указывает на старший байт (MSB) машинного кода. Этот режим предназначен для ОС / загрузчиков, которые перемещаются только в выровненные по 256 байтам границы (сохраняя LSB нетронутым).

Функция перемещения обычной метки является переходной, и присвоенное EQU значение, основанное на уже перемещаемой метке, также будет помечено как перемещаемое. Также структуры, созданные в перемещаемом блоке, имеют свои метки, помеченные как перемещаемые, и их начальные значения могут стать частью данных перемещения, если начальное значение основано на перемещаемом значении.

Вы можете добавить operator norel к метке, чтобы лишить ее свойства перемещения для конкретного выражения.

Внутренняя эвристика не является пуленепробиваемой, некоторое сложное выражение может не быть распознано как фиксированное / перемещаемое значение и вместо этого предупреждать о нестабильном результате. Рекомендуется собирать перемещаемые блоки в нижних областях адресного пространства(например, ORG 0 или ORG $1000) и чтобы выражения были достаточно простыми.

RELOCATE_TABLE [<вычитаемое_смещение>]

Выдает данные о перемещении, собранные по всем блокам перемещения. There are also two built-in symbols relocate_count и relocate_size содержащих размер таблицы (в sjasmplus поддерживаются только таблицы типа word, поэтому размер всегда равен удвоенному количеству).

Таблица представляет собой необработанный массив значений WORD (16 бит) со смещениями машинного кода в памяти, которые должны быть скорректированы (когда код перемещается по адресу, отличному от исходного базового адреса). Чтобы получить смещения от определенного базового адреса, используйте ORG перед блоком перемещения, чтобы получить инструкции и метки оттуда.

<вычитаемое_смещение> вычитается из каждого смещения, записанного в таблице перемещения (то же самое, что WinAPE делает со своим необязательным аргументом "base_address" для RELOCATE_TABLE).

REPT <число_повторов>[, <индексируемая_переменная>]

Аналог команды DUP. Также является аналогом блока REPT до ENDR (EDUP также работает).

SAVE3DOS <имя_файла>,<адрес>,<размер>[,<тип>[,<w2_line>[,<w3>]]]

Работает только в режиме эмуляции виртуального устройства. Смотри DEVICE.

Аналогично команде SAVEBIN, сохраняет блок оперативной памяти устройства, начиная с "адреса", но с добавлением заголовка +3 DOS 128 байт.

Пример В 5.40.В 

    DEVICE ZXSPECTRUM48
    ...

    ; +3 заголовок BASIC  (8 байт, начиная со смещением 15 байт в заголовке +3DOS):
    ; тип - первый байт (0 = базовый, 1, 2 = массивы, 3 = код/экран$)
    ; размер - "первое слово" (байты 1 и 2)
    ; аргумент w2_line - это "второе слово" (байты 3 и 4)
    ; аргумент w3 - "третье слово" (байты 5 и 6) (значение по умолчанию = размер)

    ; по умолчанию сохраняется тип=3 (КОД/ЭКРАН$)
    SAVE3DOS "screen.bin", $4000, $1b00
    ; тип 3: аргумент w2 $C000 является целевым адресом загрузки
    SAVE3DOS "code.bin", $8000, $1234, 3, $C000
    ; тип 0: BASIC, по умолчанию w2 = $8000 (без автозапуска)
    SAVE3DOS "prg1.bas", $5c00, 1234, 0
    ; тип 0: w2_line - это номер строки для автоматического запуска (в примере 30)
    SAVE3DOS "prg2.bas", $5c00, 1234, 0, 30
    ; тип 1: Числовой массив (для этого обратитесь к руководству +3)
    SAVE3DOS "b.dat", $8000, 30, 1
    ; тип 2: Массив символов (или, может быть, просто игнорировать их)
    SAVE3DOS "c.dat", $8000, 30, 2


SAVEAMSDOS <имя_файла>,<адрес>,<размер>[,<старт = 0>[,<тип = 2>]]

Работает только в режиме эмуляции виртуального устройства. Смотри DEVICE.

Как и SAVEBIN, сохраняет блок оперативной памяти устройства из "адреса", но с добавлением заголовка AMSDOS 128 байт.

Пример В 5.41.В 

    DEVICE AMSTRADCPC464
    ... некоторый код ...

    ; по умолчанию сохраняется тип=2 (ДВОИЧНЫЙ)
    ; значение "start" (запись) по умолчанию равно 0, здесь оно заменено на $1234
    SAVEAMSDOS "code.bin", $1000, $1b00, $1234


SAVEBIN <имя_файла>,<нчальный_адрес>,<длина_кода>

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Сохраняет блок оперативной памяти.

Пример В 5.42.В 

    PAGE 7 ;установите страницу 7 в текущий слот
    SAVEBIN "ram7.bin",$C000,$4000 ;- сохраните 4000h байт, начиная с 1000h из оперативной памяти, в файл
    SAVEBIN "ram2.bin",$8000,$3000 ;- сохраните 3000h байт, начиная с 8000h  из оперативной памяти, в файла


SAVECDT FULL <cdt_имя>[,<начальный_адрес>[,<режим_экрана>[,<бордюр>[,<ink0>...<ink15>]]]]

SAVECDT EMPTY <cdt_имя>

SAVECDT BASIC <cdt_имя>,<имя>,<начало>,<длина>

SAVECDT CODE <cdt_имя>,<имя>,<начало>,<длина>[,<пользовательский_начальный_адрес>]

SAVECDT HEADLESS <cdt_имя>,<начало>,<длина>[,<синхронизация>[,<формат>]]

Работает только в режиме эмуляции устройства Amstrad. Смотри DEVICE.

Манипуляции с файлом CDT (формат файла tape/TZX, используемый эмуляторами Amstrad CPC).

Пример В 5.43.В 

    DEVICE AMSTRADCPC6128
    ...
    ; создать пустой файл CDT (обрезает уже существующий файл, чтобы сделать его пустым)
    SAVECDT EMPTY "output.cdt"

    ; дамп в виде моментального снимка с загрузчиком по умолчанию, включая экран загрузки, все банки, ...
    SAVECDT FULL "output.cdt" ; по умолчанию: END стартовый адрес, режим экрана=1, бордюр=1
                              ; ink# = 1, 24, 20, 6, 26, 0, 2, 8, 10, 12, 14, 16, 18, 22, 24, 16

    ; BASIC программа подготовлена по адресу "label"
    SAVECDT BASIC "output.cdt","A",label,length

    ; блок двоичных данных по адресу "label" (по умолчанию "запись" = "label")
    SAVECDT CODE "output.cdt","C",label,length,entry

    ; блок без заголовка с пользовательской синхронизацией и форматом по адресу "label", форматы: 0 = AMSTRAD, 1 = ZX
    SAVECDT HEADLESS "output.cdt",label,length,sync,format ; по умолчанию sync = 0x16, format = 0


SAVECPCSNA <имя_файла>[,<стартовый_адрес_программы>]

Работает только в режиме эмуляции реального устройства AMSTRAD CPC464 / AMSTRAD CPC 6128. Смотри DEVICE.

Сохраняет снимок для эмуляторов машин Amstrad CPC. (Если начальный адрес опущен, используется адрес, указанный вEND)

Содержимое заголовка моментального снимка системы встроено в двоичный файл sjasmplus с регистрами CRTC, палитры и массива элементов устанавливается на значения CPC после загрузки в основное ПЗУ. Аналогично директиве ZX-Spectrum SAVESNA, прерывания отключены и должны быть повторно включены вашей программой. Полный список настроек можно найти в разделе источники. Если вам абсолютно необходимы другие значения по умолчанию и вы не можете позволить себе изменять состояние с помощью init-кода, вы можете выполнить последующее исправление результирующего файла моментального снимка системы непосредственно из исходного кода, смотри Вопрос #139 например.

Пример В 5.44.В 

    DEVICE AMSTRADCPC464
    ORG $1200
START  .... ;some code
    RET
    SAVECPCSNA "game.sna",START ;сохраняет снимок системы в файл game.sna. Начальный адрес - это START ($1200)


SAVEDEV <имя_файла>,<начальная_страница>,<начальное_смещение>,<длина>

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Как и SAVEBIN, Как и SAVE BIN, сохраняет блок оперативной памяти устройства.

Но это допускает длину более 64 кб, и значение смещения поступает непосредственно в виртуальную память устройства (где страницы выделяются последовательно), игнорируя текущее "отображение" слота. Т.е. страница = 2, смещение = 0 начнет сохранять данные со страницы 2 в ее начале, проходя через страницы 3, 4, 5, ... до тех пор, пока не будет сохранен запрошенный объем данных.

Смещение не ограничено размером страницы, т.е. аргументы page=1,offset=0x500 равны аргументам page=0,offset=0x4500 для устройства ZX SPECTRUM 128 (имеет размер страницы 0x4000).

Пример В 5.45.В 

    DEVICE ZXSPECTRUM128 : SAVEDEV "fullram.bin",0,0,0x20000 ; sсохранить все 128 Кб.

SAVEHOB <имя_файла>,<имя_файла_в_trdos>,<начальный_адрес>,<длина-кола>

Работает только в режиме эмуляции реального устройства. смотри DEVICE.

Сохраняет блок оперативной памяти в формате Hobeta.

Пример В 5.46.В 

    PAGE 7 ;установите 7 страницу в текущий слот
    SAVEHOB "ram7.$c","myfile1.C",$C000,$4000 ;- сохраните 4000h, начиная с 1000h оперативной памяти в файл
    SAVEHOB "ram2.$c","myfile2.C",$8000,$3000 ;- сохраните 3000h, начиная с 8000h оперативной памяти в файл


SAVENEX <команда> <аргументы_команды>

Команды для создания файла NEX, для получения подробной информации читайте главу SAVENEX .

Работает только в режиме эмуляции устройства ZX SPECTRUM NEXT. Смотри DEVICE.

SAVESNA <имя_файла>[,<стартовый_адрес-программы>]

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Сохраните снимок системы для эмуляторов ZX-Spectrum. (Если начальный адрес опущен, используется адрес, указанный в END )

Содержимое заголовка моментального снимка встроено в двоичный файл sjasmplus (отключенные прерывания могут удивить некоторых пользователей, вы можете проверить исходник чтобы увидеть все значения). Если вам абсолютно необходимы другие значения по умолчанию и вы не можете позволить себе изменять состояние с помощью init-кода, вы можете выполнить последующее исправление результирующего файла моментального снимка системы непосредственно из исходного кода, см. Вопрос #139, например.

Пример В 5.47.В 

    DEVICE ZXSPECTRUM128
    ORG $8000
START  .... ;некоторый код
    RET
    SAVESNA "game.sna",START ;сохраните снимок системы в файл game.sna. Начальный адрес - стартовый  ($8000)


SAVETAP <имя_файла>,BASIC,<файл_в_заголовке_ленты>,<старт>,<длина>[,<строка_автозапуска>[,<длина_без_переменных>]]

SAVETAP <имя_файла>,CODE,<файл_в_заголовке_ленты>,<старт>,<длина>[,<пользовательский_начальный_адрес_>[,<необязательный_3-й_параметр>]]

SAVETAP <имя_файла>,NUMBERS,<файл_в_заголовке_ленты>,<старт>,<длина>[,<буква_переменной(A..Z)>]

SAVETAP <имя_файла>,CHARS,<файл_в_заголовке_ленты>,<старт>,<длина>[,<буква_переменной(A..Z)>]

SAVETAP <имя_файла>,HEADLESS,<старт>,<длина>[,<пользовательский_флаг_блока(0..255)>]

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Добавьте заголовок ленты или блок данных в конец стандартного файла ленты для эмуляторов ZX-Spectrum.

Пример В 5.48.В 

    DEVICE ZXSPECTRUM48
    ...
    EMPTYTAP "output.tap"

    SAVETAP "output.tap",BASIC,"noAutorun",label,100
    SAVETAP "output.tap",BASIC,"w/Autorun",label,100,9999
    SAVETAP "output.tap",BASIC,"withVars",label,123,9999,100
    SAVETAP "output.tap",CODE,"bank17",screen,6912
    SAVETAP "output.tap",CODE,"screen",demo,length,org
    SAVETAP "output.tap",NUMBERS,"dimArray",label,100      ; a()
    SAVETAP "output.tap",NUMBERS,"othernum",label,200,'b'  ; b()
    SAVETAP "output.tap",CHARS,"charArray",label,300       ; a$()
    SAVETAP "output.tap",CHARS,"nextone",label,400,'m'     ; m$()
    SAVETAP "output.tap",HEADLESS,start,length


SAVETAP <имя_файла>[,<начальный_адрес_программы>]

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Сохраните файл на магнитной ленте для эмуляторов ZX-Spectrum в виде "моментального снимка" почти всей памяти. Сгенерированный файл ленты поддерживает клоны ZX-Spectrum с расширенной оперативной памятью, такие как ATM Turbo 512 и т.д. (Если начальный адрес опущен, используется адрес, указанный в END)

Сохраненная память начинается с $5E00 (при этом данные экрана на $4000 определяются автоматически и при необходимости сохраняются в файле TAP). Сохраненная память автоматически очищается от нулевых значений в начале и в конце области (поместите маркеры ненулевых байтов вокруг области, которую вы хотите сохранить, если у вас есть байты с нулевым значением в начале или в конце вашего кода).

Пример В 5.49.В 

    DEVICE ZXSPECTRUM48
    ORG $7FFF
    DB $01      ; ненулевой маркер для хранения следующих обнуленных данных
DAT DS 1024, 0  ; обнулить данные на уровне с $8000 (1024 байта)
START  ....     ; некоторый код
    RET
    SAVETAP "game.tap", START ;сохраните снимок с ленты в файл game.tap. Начальный адрес - $8400


SAVETRD <имя_файла_trd_образа>,<имя_файла_в_trdos>,<адрес>,<длина>[,<строка_автозапуска_BASIC>[,<длина_минус_переменные>]]
SAVETRD <имя_файла_trd_образа>,|<имя_файла_в_trdos>,<адрес>,<длина>[,<строка_автозапуска_BASIC>]
SAVETRD <имя_файла_trd_образа>,&<имя_файла_в_trdos>,<адрес>,<длина>

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Сохраните память устройства в образ диска TRD. При сохранении двух файлов с одинаковым именем файла будет выдано предупреждение, но в каталоге диска будут созданы два файла (с одинаковым именем).

Добавление символа канала "|" перед именем файла заставит sjasmplus удалять старые файлы с таким же именем перед записью нового => функция, подобная замене. Если удаленный файл действительно занимал все сектора до свободного места в информации о диске, sjasmplus восстановит эти сектора обратно и сохранит поверх них новый файл (но в более сложных случаях он не будет выполнять полную перестановку / дефрагментацию, sjasmplus - это просто ассемблер, а не полнофункциональный инструмент для работы с изображениями TRD).

Добавление символа амперсанда "&" перед именем файла заставит sjasmplus искать существующий файл с запрошенным именем (последний из них, все более ранние дубликаты удаляются). Новое содержимое добавляется к файлу (добавление с выравниванием по сектору), и в записи каталога исправляется только количество секторов, максимум до 255 секторов. Это специальный режим для однофайловых больших загрузчиков.

Также поддерживаются неофициальные трехбуквенные расширения (официальные расширения только: B, C, D и #).

Пример В 5.50.В 

    EMPTYTRD "test.trd" ;создание пустого TRD образа
    PAGE 7 ; установать 7 страницу в текущий слот
    SAVETRD "test.trd","myfile1.C",$C000,$4000 ;- сохраните 4000h байт начиная с C000h оперативной памяти в файл TRD образа
    SAVETRD "test.trd","myfile2.C",$8000,$3000 ;- сохраните 3000h байт начиная с 8000h оперативной памяти в файл TRD образа
    SAVETRD "test.trd",|"myfile1.C",$B000,$400 ;- заменить старые файлы "myfile1.C" новым файлом с этим же именем
    SAVETRD "test.trd",&"myfile1.C",$9000,$734 ;- добавить данные в конец файла "myfile1.C"


SETBP [<выражение>]
SETBREAKPOINT [<выражение>]

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Добавит точку останова по адресу<выражение> в файл экспорта BPLIST. Если выражение не указано, будет использоваться счетчик текущей программы.

Пример В 5.51.В 

    BPLIST "cmd_line.options.txt" zesarux ; открыть список точек останова в формате "ZEsarUX"
start:
        nop     ; ZEsarUX не перехватит самую первую инструкцию загруженного файла моментального снимка системы
        SETBP   ; таким образом, точка останова перед второй инструкцией (после первого "nop")
        xor  a
        SETBP some_routine_label  ; установите также некоторую точку останова для другого кода по его метке
        SETBREAKPOINT $0D6B       ; псевдоним SETUP, работает идентично
        ; ... ваш код программы
					  


SHELLEXEC <имя_файла>[,<параметры>]

Запускает внешнюю программу <имя_файла> используя необязательную командную строку <параметры>.

Пример В 5.52.В 

    OUTPUT "mybin.bin"
    ; некоторый код
    IF ((_ERRORS = 0) && (_WARNINGS = 0))
        SHELLEXEC "x:/somepath/bin2tap.exe mybin.bin mytap.tap"
       ; or SHELLEXEC "x:/somepath/bin2tap.exe","mybin.bin mytap.tap"
    ENDIF


SIZE <размер_файла_в байтах>

Если результирующий файл меньше заданной длины, добавляется столько нулевых байт, сколько необходимо. Подробнее смотрите в OUTPUT.

Пример В 5.53.В 

    SIZE 32768       ; убедитесь, что размер файла будет 32 КБ


SLDOPT <тип> <аргументы>

Введите `COMMENT` - добавьте разделенный запятыми список ключевых слов с учетом регистра, которые будут обнаружены в комментариях в конце строки и экспортированы в Данные отладки на уровне источника (SLD). Конкретные ключевые слова зависят от отладчика, который вы используете для обработки данных SLD.

Пример В 5.54.В 

    DEVICE ZXSPECTRUM128
    SLDOPT COMMENT WPMEM, Log
    ORG $8000
        call init ; переменная Log (при вызове п/п "init") -  экспортируется в SLD
        ret       ; здесь нет ключевого слова - не экспортировано в SLD
var1    DB 1      ; WPMEM - экспортируется
var2    DB 2      ; WpMem - не экспортируется, чувствителен к регистру!


SLOT <номер_или_адрес>

Работает только в режиме эмуляции реального устройства. Смотри DEVICE.

Установите текущий слот. Слоты определяются псевдо-операцией DEVICE. Используйте псевдо-операцию PAGE чтобы сменить страницу в текущем слоте.

(начиная с версии v1.18.1) Вы также можете использовать начальный адрес конкретного слота вместо его номера, т.е. для ZX128: SLOT $8000 является псевдонимом SLOT 2

Пример В 5.55.В 

    DEVICE ZXSPECTRUM128
    SLOT 3 ;от 0C000h до 0FFFFh
    PAGE 1 ;установите страницу 1 в слот 3
    ORG 0C000h
    ;ваша программа здесь
    PAGE 2
    INCBIN "somegfx.bin"
    ;....


TAPEND

Завершает генерацию выходных данных компилятора в блок ленточного файла, указанного в TAPOUT.

TAPOUT <имя_файла>[,<байт_флага>]

Добавляет один блок ленты в конец указанного файла. Весь следующий код будет собран в этот блок ленточного файла.

Значение байта флага по умолчанию равно 255.

Пример В 5.56.В bigfile.asm

    EMPTYTAP screen.tap

    TAPOUT screen.tap,0
    DB 3
    DB 'ScreenName'
    DW 6912
    DW 16384
    DW 32768
    TAPEND

    TAPOUT screen.tap
    INCBIN screen.bin
    TAPEND


Эта программа создаст tap-файл с содержимым экрана.

TEXTAREA <адрес>

Аналог DISP.

UNDEFINE <идентификатор>

Удаляет идентификатор, определенный с помощью DEFINE

Пример В 5.57.В 

    DEFINE Release 1

    IFDEF Release
      DISPLAY "Building release version"
    ENDIF

    UNDEFINE Release

    IFNDEF Release
      DISPLAY "It's works!"
    ENDIF

    IFDEF _SJASMPLUS
      DISPLAY "Yes, it's the sjasmplus!"
    ENDIF

    UNDEFINE *  ; удаляет все идентификаторы

    IFNDEF _SJASMPLUS
      DISPLAY "It's not the sjasmplus??"
    ENDIF


UNPHASE

Аналог ENT.

WHILE <выражение>[, <guardian-counter>]

В то время как выражение принимает ненулевое значение, генерирует следующие строки до тех пор, пока не встретится END (EDUP/ENDR псевдоним) псевдопереработка.

Необязательное значение guardian-counter приведет к прерыванию WHILE, если будет больше итераций, чем указано в guardian-counter, значение guardian-counter по умолчанию равно 100k.

Пример В 5.58.В 

ptr = $4000
    WHILE ptr < $4020, 500 ; максимум  500 повторов до сообщения об ошибке
        DB low ptr
ptr = ptr + 1
    ENDW    ; EDUP или ENDR тоже работают, но для  цикла WHILE рекомендуется применять ENDW

/* будет выдавать байты $00, $01, ..., $1F */


WORD <слова>

Определяет слово. Значения должны находиться в диапазоне от -32787 до 65536.

Пример В 5.59.В 

    WORD 4000h,0d000h
    WORD 4,"HA"


Условная сборка

Может оказаться полезным собрать часть исходника (или нет) в зависимости от определенного условия.

IF <выражение>

Если <выражение> отличается от нуля, следующие строки собираются до тех пор, пока не встретится опертор ELSE, ELSEIF или ENDIF.

Прямая ссылка на метку вызовет предупреждение, поскольку любой машинный код, выдаваемый внутри блока IF/IFN с таким выражением, может привести к нестабильным результатам. Если вы уверены, что позднее определение метки не повлияет на результирующий машинный код (блок IF не выдает никакого машинного кода и не определяет никакой метки), вы можете отключить предупреждение.

Ghbvth В 5.60.В 

    IF (aaa == 0) || (2 = aaa && ((bbb % 13) & 0x01))
        ; некоторый код для сборки только в том случае, если символ `aaa` равен нулю
        ; или (логическое ИЛИ), когда символ `aaa` равен двум
        ; и (логическое И) остаток от деления на 13 от `bbb` является нечетным числом
    ENDIF


IFN <выражение>

Если <выражение> равно нулю, следующие строки собираются до тех пор, пока не встретится оператор ELSE, ELSEIF или ENDIF.

IFDEF <идентификатор>

Условие выполняется, если определен идентификатор. Это НЕ метки.

Пример В 5.61.В 

    IFDEF MSX_LEAN_AND_MEAN
        CALL InitOwnMM
    ELSE
        CALL InitDos2MemMan
    ENDIF


IFNDEF <идентификатор>

Условие истинно, если идентификатор не определен. Это НЕ метки.

Пример В 5.62.В 

1   IN A,(0C4H)
    AND 2
    IFNDEF DEBUG
        JR NC,1B
    ENDIF


IFUSED <метка>

Условие истинно, если где-то в коде используется метка. Вы можете создавать библиотеки полезных функций, используя псевдо-операцию IFUSED

Пример В 5.63.В (similar to tests/misc/ifused_test.asm)

    OUTPUT "TEST.OUT"

    CALL LABEL3 ; LABEL3 - да
    LD A,(LABEL1) ; LABEL1 - да

    IFUSED LABEL1
LABEL1:
    DB 1
    ENDIF

    IFUSED LABEL2
LABEL2:
    DB 2
    ENDIF

    IFUSED LABEL3
LABEL3:
    DB 3
    ENDIF

    IFUSED LABEL4
LABEL4:
    DB 4
    ENDIF

    LD A,LABEL2 ; LABEL2 - да

    RET

; Выходные данные будут содержать байты от LABEL1 до LABEL 3 (1, 2, 3), но не будут содержать байты от LABEL4, поскольку эта метка не используется.

; Альтернативный синтаксис:
LABEL5:
    IFUSED ; sjasmplus будет использовать название предыдущей метки, т.е. LABEL5

    ENDIF
    


Известная ошибка: когда код использует метку внутри модуля "module", например,call labelY, отмечается только использование модуля moduleX.labelY. Затем, если вы определите "label" вне модуля и спрячете его внутри блока IFUSED labelY, вызов из модуля не сможет найти процедуру.

Обходной путь: вы можете использовать оператор глобальной метки @: "call @labelY" чтобы инициировать использование глобальной "labelY", или вы можете использовать альтернативный синтаксис IFUSED "labelY: IFUSED" который не только проверяет условие, но и определяет метку. Как только метка определена, строка "call labelY" внутри модуля найдет глобальный вариант и правильно пометит его как "используемый" ("used").

Локальные метки внутри блока предохранителей не видны до тех пор, пока не будет использована основная метка, если вы хотите вызвать только локальную метку, вы можете принудительно настроить видимость процедуры с помощью "ASSERT main_label" - это вызовет использование глобальной "main_label", а затем блок IFUSED будет собран, и локальные метки тоже станут видимыми.

IFNUSED <метка>

Условие истинно, если где-то в коде есть метка, которая не используется.

ELSE

Смотри IF. Если условие IF равно false (во всех предыдущих блоках IF/ELSEIF), else-часть компилируется.

ELSEIF <выражение>

Если предыдущий IF-блок имел условие false, вычисляется выражение ELSEIF, и ELSEIF действует как новое IF.

ENDIF

За каждым IF должен следовать ENDIF.

Макросы

Псевдо-операция MACRO определяет макрос. За ним должно следовать название макроса, необязательно сопровождаемое параметрами. Следующие строки будут храниться как тело макроса до тех пор, пока не будет обнаружена псевдо-операция END. Макросы должны быть определены перед их использованием. Имя макроса должно быть уникальным (даже если два макроса отличаются обязательными аргументами).

Пример В 5.64.В Макрос без параметров (docs_examples/s_macros.asm)

  MACRO ADD_HL_A
    ADD A,L
    JR NC,.hup
    INC H
.hup
    LD L,A
  ENDM


Метки в макросе, начинающиеся с точки, являются локальными для каждого расширения макроса.

Пример В 5.65.В Макрос с параметрами (docs_examples/s_macros.asm)

  MACRO WAVEOUT reg, data
    LD A,reg
    OUT (7EH),A
    LD A,data
    OUT (7FH),A
  ENDM
; этот макрос преобразует
  WAVEOUT 2,17
; в следующий код:
  LD A,2
  OUT (7EH),A
  LD A,17
  OUT (7FH),A


Пример В 5.66.В Другой пример (docs_examples/s_macros.asm)

    MACRO LOOP
      IF $-.lus<127
        DJNZ .lus
      ELSE
        DEC B
        JP NZ,.lus
      ENDIF
    ENDM

Main
.lus
    CALL DoALot
    LOOP
; Будет преобразовано в:
Main
.lus                  ; Main.lus
    CALL DoALot
    DJNZ .lus         ; Main.lus


Угловые скобки можно использовать, если аргументы содержат запятые.

Пример В 5.67.В Аргумент в угловых скобках (docs_examples/s_macros.asm)

    MACRO UseLess data
      DB data
    ENDM

    UseLess <10,12,13,0>
; преобразуется в:
    DB 10,12,13,0

; используйте "!", чтобы включить "!" и'>' в этих строках.

    UseLess <5, 6 !> 3>
; преобразуется в:
    DB 5, 6 > 3

    UseLess <"Kip!!",3>
; преобразуется в:
    DB "Kip!",3


Для удобства совместимости, чтобы несколько упростить перенос с разных ассемблеров, существует альтернативный синтаксис, где имя макроса пишется в начале строки (как если бы это была метка, но часть МОДУЛЯ НЕ применяется к имени макроса).

Пример В 5.68.В Имя макроса в начале строки (docs_examples/s_macros.asm)

LabelAsMacroName    MACRO  arg1?, arg2?
                        ld  a,arg1?
                        ld  hl,arg2?
                    ENDM

                LabelAsMacroName 1,$1234
            ; преобразуется в:
                ld a,1 : ld hl,$1234


Если какой-либо макрос затеняет обычную инструкцию или имя директивы, то @ символ перед именем инструкции/директивы может использоваться для запрета расширения макроса.

Пример В 5.69.Запрет оператору макрорасширения (docs_examples/s_macros.asm)

djnz    MACRO   arg1?
            dec c
            jr  nz,arg1?
            @djnz arg1? ; избегайте ссылок на себя и используйте реальные инструкции
        ENDM

1:      djnz    1B      ; здесь будет использоваться замена макроса
1:      @djnz   1B      ; здесь оригинальная инструкция djnz 


Глава В 6.В Структуры

Что такое структуры?

Структуры можно использовать для более легкого определения структур данных в памяти. Название структуры задается в соответствии с общим размером структуры.

Определение структуры

Определение структуры начинается с: STRUCT <имя>[,<начальное смещение>] и заканчивается словами ENDS. Определения структуры являются локальными для текущего модуля, но, как и в случае с метками, '@' может использоваться для переопределения этого.

Строки между STRUCT и ENDS должны иметь следующий формат:

имя_участника псевдооперации операнды

Все поля являются необязательными. Строки без метки должны начинаться с пробела.

Когда используется ненулевое смещение , оно действует так, как если бы BLOCK with length equal to смещение было определено как первый член структуры.

STRUCT инструкции

Между псевдо-инструкциями STRUCT и ENDS могут быть использованы следующие инструкции:

BYTE [<значение_по_умолчанию>]

Определяет однобайтовый элемент. Значение по умолчанию используется, когда при объявлении структуры не задается значение инициализации. (Вместо BYTE могут использоваться DB и DEFB).

WORD [<значение_по_умолчанию>]

Определяет двухбайтовый элемент. Значение по умолчанию используется, когда при объявлении структуры не задается значение инициализации. (Вместо WORD могут использоваться DW и DEFW).

D24 [<значение_по_умолчанию>]

Определяет трехбайтовый элемент. Значение по умолчанию используется, когда при объявлении структуры не задается значение инициализации.

DWORD [<значение_по_умолчанию>]

Определяет четырехбайтовый элемент. Значение по умолчанию используется, когда при объявлении структуры не задается значение инициализации. (Вместо DWORD могут использоваться DD и DEFD).

TEXT <длина>[,{<DB-подобный(е) операнд(ы)>}]

(начиная с версии v1.17) Для определения элемента указанной длины в байтах. Операнды отформатированы в DB-подобном формате, и последний явно определенный байт заполнит оставшиеся байты, зарезервированные при определении (обнуляются, если значение вообще не указано).

Значение по умолчанию может быть изменено с помощью значений init, когда используется структура, но тогда только заданные байты перезаписывают содержимое по умолчанию, НЕ заполняя его остальную часть.

Хотя операнды отформатированы в формате DB, они должны быть заключены в фигурные скобки. Также убедитесь, что фигурные скобки не перепутаны с необязательными фигурными скобками на границах подструктуры, при использовании элемента TEXT в подструктуре вам может потребоваться использовать фигурные скобки для самой подструктуры вокруг фигурных скобок, используемых для значений TEXT (что делает фигурные скобки подструктуры обязательными в таком случае). Длина может составлять от 1 до 8192 байт (если вам нужен еще более длинный "текст", используйте два члена и разделите свои аргументы).

BLOCK <длина>[,<заполняющий_байт>]

Чтобы определить элемент из указанного количества байт. Аргументы задаются при определении текущей структуры и не являются частью значений init при последующем использовании структуры. (Вместо BLOCK могут использоваться '#', DS и DEFS).

(начиная с версии v1.11), если заполняющий_байт опущен, содержимое памяти устройства в области блока сохраняется (не обнуляется).

ALIGN [<выражение>[, <байт>]]

Выравнивает смещение. Если выражение опущено, предполагается значение 4. ('##' может использоваться вместо ALIGN).

(начиная с версии v1.11) Если байт опущен, содержимое памяти устройства сохраняется (не обнуляется).

<имя структуры> [<начальное значение>]

Можно вложить структуры и задать новые значения по умолчанию для элементов BYTE и WORD.

Использование определенной структуры

[<метка>] <имя_структуры> [<начальное_значение>] будет выдавать полную структуру в машинный код, либо используя значения по умолчанию из определения структуры, либо переопределяя их явным значением из списка <начальные_значения>. В начальных_значениях вы можете использовать фигурные скобки {} для группировки определенных начальных значений для конкретной подструктуры, любые отсутствующие значения в init-list конкретной подструктуры устанавливаются значениями по умолчанию для конкретного поля. Смотрите пример "SDOT" ниже или файлы tests/struct asm для получения дополнительных примеров.

<метка> <имя_структуры> = <выражени> будет настроена только <метка>.<struct_field> labels starting from designed address provided by метки, начинающиеся с заданного адреса, предоставленного выражением, но не будет выдаваться машинный код (и текущий адрес "$" не будет продвигаться).

(начиная с версии v1.17) Начальные значения внутри блока фигурных скобок теперь могут занимать несколько строк с новой строкой, заканчивающейся выражением текущего значения (запятая после выражения в таком случае необязательна). Пожалуйста, имейте в виду, что это выводит оригинальную архитектуру sjasmplus за рамки ее первоначального дизайна (многострочные определения) и может привести к сбою в сложных сценариях (например, макромеханика "точечного повторителя" будет повторять только оставшуюся часть текущей строки, игнорируя блок фигурных скобок, охватывающий следующие строки). Если у вас есть пример кода, который завершается ошибкой, но вы считаете, что это разумный вариант использования, пожалуйста, откройте проблему на github с таким примером, чтобы можно было улучшить функцию в будущем (повторитель точек - это случай "не исправит", но в остальном функция должна работать надежно).

Примеры

Пример В 6.1.В docs_examples/c_structures.asm

	STRUCT SCOLOR
RED	BYTE 4
GREEN	BYTE 5
BLUE	BYTE 6
	ENDS

Это идентично:

SCOLOR		EQU 3 ; длина
SCOLOR.RED	EQU 0 ; смещение
SCOLOR.GREEN	EQU 1 ; смещение
SCOLOR.BLUE	EQU 2 ; смещение

Пример В 6.2.В docs_examples/c_structures.asm

	STRUCT SDOT
X	BYTE
Y	BYTE
C	SCOLOR 0,0,0 ; используйте новые значения по умолчанию
	ENDS

Это идентично:

SDOT		EQU 5 ; length
SDOT.X		EQU 0 ; смещение
SDOT.Y		EQU 1 ; смещение
SDOT.C		EQU 2 ; смещение
SDOT.C.RED	EQU 2 ; смещение
SDOT.C.GREEN	EQU 3 ; смещение
SDOT.C.BLUE	EQU 4 ; смещение

Пример В 6.3.В docs_examples/c_structures.asm

	STRUCT SPOS,4
X	WORD
Y	BYTE
	ALIGN 2
AD	WORD
	ENDS

Это идентично:

SPOS	EQU 10 ; length
SPOS.X	EQU  4 ; смещение
SPOS.Y	EQU  6 ; смещение
SPOS.AD	EQU  8 ; смещение

Пример В 6.4.В docs_examples/c_structures.asm

Когда структура определена, с ее помощью можно объявлять метки

COLOR SCOLOR

Это идентично:

COLOR
COLOR.RED   BYTE 4
COLOR.GREEN BYTE 5
COLOR.BLUE  BYTE 6

Обратите внимание на значения по умолчанию.

Or without label:

COLORTABLE
  SCOLOR 0,0,0
  SCOLOR 1,2,3
  SCOLOR ,2
  ; и т.д..

Это идентично:

COLORTABLE
  BYTE 0,0,0
  BYTE 1,2,3
  BYTE 4,2,6
  ; и т.д..

DOT1 SDOT 0,0, 0,0,0     ; or 0,0,0,0,0 or {0,0,{0,0,0}}

Могут быть инициализированы только элементы BYTE и WORD.

Полученные метки можно использовать в качестве любой другой метки:

  ld b,(ix+SCOLOR.RED)
  ld a,(COLOR.GREEN)
  ld de,COLOR
  ; etc.

Пример В 6.5.В docs_examples/st_usage_example.asm

	STRUCT BIN_FILE_MAP, 256
value1	BYTE
value2	WORD
	ENDS

        ORG  0x8000
binData BIN_FILE_MAP = $        ; настраивает только значения меток (без байтов)
        INCBIN "some_data.bin"  ; вместо этого загружает байты из файла

        ; использование данных через определение структуры
        ld  a,(binData.value1)
        ld  hl,(binData.value2)

This is identical to:

BIN_FILE_MAP            EQU 259      ; length
BIN_FILE_MAP.value1     EQU 256      ; смещение
BIN_FILE_MAP.value2     EQU 257      ; смещение
; метки для доступа к двоичным данным, загруженным INCBIN
binData                 EQU 0x8000   ; адрес
binData.value1          EQU 0x8100   ; адрес
binData.value2          EQU 0x8101   ; адрес

Пример В 6.6.В docs_examples/st_text.asm

        STRUCT BLOCK_HEADER
length      WORD    BLOCK_HEADER
type        BYTE    $AB
name        TEXT    10, { "none", 32, '!' } ; выдаст "none!!!!!" данные по умолчанию
                    ; поскольку это определение поля, здесь последний байт является "заполнителем".
datastart   WORD
datalen     WORD
checksum    BYTE    $CC
        ENDS

        ORG  0x8000
head1   BLOCK_HEADER {      ; Для многострочной инициализации требуются фигурные скобки.
    , ,                     ; Сохранение длины и типа по умолчанию путем указания пустых значений.
    { 'New',                ; Окончательными данными `name` будут "New Name!!"
        32,                 ; перезапись только 8 байт данных по умолчанию.
        "Name" },           ; Последняя буква "e" НЕ является "заполнителем" в значении, отличном от значения по умолчанию.
        $8000, $1234        ; Явные значения datastart и datalen.
}                           ; Конец блока исходных данных ("контрольная сумма" сохраняет значение по умолчанию).

; машинный код (структурные данные):
; 12 00 AB 4E 65 77 20 4E 61 6D 65 21 21 00 80 34 12 CC
; = { $0012, $AB, "New Name!!", $8000, $1234, $CC }

Предупреждение

Не используйте смещенные метки в таких направлениях, как:

LD A,(SDOT.X)

Его воля противоречит дальнейшим "улучшениям" ;-)

Если это абсолютно необходимо (почему?), используйте что-то вроде этого:

LD A,(+SDOT.X)

Глава В 7.В Lua скрипты

Why?

Почему скриптовый движок в виде Lua встроен в компилятор? Ответ прост: он может быть использован пользователями для добавления дополнительных функций. А Lua - это достаточно маленький, быстрый и мощный скриптовый движок.

Начиная с версии v1.20.0, sjasmplus интегрирует Lua 5.4.4. До этого он использовал Lua 5.1.5 с несколькими сторонними внешними библиотеками, которые в основном были нефункциональными из-за пренебрежительного обновления инструмента tolua++ и самой интеграции. Обновление до Lua 5.4 было выполнено вместе с заменой tolua++ на LuaBridge2.6, и хотя было приложено много усилий для сохранения оригинальных привязок Lua к sjasmplus, в API внесено несколько изменений.

Если ваш старый исходный код больше не работает после обновления, пожалуйста, внимательно проверьте документацию по привязкам расположенную ниже.

Проверьте, действительно ли ваш код использует только официальный API, и если вы использовали секретные дополнительные аргументы, проверьте тестовые файлы и примеры того, как эти скрипты lua были скорректированы для сборки с версией v1.20.0. Документация по API привязок была очищена, некоторые API расширены и имеют лучшее тестовое покрытие, чтобы снизить вероятность изменений в будущем..

Также, пожалуйста, обратите внимание на критические изменения самого Lua и адаптируйте свои скрипты к синтаксису Lua 5.4 и библиотечным функциям, ниже приведен пример с уже встречающимися общими проблемами (откройте проблемы github с другими, чтобы мы могли добавить их в документы).

Как использовать?

Вы должны использовать псевдо-операции для начала LUA и для завершения ENDLUA.

Пример В 7.1.В Hello World!

    LUA
        print ("Hello World!")
    ENDLUA


Привязки функций SjASMPlus к Lua

Из Lua вы можете управлять некоторыми переменными и использовать функции компилятора. Полный список:

[integer] _c("выражение")

Вычисление выражения с помощью калькулятора компилятора (только 32-разрядный). Пример: val = _c("SOMELABEL+12")

[void] _pc("code")

Анализ строки ассемблера Z80. Пример: _pc("ADD A,B")

[void] _pl("label code")

Анализ строки ассемблера Z80. Пример: _pl("SOMELABEL ADD A,B")

Эта привязка делает почти все псевдоинструкции (директивы) доступными из Lua-скрипта со всеми опциями и функциями. В будущем API привязок будет в основном заморожен, расширяясь только в том случае, если использование_pl(...) слишком громоздко.

[integer] sj.calc("выражение")

Смотри _c

[void] sj.parse_code("code")

Смотри _pc

[void] sj.parse_line("label code")

Смотри _pl

[void] sj.error("сообщение","плохое_значение" = nil)

Печать сообщения об ошибке.

[void] sj.warning("сообщение","плохое_значение" = nil)

Вывести предупреждающее сообщение.

[boolean] sj.file_exists("имя_файла")

Проверить, существует ли файл.

[string] sj.get_define("имя", "include_macro_args" = false)

Получает значение define, возвращает nil, если define не найдено. При желании можно также выполнить поиск аргументов макроса (с более высоким приоритетом).

[boolean] sj.insert_define("id", "value" = "")

Добавляет новое определение. Возвращает true, если define является новым, false, когда define уже существовал и значение было заменено, или когда id недействителен.

[integer] sj.get_label("имя")

Получает адрес метки. Возвращает -1, если имя недопустимо, 0, если не найдено или все еще имеет неопределенное значение (вы также можете использовать _c("имя") чтобы получить значение символа и выполнить с ним некоторые вычисления).

[boolean] sj.insert_label("имя", адрес)

Добавляет новую метку. Возвращает true, если метка была успешно вставлена (или значение изменено в первый раз при следующем проходе сборки), false, если имя недопустимо или метка уже была определена.

[integer] sj.current_address

Переменная, доступная только для чтения. Текущий адрес.

[integer] sj.error_count

Переменная, доступная только для чтения. Количество ошибок.

[integer] sj.warning_count

Переменная, доступная только для чтения. Количество предупреждений.

[void] sj.exit(errorcode = 1)

Завершает работу компилятора.

[void] sj.add_byte(байт)

Добавляет байт на вывод (или в память) и увеличивает на 1 sj.current_address

[void] sj.add_word(слово)

Добавляет слово на вывод (или в память) и увеличьте на 2 sj.current_address

[integer] sj.get_byte(адрес)

Получает байт из памяти. Работает только в режиме эмуляции реального устройства и только на последнем этапе сборки.

[integer] sj.get_word(адрес)

Получает слово из памяти. Работает только в режиме эмуляции реального устройства и только на последнем этапе сборки.

[string] sj.get_device()

Возвращает идентификатор текущего эмулируемого устройства. Возвращает "NONE", если режим эмуляции отсутствует.

[boolean] sj.set_device("id" = "NONE", ramtop = 0)

Установливает идентификатор текущего эмулирующего устройства. Возвращает значение false, если запрошенный идентификатор устройства не найден и текущий набор устройств потерян (установлено значение "НЕТ").

[boolean] sj.set_page(номер)

Установливает "номер страницы" в текущий слот. Работает как псевдо-оператор PAGE.

[boolean] sj.set_slot(номер_или_адрес)

Установите для текущего слота значение "номер". Работает как псевдо-оператор SLOT.

(начиная с версии v1.20.0) Вы также можете вместо этого использовать начальный адрес слота, например, для ZX128 sj.set_slot(0x8000) является псевдонимом sj.set_slot(2).

[void] sj.shellexec("имя_программы")

Смотри псевдо-оператор SHELLEXEC.

[boolean] zx.trdimage_create("имя_trd_образа", "метка" = "")

Создает пустой файл TRD образа.

[boolean] zx.trdimage_add_file("имя_trd_образа", "какое-то_имя_C", начальный_адрес, длина, autostart = -1, replace = false)

Сохраняет блок памяти в файл образа TRD. Работать только в режиме эмуляции реального устройства.

[boolean] zx.save_snapshot_sna("имя_файла.sna", начальный_адрес_программы)

Сохранение моментального снимка памяти в формате SNA. Работает только в режиме эмуляции реального устройства и только для ZX SPECTRUM 48 и ZX SPECTRUM 128.

Встроенные библиотеки сторонних производителей

Не доступно на данный момент.

Начиная с версии v1.20.0, sjasmplus интегрирует Lua 5.4.4.

Библиотеки, включенные в более старые версии sjasmplus: lpack.c, bit (побитовые операторы) и hex (преобразование в / из шестнадцатеричных чисел), теперь все являются частью стандарта Lua 5.4.

Ссылка на Lua документацию Lua документацию для получения полного списка функций и подробной справки.

Для небольшого примера проверьте тест tests/lua_examples/trivial/lua_standard_libs.asm

Примеры

Пример В 7.2.В Переменные не очищаются при новых проходах компилятора

    LUA PASS1
       v = 1
    ENDLUA

    LUA PASS2
       print (v)
-- out to console: 1
       v = v + 1
    ENDLUA

    LUA PASS3
       print (v)
-- out to console: 2
    ENDLUA


Пример В 7.3.В Чтобы сгенерировать какой-либо код, вам нужно сгенерировать его во всех проходах

    LUA ALLPASS
        _pl("ClearScreen LD (.savesp+1),SP")
        _pc("LD SP,16384+6144")
        _pc("LD HL,0")
        for i = 32768, 38912, 2 do
            _pc("PUSH HL")
        end
        _pl(".savesp: LD SP,0")
        _pc("RET")
    ENDLUA

    LUA PASS2 ; если вы полностью понимаете, что делаете
        sj.add_byte(123) -- and you need emit bytes in other mode
    ENDLUA ; luamc-ok ; вы можете отключить предупреждение здесь или в начале блока


Пример В 7.4.В Объявляйте функцию и используйте ее

     LUA
         function savetape_mytype(имя_файла, начальный_адрес)
             local fp
             fp = assert(io.open(имя_файла, "wb"))
             for i = 16384, 32767, 4 do
                 assert(fp:write( string.pack("bbbb",
                                sj.get_byte(i),
                                sj.get_byte(i+1),
                                sj.get_byte(i+2),
                                sj.get_byte(i+3)) ))
             end
             assert(fp:flush())
             assert(fp:close())
         end
     ENDLUA

 ;где-то в вашей программе
     LUA
         savetape_mytype("tapefiles/myprogram.tape", _c("StartGameLabel"))
     ENDLUA


Пример В 7.5.В Простой образец :)

	LUA
-- Функция считывает число из файла <fname>, инкрементирует его, создает определение "BUILD" с числом и сохраняет число в <fname>.
-- С помощью этой функции вы можете контролировать количество компиляций.
	function increase_build(fname)
		local fp
		local build
		fp = assert(io.open(fname, "rb"))
		build = tonumber(fp:read("*all"))
		assert(fp:close())
		if type(build) == "nil" then
		    build = 0
		end
		build = build + 1;
		sj.insert_define("BUILD", build)
		fp = assert(io.open(fname, "wb"))
		assert(fp:write( build ))
		assert(fp:flush())
		assert(fp:close())
	end

-- Перед использованием вы должны создать пустой файл "build.txt"!
	increase_build("build.txt")

-- Создает определение "TIME" с текущим временем
	sj.insert_define("TIME", '"' .. os.date("%Y-%m-%d %H:%M:%S") .. '"')
	ENDLUA

; выводит на консоль ваше время и номер сборки
	DISPLAY "Build time: ", TIME
	DISPLAY "Build number: ", /D, BUILD


Пример В 7.6.В Распространенные проблемы при обновлении до Lua 5.4

  LUA ALLPASS
    x = 2.3 ^ 4.5             -- старый синтаксис: math.exp(2.3, 4.5)
    _pc("db " .. math.floor(x))
    _pc("db " .. 35//7)       -- старый синтаксис: 35/7
      -- значения с плавающей запятой теперь строго форматируются с помощью ".0" из Lua
      -- что приводит к ошибке в анализаторе sjasmplus: Unexpected: .0
      -- и требует применения целочисленного типа уже на стороне lua
      -- вы можете использовать либо функцию `math.floor()`, либо целое число
      -- такие операторы, как целочисленное деление `//` или сдвиг влево`1<<7`

    -- значения с плавающей запятой (например, "12.0") автоматически усекаются начиная с версии v1.20.1 (до "12"),
    -- но в версии v1.20.0 в них отсутствуют ошибки, если только вы не исправите lua-скрипт для получения целых чисел
  ENDLUA


Глава В 8.В Руководство SAVENEX

Формат файла NEX

NEX - это двоичный формат для ZX Spectrum Next, предназначенный для обеспечения простой доставки программного обеспечения для платформы. Для получения подробной информации о формате файла проверьте https://specnext.dev/wiki/NEX_file_format. Короче говоря, это заголовок + экран загрузки + двоичный snapshot-подобный файл и оставшиеся ресурсы, добавленные после.

Sjasmplus в настоящее время поддерживает версии V1.2 и V1.3 формата файлов NEX (подробности см. в wiki).

Таким образом, команды SAVENEX доступны только в режиме эмуляции устройства ZX SPECTRUM NEXT, см. DEVICE.

Поскольку файл предназначен для автономного распространения целых приложений / игр, его настройка и сборка слишком сложны для одной директивы, и вместо этого конфигурация разделена на несколько команд, а сборка проходит несколько этапов, поэтому некоторые команды должны использоваться в правильной последовательности.

Хотя формат технически позволяет включать данные нескольких типов экранов, все они загружаются вначале друг поверх друга, поэтому имеет смысл предоставить только один загрузочный экран (sjasmplus обеспечивает это).

Подробное описание каждой команды SAVENEX

SAVENEX OPEN <имя_файла>[,<начальный_адрес>[,<адрес_стека>[,<Входной_банк16k 0..111>[,<версия_файла 2..3>]]]]

Открывает файл NEX, определяет начальный адрес, адрес стека и банк данных 16k, которые должны быть сопоставлены с 0xC000 перед выполнением кода (если значения опущены, начальный адрес равен нулю = нет начала, адрес стека равен 0xFFFE, Входной_банк равен нулю, версия файла равна 2).

Одновременно может быть открыт только один файл NEX, и для завершения содержимого заголовка необходимо использовать команду CLOSE (автоматически закрывается, если исходный код заканчивается).

Банк ввода - это номер банка 16k (0..111), а не родной страницы 8k, значение по умолчанию равно нулю, т.е. карта памяти по умолчанию идентична ZX128 (ПЗУ, банки оперативной памяти 5, 2 и 0).

Убедитесь, что в вашем новом стеке доступны по крайней мере десятки байт, поскольку они уже будут использованы загрузчиком NEX перед выполнением вашей точки входа (хотя и выпущены обратно).

Версия файла может быть 2 (NEX V1.2) или 3 (NEX V1.3), что обеспечит соблюдение указанной версии файла. В противном случае файл по умолчанию имеет версию V1.2 и автоматически переключится на версию V1.3, когда будет настроена / использована какая-либо функция версии V1.3. При внедрении версии 2 любое использование функции версии V1.3 приведет к ошибке.

SAVENEX CORE <major 0..15>,<minor 0..15>,<subminor 0..255>

Установите минимально необходимую следующую версию ядра, может быть установлена в любое время до CLOSE.

SAVENEX CFG <border 0..7>[,<fileHandle 0/1/$4000+>[,<PreserveNextRegs 0/1>[,<2MbRamReq 0/1>]]]

Установите цвет границы (во время загрузки), следует ли переводить компьютер в состояние по умолчанию (PreserveNextRegs = 0 = по умолчанию), требуется ли приложению расширенная оперативная память (224 8k страниц) и как следует обращаться с дескриптором файла NEX: 0 = по умолчанию = закрыть, 1 = оставить открытым и передайте в BC, $4000..$FFFE = оставить открытым и записать в память по указанному адресу (после того, как банк ввода будет выгружен). Это может быть установлено в любое время до CLOSE.

SAVENEX CFG3 <DoCRC 0/1>[,<PreserveExpansionBus 0/1>[,<CLIbufferAdr>,<CLIbufferSize>]]

Все это функции формата NEX версии V1.3, и использование команды "CFG 3" автоматически изменит версию на V1.3 (если не указано в OPEN).

DoCRC: по умолчанию = 1, sjasmplus проверит контрольную сумму файла (если вы знаете, что после этого будете дополнительно исправлять файл, отключите его, в противном случае оставьте 1).

PreserveExpansionBus: default = 0, 0 = загрузчик NEX отключит шину расширения через NextReg $80/1 = загрузчик NEX ничего не сделает.

CLIbufferAdr, CLIbufferSize:default = [0, 0], адрес и размер буфера для NEX-загрузчика, в который копируется строка аргументов. Буфер копируется после сопоставления "entryBank", поэтому вы можете выделить буфер в своем entryBank. Загрузчик / формат имеет жесткое ограничение в 2048 байт, строка аргумента будет усечена, если она длиннее. Если ваш зарезервированный буфер короче 2048 байт, копия также будет урезана только до размера вашего буфера. Если строка аргумента не усечена, она может заканчиваться любым из этих символов: Enter (13), двоеточие или нулевой байт (усеченный не содержит символа-ограничителя, просто заполняет полный буфер).

SAVENEX BAR <loadBar 0/1>,<barColour 0..255>[,<startDelay 0..255>[,<bankDelay 0..255>[,<posY 0..255>]]]

Loading-bar связанный с загрузкой (использование "цвета" зависит от режима экрана), может быть настроена в любое время до CLOSE.

Аргумент post будет применяться только к экранам Layer2 версии V1.3 с разрешением 320x256 и 640x256 (тогда значение по умолчанию 254 = нижняя часть экрана, полоса высотой 2 пикселя).

SAVENEX PALETTE NONE

SAVENEX PALETTE DEFAULT

SAVENEX PALETTE MEM <palPage8kNum 0..223>,<palOffset>

SAVENEX PALETTE BMP <filename>

Это необязательная команда для установки палитры альтернативным способом перед командой SCREEN с более высоким приоритетом (если используется команда PALETTE, следующие команды SCREEN будут игнорировать аргументы палитры и сохранят палитру, определенную этой командой). Вы можете использовать его между командами OPEN и SCREEN.Но соответствующая палитра, поддерживающая тип SCREEN, также должна быть определена командой SCREEN.

Палитра состоит из 512 байт (256 элементов палитры с индексом 0) в цветовом формате 9b: первый байт - %RRRGGGBBB, второй байт - %P000000B (P - флаг приоритета для цветов слоя 2).

Палитра ПО УМОЛЧАНИЮ будет генерировать значения цвета из цветового индекса таким же образом, как палитра слоя 2 по умолчанию инициализируется в ZX Spectrum Next.

Палитра NONE принудительно установит флаг "нет палитры", даже если команда SCREEN позже укажет какую-либо палитру (она все равно будет проигнорирована).

SAVENEX SCREEN L2 [<Page8kNum 0..223>,<offset>[,<palPage8kNum 0..223>,<palOffset>]]

Загрузочный экран слоя 2, может использоваться между командами OPEN и первой AUTO/BANK.

Палитра состоит из 512 байт (256 элементов палитры с индексом 0) в цветовом формате 9b: первый байт - %RRRGGGBBB, второй байт - %P000000B (P - флаг приоритета для цветов слоя 2).

Данные изображения занимают 48 Кб блока памяти, загрузчик всегда будет использовать банки 9..11 для их отображения (8 кб страниц 18..23), но если вы подготовите данные там, они также будут повторно сохранены с помощью команды AUTO, поэтому либо используйте другие банки и перезапишите их действительными данными / кодом после использования команды SCREEN, либо сбросьте страницы 18..23 до нуля после SCREEN.

Если адрес памяти не указан, страницы 18..23 сохраняются в файле, а если адрес палитры не указан, в файле NEX устанавливается флаг отсутствия палитры.

SAVENEX SCREEN L2_320 [<Page8kNum 0..223>,<offset>[,<palPage8kNum 0..223>,<palOffset>]]

SAVENEX SCREEN L2_640 [<Page8kNum 0..223>,<offset>[,<palPage8kNum 0..223>,<palOffset>]]

Работает так же, как вариант "L2", но настраивает экран на новые разрешения 320x256x8 и 640x256x4. Разница в том, что требуемые данные изображения составляют 80 КБ (пять банков по 16 Кб; равно десяти страницам по 8 Кб), банки, используемые для отображения экрана в загрузчике, составляют 9.. 13 (8 кб страниц 18..27 - это также адрес данных по умолчанию, если не указан) - избегайте их в обычных банках сохраненный в файле.

Это функции NEX format V1.3, и их использование автоматически изменит версию на V1.3 (если не указано в OPEN). Эта команда не позволяет задать конкретное значение смещения палитры (слишком ленив, чтобы добавлять его, используйте вариант BMP, если вам это действительно нужно).

Данные уже должны быть в правильном формате и организованы так, как если бы они отображались ("транспонированное" растровое изображение, где +1 адрес переходит в пиксель ниже, а +256 - в пиксель справа (или пару пикселей в случае режима 640x256x4bpp), эта команда просто сбросит их в файл "как есть".

Байт цвета загрузочной панели также будет использоваться "как есть", что в режиме 4bpp означает, что байт действительно определяет пару 4-битных пикселей, т.е. если вы хотите однотонную загрузочную панель "3" в режиме 4bpp, определите ее как значение $33. Имейте также в виду, что положение панели загрузки по умолчанию равно Y = 254, что на большинстве TV / LCD дисплеев находится за пределами видимого диапазона, разумно "безопасное" (видимое почти на всех экранах) разрешение составляет около 288x224 (+16 пикселей вокруг области PAPER, + 24 пикселей видно на многих экранах дисплеи тоже), вы можете организовать свой экран таким образом, чтобы отображать всю важную информацию в этой области, а остальную сделать "неважной", чтобы она могла скрываться за краем экрана.

SAVENEX SCREEN LR [<Page8kNum 0..223>,<offset>[,<palPage8kNum 0..223>,<palOffset>]]

Загрузочный экран LoRes (128x96), может использоваться между командами OPEN и первой AUTO/BANK.

Палитра похожа на режим Layer 2, только в режиме LoRes бит приоритета отсутствует.

Данные изображения представляют собой блок памяти объемом 12288 байт - либо последовательный блок, если указан конкретный адрес, либо без адреса хранится фактическая память банка 5 (берется 6144 байта с адреса 0x4000 и 6144 байта с адреса 0x6000).

SAVENEX SCREEN BMP <filename>[,<savePalette 0/1>[,<paletteOffset 0..15>]]

Можно использовать только небольшое подмножество BMP-файлов: 256x192 (Слой 2) или 128x96 (LoRes), проиндексированных (8-битные данные изображения с палитрой), и данные палитры будут усечены непосредственно до цветового пространства 3:3:3 (интеллектуальное квантование цвета или сглаживание не применяются). И файл должен быть несжат.

Для файлов NEX версии V1.3 вы можете включить также файлы 320x256 и 640x256 (Слой 2), 640x256 также должны быть проиндексированы на 8 бит, но будут использоваться только 4 бита пиксельных данных (допустима 256-цветовая палитра, которая будет сохранена "как есть" в файле NEX). Эти два новых режима также могут включать параметр смещения палитры 0..15 (не применяется к BMP-файлам версии V1.2 выше), смещение добавляется к четырем верхним битам значения пикселя.

BMP будет включен в качестве загрузочного экрана, может использоваться между командами OPEN ипервой AUTO/BANK.

По умолчанию используется палитра из BMP-файла, но вы можете переопределить это, установив savePalette = 0.

SAVENEX SCREEN (SCR|SHC|SHR) [<hiResColour 0..7>]

Экран загрузки режимов ULA / Timex, может использоваться между командами OPEN и первой AUTO/BANK.

Фактический объем памяти банка 5 (страницы 10..11) сохраняется так, как если бы отображалось изображение, в этих режимах палитру указать невозможно.

SCR - это классический экран ZX длиной 6912 байт с адреса 0x4000 (используется страница 10, даже если слот 1 изменен на другую страницу, поэтому вы должны подготовить изображение "на месте").

SHS и SHR - это режимы Timex HiColor (атрибут 8x1) и HiRes (растровое изображение 512x192), подготавливающие данные "на месте", т.е. 6144 байта на страницу 10 и 6144 байта на страницу 11 (адреса 0x4000 и 0x6000 в настройках памяти по умолчанию). Для режима HiRes вы должны указать цвет чернил (бумага должна быть заполнена чернилами).

SAVENEX SCREEN TILE <NextReg $6B>,<NextReg $6C>,<NextReg $6E>,<NextReg $6F>[,<AlsoStoreBank5 0/1 = 1>]

Экран загрузки tilemap NEX V1.3, может использоваться между командами OPEN ипервой AUTO/BANK.

Чтобы определить палитру, используйте команду PALETTE.

Данные изображения хранятся в виде обычного банка 5 файла NEX (который является первым банком, загружаемым загрузчиком), в зависимости от значения AlsoStoreBank5 (по умолчанию 1), эта экранная команда также будет выполняться комадой BANK 5 для хранения данных изображения.

Регисторв NextRegisters $6B, $6C, $6E и $6F должно быть достаточно, чтобы указать любой вариант режима tilemap, поэтому точный подтип и расположение данных изображения находятся под контролем пользователя, sjasmplus не применяет какую-либо конкретную конфигурацию.

Если вы хотите использовать также команду COPPER, используйте его либо перед командой SCREEN TITLE, либо используйте "AlsoStoreBank5 = 0", чтобы отложить сохранение данных банка 5. В таком случае вы должны позже явно сохранить Bank 5 как обычный банк, либо с помощью команды BANK, либо AUTO.

SAVENEX COPPER <Page8kNum 0..223>,<offset>

Может быть использован после OPENи перед первой командой AUTO или BANK (данные о меди сохраняются между экраном и банковскими данными).

Хранится ровно 2048 байт (полная память Copper), и загрузчик запустит код copper в режиме %01 (сбросит CPC на 0, затем запустит copper), так что код copper будет бесконечно повторяться после выполнения 1024-й инструкции. Процесс запускается после загрузки и отображения экранного блока.

SAVENEX BANK <bank16k 0..111>[,...]

Может быть использован после команды OPEN or SCREEN и перед CLOSE, но банки 16k i должны быть сохранены в правильном порядке: 5, 2, 0, 1, 3, 4, 6, 7, 8, 9, 10, ..., 111

SAVENEX AUTO [<fromBank16k 0..111>[,<toBank16k 0..111>]]

Может быть использован после команды OPEN or SCREEN и перед CLOSE. sjasmplus сохранит каждый 16-килобайтный банк, содержащий по крайней мере один ненулевой байт; обнаруженный в правильном порядке (автоматически сохранит каждый ненулевой 16-килобайтный банк, обнаруженный в правильном порядке (автоматически начиная с первого возможного банка после предыдущих команд BANK /AUTO или из предоставленного "from Bank").

Для значения "_from Bank" используйте указанный выше порядок в команде BANK , т.е. 5, 2, 0, ...

SAVENEX CLOSE [<fileToAppend>]

Может быть использован после команды OPEN. Открытый в данный момент файл NEX будет доработан (заголовок скорректирован), а необязательный дополнительный файл просто добавлен в конец файла NEX.

Примеры

Пример В 8.1.В docs_examples/s_savenex_examples.asm

Создаем файл NEX, который будет иметь экран загрузки Layer2 (полосы), индикатор выполнения и войдет в бесконечный цикл со стеком вызовов (используемым обработчиком прерываний IM 1), видимым на экране Layer 2.

    DEVICE ZXSPECTRUMNEXT
    ORG $7E00
start:  ei : jr $           ; точка входа в код приложения, BC = дескриптор файла NEX
    ; Экран Layer2 (верхняя часть определена на 1/3, нижняя часть также будет использоваться в качестве "видимого" стека)
    ORG $C000 : DUP 64*32 : DB $90,$91,$92,$93,$94,$95,$96,$97 : EDUP

    ; записываем все в файл NEX
    SAVENEX OPEN "example.nex", start, $FFFE, 9  ; стек перейдет в Layer2
    SAVENEX CORE 2, 0, 0        ; Требуется как минимум следующее ядро 2.0.0
    SAVENEX CFG 4, 1, 0, 1      ; зеленая граница, дескриптор файла в BC, сброс NextRegs, требуется 2 МБ
    SAVENEX BAR 1, $E0, 50, 25  ; панель загрузки do, красный цвет, задержка запуска/загрузки 50/25 кадров
    SAVENEX SCREEN L2 0, 0      ; сохраняет данные из C000 (страница 0, смещение 0), палитры нет
    SAVENEX BANK 5, 100, 101    ; сохраняет 16 банков данных 5 (содержит код 0x7E00), 100, 101
    SAVENEX CLOSE               ; (банки 100 и 101 добавлены просто в качестве примера)
		  

Глава В 9.В Данные отладки на уровне источника (SLD)

Что это?

Данные SLD - это дополнительные данные "трассировки", создаваемые во время сборки для отладчиков и IDE, аналогичные файлам "map", уже поддерживаемым sjasmplus ( LABELSLIST и CSPECTMAP).

Отладчик может считывать эти данные, и с помощью несложного исходного кода, создающего машинный код с правильным отображением памяти устройства, отладчик может проследить происхождение каждой инструкции обратно к исходной строке исходного кода и отобразить исходный код вместо этого / в режиме дизассемблирования (файлы "карты", упомянутые выше, предоставляют только список из меток, что обычно уже очень полезно, но не позволяет отследить исходные коды каждой инструкции).

Оригинальный импульс и рабочий патч для этой функции был разработан Крисом Кирби, который добавил функцию "пошаговая инструкция" в свои инструменты разработки: Next Development System (в настоящее время в 2019 году ведется интенсивная разработка).

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

На стороне sjasmplus все, что вам нужно, это добавить еще один параметр командной строки при запуске ассемблера.

prompt$ sjasmplus --sld=project.sld.txt file1.asm file2.asm

Это приведет к созданию наряду с обычными файлами также файла `project.sld.txt ` содержащий данные отслеживания. Формат файла текстовый, поэтому содержимое можно просмотреть в любом текстовом редакторе, но предполагается, что оно обрабатывается отладчиком.

Данные SLD экспортируются только для машинного кода, созданного на одном из виртуальных устройств (смотри DEVICE). А точность данных напрямую зависит от состояния виртуального устройства на момент сборки конкретной инструкции. Дополнительные рекомендации по получению наилучших данных отслеживания см. в следующем разделе.

Если используется опция `--sold` без явного имени файла, будет скопировано первое имя файла входного источника и изменено его расширение на `.sld.txt `, который должен хорошо работать для проектов с одним основным файлом.

Как написать "не хитрый" исходный код

Для достижения наилучших результатов (отслеживание данных, охватывающих все ваши инструкции, и постоянная доступность отладки на уровне исходного кода):

Генерируйте машинный код только с инструкциями, т.е. в то время как `db 0` в исходном коде выдаст команду `nop`, данные отслеживания для такого `nop` будут отсутствовать. Единственная исходная строка, содержащая "nop", будет передавать как нулевой байт в машинный код, так и данные отслеживания.

Сохраните карту памяти виртуального устройства в том виде, в каком она будет установлена во время выполнения при написании определенного кода. При использовании только обычного ORG для размещения кода в желаемой области памяти достаточно сохранить только измененную область с отображенными страницами памяти, чтобы получить правильные данные SLD - но при использовании директивы DISP для генерации кода смещенным способом вам необходимо отобразить правильные страницы в обеих областях памяти (где код в данный момент собран и где он должен быть работоспособен во время выполнения - в настоящее время невозможно, если две области совместно используют одну и ту же область SLOT).

Для отображения на правильных страницах вы можете использовать директивы: SLOT, PAGE, MMU и ORG

Только метки, определенные обычным способом, получают также данные страницы памяти в файле SLD, значения EQU экспортируются без информации о странице, даже если они представляют адрес памяти:

regularLabel:   nop             ; текущая страница, экспортированная в SLD data
equLabel        EQU   $8000     ; экспортируется только значение без страницы
varSymbol       =     14        ; =/DEFL метки полностью опущены

Повторное использование одной и той же области памяти (страница + адрес) для двух разных фрагментов кода (например, при использовании нескольких подпрограмм, нацеленных на один и тот же адрес с помощью DISP, и кода во время выполнения, динамически загружающего правильный вариант в пункт назначения), скорее всего, приведет к путанице в отладчике, создавая два исходных данных для идентичный адрес. Возможно, вы захотите избежать этого, особенно учитывая, что ранняя версия инструментов не способна разумно разрешить такую двусмысленность (sjasmplus даже в этом случае нормально сгенерирует данные трассировки, но их сложно интерпретировать).

Если вы используете двоеточия для размещения нескольких инструкций в одной строке, убедитесь, что отладчик может справиться с данными отслеживания, содержащими полную информацию о начале / конце строки + столбца, простые / ранние инструменты, скорее всего, выделят только целую строку исходного кода. Для начала, сохранение одной инструкции в строке может упростить задачу.

Различные генераторы кода, написанные в макросах или скриптах Lua, будут выдавать точные данные трассировки в случае макросов и сжатые (указывающие на строку "END LUA") данные для генераторов Lua, но все еще зависит от отладчика, может ли он отображать как исходный код верхнего уровня, запускающий генератор, так и исходные строки, содержащие определения конкретных инструкций.

Определение формата файла SLD (версия "1")

Формат файла все еще находится в стадии разработки. Если вы работаете над поддержкой в debugger, оставайтесь с нами на связи, чтобы мы могли обсудить с вами любые изменения текущего формата.

Данные SLD представляют собой текстовый файл (sjasmplus использует UNIX-подобные новые строки 0x0A, но синтаксические анализаторы скорее должны справляться с любой из распространенных схем EOL). Общий формат - CSV-подобный, использующий символ канала в качестве разделителя между полями.

Если первое поле пусто, то строка является одной из специальных управляющих строк - во втором поле выбирается тип управляющей строки. Если также второе поле пусто, оставшуюся часть строки следует игнорировать (строка комментария). В настоящее время существует только один тип "управляющей строки" - "SLD.data.version" (третье поле - целое число):

|SLD.data.version|1
||что-нибудь... строка, похожая на комментарий

Строка версии формата файла всегда должна быть первой строкой файла данных SLD.

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

<source file>|<src line>|<definition file>|<def line>|<page>|<value>|<type>|<data>

<source file> - имя файла источника верхнего уровня, передающего инструкцию/метку/устройство.

<src line> - строка и символы в исходном файле верхнего уровня, точный формат "<line>[:<column begin>[:<column end>]]" где первое число - это номер строки (начинающийся с 1). Два следующих числа, разделенных двоеточием, являются необязательными и представляют столбец, в котором сегмент начинается/заканчивается в строке. Значения столбцов начинаются от 1 до столбца "end" указывает за пределы текущего сегмента. Столбцы указаны в "байтах", т.е. табулятор увеличивает значение столбца только на +1, и "конец" на самом деле может указывать далеко за пределы "strlen(line)".

<definition file> - имя файла источника, определяющего конкретную инструкцию (например, там, где изначально была определена инструкция внутри макроса). Если пусто, то имя файла определения идентично <source file> (обычный случай для проектов с одним исходным кодом).

<def line> - ноль, когда нет никакого дополнительного "определения" инструкции. Если значение не равно нулю, формат идентичен <src line>, но что касается файла, указанного в поле <definition file>.

<page> - номер страницы памяти, на которую указывает адрес <value>, или -1, если значение не является адресом памяти.

<value> - любое 32-разрядное целое значение (EQU), но при представлении адреса памяти это полное 16-разрядное значение из адресного пространства Z80 (верхние биты за пределами размера страницы памяти содержат номер "слота", в котором находится инструкция / метка).

<type> - одна заглавная буква, обозначающая тип строки, текущие типы: T (трассировка инструкций), L (метка), F [устаревший, посылка], D [устаревший, синтаксический анализ L], Z (модель памяти устройства), K (комментарий к ключевому слову, см. `КОММЕНТАРИЙ SLDOPT`).

<data> - дополнительные данные, специфичные для конкретного типа строки. Пусто для строк "T". Для "L" - список элементов, разделенных запятой, где первые три элемента представляют подразделы имени символа: название модуля, основная метка, локальная метка (подраздел может быть пустым), необязательные остальные элементы являются признаками использования, предоставляющими различную внутреннюю информацию об использовании символа (в настоящее время экспортируемые признаки: +equ, +macro, +reloc, +reloc_high, +used, +module, +endmod, +struct_def, +struct_data). Для типа "K" присутствует комментарий, содержащий одно из определенных ключевых слов.

Для типа "Z" поле данных содержит строку, описывающую модель памяти устройства, которая выбирается в источнике и должна применяться для следующих строк данных SLD. Формат строки модели памяти является:

pages.size:<page size>,pages.count:<page count>,slots.count:<slots count>[,slots.adr:<slot0 adr>,...,<slotLast adr>]
// unsigned <page size> также доступен любой размер слота в текущей версии.
// unsigned <page count> и <slots count> определяет, сколько существует страниц/слотов
// uint16_t <slotX adr> является начальным адресом области памяти слота в адресации Z80 16b

Пример В 9.1.В Пример SLD файла

|SLD.data.version|1
|| ZX Spectrum Next device description:
toplevel.asm|59||0|-1|-1|Z|pages.size:8192,pages.count:224,slots.count:8,slots.adr:0,8192,16384,24576,32768,40960,49152,57344
|| метка "main" указывает на 32768, с отображением страницы 14 (определено в toplevel.asm:62)
|| метка "main" используется другим кодом (IF USED - подобный) и содержит данные о перемещении
toplevel.asm|62||0|14|32768|L|,main,,+reloc,+used
|| код операции инструкции в 32768 (страница 14) был создан toplevel.asm:64
toplevel.asm|64||0|14|32768|T|
|| код операции инструкции в 32769 (стр. 14) был создан toplevel.asm:67
|| (но это строка, использующая макрос, инструкция была определена toplevel.asm:52)
toplevel.asm|67||52|14|32769|T|
|| код операции инструкции в 32770 (стр. 18) был создан toplevel.asm:68:12-24
toplevel.asm|68:12:24||0|18|32770|T|
|| код операции инструкции в 32771 (стр. 18) был создан toplevel.asm:68:24 (до EOL)
toplevel.asm|68:24||0|18|32771|T|
|| "PORT_NUMBER = 254" определен на верхнем уровне.asm:69
toplevel.asm|69||0|-1|254|L|,PORT_NUMBER,,+equ
|| метка+инструкция, исходящая из toplevel.asm:70, но определенная в include.asm:3
|| с меткой макроса "0>macro_defined_in_include_asm" (исходник ".macro_defined_in_include_asm:")
toplevel.asm|70|include.asm|3|37|40976|L|,0,macro_defined_in_include_asm,+macro,+used
toplevel.asm|70|include.asm|3|37|40976|T|

Индекс

Символы

!, Выражения
!=, Выражения
$, Выражения
$$, Выражения
$$$, Выражения
$$$$, Выражения
$$label, Выражения
%, Выражения
&, Выражения
&&, Выражения
*, Выражения
+, Выражения
-, Выражения
.<repeat-count>, Псевдо-операции
/, Выражения
<, Выражения
<<, Выражения
<=, Выражения
<?, Выражения
=, Выражения
==, Выражения
>, Выражения
>=, Выражения
>>, Выражения
>>>, Выражения
>?, Выражения
^, Выражения
_c(..), Привязки функций SjASMPlus к Lua
_pc(..), Привязки функций SjASMPlus к Lua
_pl(..), Привязки функций SjASMPlus к Lua
__BASE_FILE__, Предопределенные определения
__COUNTER__, Предопределенные определения
__DATE__, Предопределенные определения
__ERRORS__, Предопределенные определения
__FILE__, Предопределенные определения
__INCLUDE_LEVEL__, Предопределенные определения
__LINE__, Предопределенные определения
__PASS__, Предопределенные определения
__SJASMPLUS__, Предопределенные определения
__TIME__, Предопределенные определения
__VERSION__, Предопределенные определения
__WARNINGS__, Предопределенные определения
{..}, Выражения
{b ..}, Выражения
|, Выражения
||, Выражения
~, Выражения

D

D24, Псевдо-операции, STRUCT instructions
DB (смотри BYTE)
DC, Псевдо-операции
DD (смотри DWORD)
DEFARRAY, Псевдо-операции
DEFARRAY+, Псевдо-операции
DEFB (смотри BYTE)
DEFD (смотри DWORD)
DEFDEVICE, Псевдо-операции
(смотри также DEVICE)
DEFG (смотри DG)
DEFH (смотри DH)
DEFINE, Псевдо-операции
DEFINE+, Псевдо-операции
DEFL, Псевдо-операции
(смотри также EQU)
DEFM (смотри BYTE)
DEFS (смотри BLOCK)
DEFW (смотри WORD)
DEPHASE (смотри ENT)
(смотри также DISP)
DEVICE, Псевдо-операции
(смотри также DEFDEVICE)
(смотри также MMU)
(смотри также ZXSPECTRUM128)
(смотри также ZXSPECTRUMNEXT)
DG, Псевдо-операции
DH, Псевдо-операции
DISP, Псевдо-операции
(смотри также ENT)
DISPLAY, Псевдо-операции
DM (смотри BYTE)
DS (смотри BLOCK)
DUP, Псевдо-операции
DW (смотри WORD)
DWORD, Псевдо-операции, Инструкции STRUCT
DZ, Псевдо-операции

E

ELSE, Условная компиляция
(смотри также IF)
ELSEIF, Условная компиляция
(смотри также IF)
EMPTYTAP, Псевдо-операции
EMPTYTRD, Псевдо-операции
ENCODING, Псевдо-операции
END, Псевдо-операции
ENDIF, Условная компиляция
ENDLUA, Псевдо-операции
(смотри также LUA)
ENDMOD (смотри ENDMODULE)
ENDMODULE, Псевдо-операции
(смотри также MODULE)
ENDT (смотри ENT)
ENT, Псевдо-операции
(смотри также DISP)
EQU, Псевдо-операции
(смотри также DEFL)
exist, Выражения
EXPORT, Псевдо-операции

H

HEX, Псевдо-операции
(смотри также DH)
high, Выражения

M

MMU, Псевдо-операции
(смотри также DEVICE)
(смотри также PAGE)
(смотри также SLOT)
mod, Выражения
MODULE, Псевдо-операции

O

OPT, Псевдо-операции
or, Выражения
ORG, Псевдо-операции
(смотри также DEVICE)
OUTEND, Псевдо-операции
(смотри также OUTPUT)
(смотри также SIZE)
OUTPUT, Псевдо-операции
(смотри также SIZE)

P

PAGE, Псевдо-операции
(смотри также DEVICE)
(смотри также MMU)
(смотри также SLOT)
PHASE (смотри DISP)

R

RELOCATE_END, Псевдо-операции
RELOCATE_START, Псевдо-операции
RELOCATE_TABLE, Псевдо-операции
REPT (смотри DUP)

S

SAVE3DOS, Псевдо-операции
SAVEAMSDOS, Псевдо-операции
SAVEBIN, Псевдо-операции
SAVECDT, Псевдо-операции
SAVECPCSNA, Псевдо-операции
SAVEDEV, Псевдо-операции
SAVEHOB, Псевдо-операции
SAVENEX, Псевдо-операции
SAVESNA, Псевдо-операции
SAVETAP, Псевдо-операции
SAVETRD, Псевдо-операции
SETBP, Псевдо-операции
(смотри также BPLIST)
SETBREAKPOINT (смотри SETBP)
SHELLEXEC, Псевдо-операции
shl, Выражения
shr, Выражения
SIZE, Псевдо-операции
(смотри также OUTPUT)
sj.add_byte(..), Привязки функций SjASMPlus к Lua
sj.add_word(..), Привязки функций SjASMPlus к Lua
sj.calc(..) (смотри _c(..))
sj.current_address, Привязки функций SjASMPlus к Lua
sj.error(..), Привязки функций SjASMPlus к Lua
sj.error_count, Привязки функций SjASMPlus к Lua
sj.exit(..), Привязки функций SjASMPlus к Lua
sj.file_exists(..), Привязки функций SjASMPlus к Lua
sj.get_byte(..), Привязки функций SjASMPlus к Lua
sj.get_define(..), Привязки функций SjASMPlus к Lua
sj.get_device(), Привязки функций SjASMPlus к Lua
sj.get_label(..), Привязки функций SjASMPlus к Lua
sj.get_word(..), Привязки функций SjASMPlus к Lua
sj.insert_define(..), Привязки функций SjASMPlus к Lua
sj.insert_label(..), Привязки функций SjASMPlus к Lua
sj.parse_code(..) (смотри _pc(..))
sj.parse_line(..) (смотри _pl(..))
sj.set_device(..), Привязки функций SjASMPlus к Lua
sj.set_page(..), Привязки функций SjASMPlus к Lua
sj.set_slot(..), Привязки функций SjASMPlus к Lua
sj.shellexec(..), Привязки функций SjASMPlus к Lua
sj.warning(..), Привязки функций SjASMPlus к Lua
sj.warning_count, Привязки функций SjASMPlus к Lua
SLDOPT, Псевдо-операции
SLOT, Псевдо-операции
(смотри также DEVICE)
(смотри также MMU)
(смотри также PAGE)

T

TAPEND, Псевдо-операции
(смотри также TAPOUT)
TAPOUT, Псевдо-операции
TEXT, STRUCT instructions
TEXTAREA (смотри DISP)

U

UNDEFINE, Псевдо-операции
(смотри также DEFINE)
UNPHASE (смотри ENT)