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
- добавлен необязательный второй аргумент для `DUP` имеющую индексную переменную - опция `--exp` создаст файл, даже если `EXPORT` не используется - исправлен конфликт имен переменных при компиляции с musl-libc - Обновлен LuaBridge, немного обновлены CMake и Makefile - незначительные исправления / улучшения в синтаксическом анализаторе в конкретных крайних случаях
- разбор десятичных числовых констант с предупреждением (для упрощения работы с Lua 5.4) - добавлено `SAVEAMSDOS` (как, например, SAVEBIN с заголовком AMSDOS) - добавлен "умный" синтаксис SMC offset для меток с самоизменяющимся кодом: `abc+*: или 123` - добавлен `DEFDEVICE` для определения пользовательских устройств - Очистка Makefile
- 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>`
- добавлены устройства 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)
- добавлен режим `--color` чтобы включить/отключить ANSI-раскраску ошибок/предупреждений - добавлен режим `--syntax=s` для отключения подстановки вложенных слов в DEFINEs - добавлен префикс at-sign macro local labels для локальных меток макросов, чтобы действовать как локальная метка, не относящаяся к макросу - `SAVETRD` принимает имена, содержащие точку ("z.x.B" - это "z.x" с расширением "B") - автор Dart Alver - `SAVETRD` имеет необязательный аргумент для сохранения BASIC с переменными (length_minus_variables) - незначительные исправления ошибок (анализатор условных блоков)
- [может нарушить работу старых исходников] новый оператор exist exist operator для проверки существования метки - режим --syntax=i теперь также делает синтаксический анализ регистра нечувствительным к регистру - незначительные исправления ошибок (предопределенные значения, загрузчик savenext BMP менее строг в отношении содержимого "colors used")
- Поддержка хостов 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
- [может нарушать работу старых исходников] двоеточие между концом 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
- `STRUCT` имеет новые `TEXT` псевдо-инструкция для определения "DB-подобных" данных (Issue #93) - блок инициализатора `STRUCT` теперь может быть многострочным (при правильном заключении в фигурные скобки) - `EQU` теперь допускает необязательное переопределение номера страницы, присвоенного новому символу - новые $$$ и $$$$ операторы позволяют получить "физический" адрес/страницу внутри блока DISP - команда `out (c),0` теперь выдает предупреждение (может быть подавлена комментарием "; ok") - исправлено перечисление структур с использованием длинных блочных (BLOCK) полей (машинный код был правильным, но перечисление нет) - исправлены некоторые утечки памяти, неопределенное поведение и несогласованный доступ к памяти
- `LUA` новое предупреждение об эмиссии (версия v1.15.1) теперь можно отключить - Предопределенные определения расширены и переименованы (в соответствии с gcc / clang) - добавлен генератор перемещаемых данных (аналогично функции WinAPE), проверьте также пример - исправления / улучшения в синтаксическом анализаторе, такие как: за операторами "not", "low", "high" также может следовать "("
Смотри CHANGELOG.md с полным списком изменений
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
Метки чувствительны к регистру и могут быть любой разумной длины, то есть примерно до 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 ; *новое* работает также в выражениях
Числовые константы всегда должны начинаться с цифры или $, # или %.Поддерживаются следующие форматы:
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
Предопределенные устройства:
Отключение режима эмуляции реального устройства. По умолчанию.
Имеет 4 слота (0-3) размером 4000h, 4 страницы (0-3) размером 4000h. Слот 3 (он начинается с 0C000h) по умолчанию включен в текущий режим.
Имеет 8 страниц оперативной памяти (0-7) размером 4000h. Слот по умолчанию равен 3.
То же, что и русский клон Scorpion 256. Имеет 16 страниц оперативной памяти (0-15) размером 4000h.
То же, что и российские клоны ATM Turbo 512 и Pentagon 512. Имеет 32 страницы оперативной памяти (0-31) размером 4000h.
То же, что и российские клоны ATM Turbo 2 и Pentagon 1024 SL. Имеет 64 страницы оперативной памяти (0-63) размером 4000h.
Подобно другим устройствам spectrum, имеет 128 страниц оперативной памяти (0-127) размером 4000 h.
Подобно другим устройствам spectrum, имеет 256 страниц оперативной памяти (0-255) размером 4000h.
Подобно другим устройствам spectrum, имеет 512 страниц оперативной памяти (0-511) размером 4000 h.
ZX Spectrum Next имеет 8 слотов (0-7) размером 0x2000 и 224 страницы оперативной памяти (0-223) общим объемом 1,75 Мбайт.Распределение памяти по умолчанию аналогично ZX128, подкачка в: {14, 15, 10, 11, 4, 5, 0, 1} страницы. Слот по умолчанию равен 7 (диапазон памяти 0xE000..0xFFFF). Вся память обнуляется во время инициализации.
Имеет только один слот размером 64 Кб (слот 0), охватывающий весь диапазон адресации процессора Z80. Доступно 32 страницы памяти, по умолчанию отображается страница 0. Таким образом, в общей сложности доступно 2 Мбайт памяти (32 * 64 кб = 2 МБайт).
Имеет 4 слота (0-3) размером 0x4000 и 4 страницы (0-3) размером 0x4000, общим объемом 64 КБ. Эти страницы отображаются линейно в виде { 0, 1, 2, 3 }.
Имеет 4 слота (0-3) размером 0x4000 и 8 RAMpages (0-7) размером 0x4000 (всего 128 Кб). Сопоставление страниц по умолчанию является { 0, 1, 2, 3 }.
Если вы хотите посмотреть другие устройства, вы должны написать нам. Смотрите главу Обратная связь.
SjASMPlus имеет предопределенные определения.
Номер текущей версии программы разделен на три 8-битных значения, т.е. 0x010F02 для "1.15.2".
Строковое значение (с кавычками вокруг него) текущей версии программы, например "1.15.2"
.
Количество ошибок.
Количество предупреждений.
Дата компиляции (временная метка перед первым проходом).
Время компиляции (отметка времени перед первым проходом, форма 24 часа).
Текущий проход компилятора (1, 2 или 3).
Текущий уровень вложенности include.
Имя базового файла (включает нулевой уровень).
Это необработанное значение без кавычек, практически непригодное для использования в asm-источнике, но LUA предоставляет средства для работы с таким строковым значением.
Имя текущего файла
Это необработанное значение без кавычек, практически непригодное для использования в asm-источнике, но LUA предоставляет средства для работы с таким строковым значением.
Текущий номер строки.
Увеличивается при каждом использовании (начиная со значения 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
Предопределенные значения были переименованы и расширены, чтобы больше походить на предопределенные значения gcc / clang, следующие значения являются устаревшими оригиналами.
Устарел, рассмотрите возможность использования аналогичного __SJASMPLUS__
Устарел, переименован в __VERSION__
Устарел, рассмотрите возможность использования аналогичного __SJASMPLUS__
Пример В 4.6.В
IF _RELEASE = 1 ; 0 - является стабильной версией ;код для Release Candidate 1 ELSE ;код для остальных версий ENDIF
Количество ошибок. Устарел, переименован в __ERRORS__
Количество предупреждений. Устарел, переименован в __WARNINGS__
.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
Определяет байт или строку байтов. Смещение прибавляется к каждому из следующих байтов.
Пример В 5.2.В
ABYTE 2 4,9 ; компилируется как BYTE 6,11 ABYTE 3 "ABC" ; компилируется как BYTE "DEF"
Определяет байт или строку байтов, где в последнем байте строки будет установлен бит 7. Смещение добавляется к каждому из следующих байтов.
Пример В 5.3.В
ABYTEC 0 "KIP" ; компилируется как "KI",'P'|128 ABYTEC 1 "ABC",0,"DE" ; компилируется как BYTE "BC",'D'|128,1,'E','F'|128
Определяет байт или строку байтов, за которой следует ноль. Смещение добавляется к каждому из следующих байтов.
Выравнивание продвигается к ближайшему адресу, где остаток от деления <новый адрес>на <выражение> (по умолчанию 4) равно 0 (по возможности остается на текущем адресе).
Если указан <байт>, то им заполняется свободное место в памяти.
Пример В 5.5.В
ALIGN ; => ALIGN 4 - просто выровняйте на 4 ALIGN 2 ; выравнивает на 2 (сохраняет значение в памяти "устройства") ALIGN 2,0 ; + заполняет память нулем
Ошибка 'assertion failed' ("утверждение не выполнено") выдается, если выражение равно нулю. Параметр "Что угодно" (необязательный аргумент начиная с версии v1.18.1) также отображается в сообщении об ошибке, поэтому вы можете добавить туда описание / примечания о выражении.
Пример B 5.6.В
STACKPOINTER=0D500H ASSERT END_OF_PROGRAM < УКАЗАТЕЛЬ СТЕКА, программный код просачивается в область стека END_OF_PROGRAM
Синоним INCBIN.
Задает область памяти. За оператором необхидимо указать число байт для резервирования, необязательный параметр - заполняющий байт.
Пример В 5.7.В
BLOCK 500 ; определяет блок из 500 нулевых байт BLOCK 500,0 ; определяет блок из 500 нулевых байт BLOCK 400,-1 ; определяет блок из 500 байт заполненый числами 255
Работает только в режиме эмуляции реального устройства. Смотри 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"
Определяет байт или строку байтов. Каждое значение должно быть в диапазоне от -129 до 256.
Полезно для эмулятора 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" к имени источника.
Определяет три байта 24-х битной константы. Значения должны находиться в диапазоне от -16777217 до 16777216.
Синоним директивы BYTE.
Такой же, как BYTE, но для каждого последнего символа строки будет установлен бит 7.
Синоним DWORD.
Массив значений.
Используйте имя_массива[#]
для получения текущего размера массива.
Пример В 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
Добавление дополнительных значений из списка к уже определенному массиву
Пример В 5.13.В
DEFARRAY myarray 'A', 'B', 'C' DEFARRAY+ myarray 'D', 'E' ; теперь массив "myarray" содержит 5 значений DUP 3 : DEFARRAY+ myarray '!' : EDUP ; в массив "myarray" добавлено 3x '!'
Сноним для BYTE.
Синоним для DWORD.
(начиная с версии v1.20.1) Добавление определенного пользователем устройства. Адресное пространство 64 кБ Z80 равномерно разделено на N размер_слота
слотов, а общая память устройства равна размер_слота * число_страниц
байтов.
Начальные страницы неявно переходят от 0
до число_страниц-1
(повторяя страницу число_страниц-1
для оставшихся слотов, когда страниц недостаточно), но вы можете указать начальный макет страницы явно.
Используйте DEVICE для выбора нового определенного устройства.
Синоним DG.
Синоним DH.
<идентификатор> будет заменен на <замена>.
Директива 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
Присваивает значение <выражение> символу <метрка>. Новая метка, определенная 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
Аналогичен BYTE.
Аналогичен BLOCK.
Аналогичен WORD.
Аналогичен ENT.
Включает режим эмуляции реального устройства по его идентификатору. Если во всем исходном пакете есть только одна директива 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
Данные состоят из набора символов, кратных 8 каждый блок из 8 символов преобразуется в байт.
Дефис '-' (также '.' и '_') преобразуется в 0, а любой другой символ, не содержащий пробелов, преобразуется в 1. Пробелы игнорируются, используйте их для форматирования, если хотите. Внимание, "DG 10100001" имеет значение 255, потому что символ "0" не является тире "-". (начиная с версии v1.11)
Пример В 5.16.В
DG 1-1----1 ; преобразуется в 161 в текущей локации DG ...# #... .##. .... ;преобразуется в 2 байта: 0x18, 0x60
Преобразует строку из четного количество шестнадцатеричных цифр в множество байт. Вы можете добавлять пробелы между парами по своему усмотрению. (начиная с версии v1.11)
Пример В 5.17.В
DH "0123456789ABCDEF" ; преобразуется в 8 байт: #01 #23 ... DH "01 23 45 67" ; преобразуется в 4 байта: #01 #23 #45 #67
Установливает адрес, по которому должна работать часть кода. 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)
Эта псевдо-операция аналогична операции ассемблера 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 */
Аналогична директиве BYTE.
Аналогична директиве BLOCK.
DUP указывает количество повторов строк, которые расположены до псевдо-операции EDUP. DUP может быть использован в макросах.
Необязательным вторым аргументом (начиная с версии v1.20.2) является имя метки (переменной), чтобы внутри повторяющихся блоков к этим меткам (переменным)были добавлены индексы повторения (значения 0, 1, 2, 3, ...).
ExampleВ 5.20.В
DUP 3 ; нулевое значение счетчика позволило бы пропустить весь блок NOP EDUP /* будет представлено как: NOP NOP NOP */
Аналогична директиве WORD.
Определяет так называемое двойное слово. Значения должны быть между -2147483649 и 4294967296.
То же, что и BYTE, но в конце будет добавлен дополнительный ноль.
Полезно только для пользователей ZX-Spectrum
Создайте новый или перезапишите существующий стандартный файл магнитофонной записи для эмуляторов ZX-Spectrum. Смотрите пример SAVETAP.
Полезно только для пользователей ZX-Spectrum
Создайте пустой TRD-образ для эмуляторов ZX-Spectrum. Смотрите пример SAVETRD.
Полезно только для пользователей, не владеющих английским языком
Установить текущую кодировку символов, т.е. если вы установите "DOS", SjASMPlus автоматически преобразует строки из ANSI в DOS-866. Кодировка может быть "DOS" (DOS-866) или "WIN" (ANSI/Win1251). Значение по умолчанию - "WIN".
Пример В 5.23.В
ENCODING "WIN" DB "тексттекст" ;will be тексттекст ENCODING "DOS" DB "тексттекст" ;will be ⥪бв⥪бв
На указанном адресе ассемблер остановится. Псевдо-операция AND не работает в начале строки (даже с --dirbol). Можно использовать необязательный аргумент SAVEZNA, SAVECPCSNA, SAVE TAPE и SAVE NEXT.
Смотри LUA для получения дополнительной информации.
Аналогичен ENDMODULE.
Служит для указания конца модуля (см. MODULE).
Аналогичен ENT.
Восстанавливает текущий адрес. СмотриDISP для получения дополнительной информации.
Присваивает метке значение, отличное от текущего значения счетчика команд. Метка не должна быть определена ранее (вы можете присвоить ей только одно значение). Необязательный параметр номер_Страницы
может принудительно ввести явное значение страницы для метки (для оператора$$label
).
Для изменяемых меток, содержащих временные значения, используйте DEFL.
Именованная метка будет записана в экспортный файл в виде 'метка: EQUAL значение'. Таким образом, экспортный файл может быть включен в другие источники. Порядок меток в файле соответствует порядку инструкций EXPORT.
Директива FPOS позволяет установить положение файла в любом месте выходного файла. Значение позиции без знака используется в качестве устанавливаемого абсолютного значения, позиция, начинающаяся со знака + или -, будет использоваться в качестве относительного положения.
В сочетании с OUTPUT <имя_файла>,r можно перезаписать существующие файлы.
Аналогичен DH, обычно используется без кавычек вокруг данных.
Записывает двоичный файл в выходной файл. Смещение и длина необязательны. Добавлено в версии 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
Записывает данные из файла hobeta в выходной файл. Смещение и длина необязательны.
Пример В 5.28.В
INCHOB "gfx.$c",7 ; включает gfx.scc, пропустив первые 7 байт INCHOB "sprs.$c",3,256 ; включает 256 байт из файла со смещением 3 байта INCHOB gfx.$c ,7 ; обратите внимание на пробел между именем файла и ',7' :)
Включает другой исходный файл в текущий. Исходные файлы могут быть вложены на глубину 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"
Добавляет другой LUA-скрипт в первый проход(!). Если файл не может быть найден в текущем каталоге (текущий каталог - это каталог, из которого поступает текущий файл), поиск файла будет произведен в каталогах, указанных в командной строке. При использовании угловых скобок поиск в каталогах командной строки выполняется перед текущим каталогом.
Пример В 5.30.В
INCLUDELUA <mylibrary1.lua> INCLUDELUA mylibrary2.lua INCLUDELUA "library_for_zx.lua"
Добавляет файл из TRD образа в выходной файл. Смещение и длина необязательны.
Пример В 5.31.В
INCTRD "test.trd","mygfx.C" ; добавить файл mygfx.C из образа test.trd INCTRD "test.trd","mygfx.C",12 ; добавить mygfx.C из образа test.trd, пропустив первые 12 байт
INSERT аналогичен команде INCBIN. Смотри выше.
Полезно только для эмулятора ZX-Spectrum UNREAL SPECCY.
Работает только в режиме эмуляции реального устройства. Смотри DEVICE.
Сохраняет список меток в формате:
NN:ADDRESS LABELNAME
где NN - номер страницы памяти, а АДРЕС усечен до диапазона 0000..3FFF
Если <виртуальные метки>
отличны от нуля, то номер страницы NN не является частью выходных данных, а АДРЕС усекается до диапазона 0000..FFFF.
Используя псевдо-операции 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
Пока недоступно.
Сопоставляет страницу(ы) памяти со слотом(ами), аналогично комбинации СЛОТ + СТРАНИЦА, но позволяет настроить весь диапазон последовательных слотов (с последовательными страницами памяти). Или, если указан только один слот, можно использовать дополнительную опцию для расширения функциональности конкретного слота. Поведение слота будет оставаться заданным на текущем УСТРОЙСТВЕ до тех пор, пока другой 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
Метки должны быть уникальными только внутри текущего модуля (модуль добавляется к ним в качестве префикса). Также обратите внимание на использование оператора '@' для подавления всей этой обработки меток. Модули могут быть вложенными, и модуль должен заканчиваться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 ; восстановление синтаксиса в исходное состояние
Установите программный счетчик на определенный адрес. Если указан второй аргумент, это изменит страницу памяти в текущем слоте, см. 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
Завершает генерацию выходных данных компилятора в файл, указанный в OUTPUT, и сбрасывает значение SIZE на значение по умолчанию "нет".
С помощью 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.
Работает только в режиме эмуляции реального устройства. Смотри DEVICE.
Устанавливает текущую страницу памяти в текущий слот.
ExampleВ 5.39.В
PAGE 7 ; установить 7 страницу SAVEBIN "ram7.bin",$C000,$4000 ;- записать $4000 байт из ОЗУ с адреса $C000 в указанный файл
Аналогичен DISP.
Завершает блок кода, для которого создаются данные о перемещении (начинается с RELOCATE_START). Чтобы получить сами данные о перемещении, используйте RELOCATE_TABLE и связанные с ними символы.
Для получения более подробной информации / примеров ознакомьтесь с examples/relocation, examples/SymbOS_nslookup и relocation tests.
Отмечает начало блока, для которого создаются данные о перемещении. Любая * обычная* метка (не символы EQUAL/DEFL), определенная внутри блока RELOCATE_START .. RELOCATE_END будет рассматриваться как метка "перемещаемый". Любая инструкция/директива внутри блока, для которой требуется скорректировать результирующий код операции при перемещении на другой адрес, создаст данные перемещения для RELOCATE_TABLE.
Команда RELOCATE_START HIGH
проверяет только перемещение старших байтов. Созданная таблица указывает на старший байт (MSB) машинного кода. Этот режим предназначен для ОС / загрузчиков, которые перемещаются только в выровненные по 256 байтам границы (сохраняя LSB нетронутым).
Функция перемещения обычной метки является переходной, и присвоенное EQU значение, основанное на уже перемещаемой метке, также будет помечено как перемещаемое. Также структуры, созданные в перемещаемом блоке, имеют свои метки, помеченные как перемещаемые, и их начальные значения могут стать частью данных перемещения, если начальное значение основано на перемещаемом значении.
Вы можете добавить operator norel
к метке, чтобы лишить ее свойства перемещения для конкретного выражения.
Внутренняя эвристика не является пуленепробиваемой, некоторое сложное выражение может не быть распознано как фиксированное / перемещаемое значение и вместо этого предупреждать о нестабильном результате. Рекомендуется собирать перемещаемые блоки в нижних областях адресного пространства(например, ORG 0
или ORG $1000
) и чтобы выражения были достаточно простыми.
Выдает данные о перемещении, собранные по всем блокам перемещения. There are also two built-in symbols relocate_count
и relocate_size
содержащих размер таблицы (в sjasmplus поддерживаются только таблицы типа word, поэтому размер всегда равен удвоенному количеству).
Таблица представляет собой необработанный массив значений WORD (16 бит) со смещениями машинного кода в памяти, которые должны быть скорректированы (когда код перемещается по адресу, отличному от исходного базового адреса). Чтобы получить смещения от определенного базового адреса, используйте ORG перед блоком перемещения, чтобы получить инструкции и метки оттуда.
<вычитаемое_смещение> вычитается из каждого смещения, записанного в таблице перемещения (то же самое, что WinAPE делает со своим необязательным аргументом "base_address" для RELOCATE_TABLE).
Аналог команды DUP. Также является аналогом блока REPT до ENDR (EDUP также работает).
Работает только в режиме эмуляции виртуального устройства. Смотри 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
Работает только в режиме эмуляции виртуального устройства. Смотри DEVICE.
Как и SAVEBIN, сохраняет блок оперативной памяти устройства из "адреса", но с добавлением заголовка AMSDOS 128 байт.
Пример В 5.41.В
DEVICE AMSTRADCPC464 ... некоторый код ... ; по умолчанию сохраняется тип=2 (ДВОИЧНЫЙ) ; значение "start" (запись) по умолчанию равно 0, здесь оно заменено на $1234 SAVEAMSDOS "code.bin", $1000, $1b00, $1234
Работает только в режиме эмуляции реального устройства. Смотри 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
Работает только в режиме эмуляции реального устройства 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)
Работает только в режиме эмуляции реального устройства. Смотри DEVICE.
Как и SAVEBIN, Как и SAVE BIN, сохраняет блок оперативной памяти устройства.
Но это допускает длину более 64 кб, и значение смещения поступает непосредственно в виртуальную память устройства (где страницы выделяются последовательно), игнорируя текущее "отображение" слота. Т.е. страница = 2, смещение = 0 начнет сохранять данные со страницы 2 в ее начале, проходя через страницы 3, 4, 5, ... до тех пор, пока не будет сохранен запрошенный объем данных.
Смещение не ограничено размером страницы, т.е. аргументы page=1,offset=0x500 равны аргументам page=0,offset=0x4500 для устройства ZX SPECTRUM 128 (имеет размер страницы 0x4000).
Работает только в режиме эмуляции реального устройства. смотри 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 оперативной памяти в файл
Команды для создания файла NEX, для получения подробной информации читайте главу SAVENEX .
Работает только в режиме эмуляции устройства ZX SPECTRUM NEXT. Смотри DEVICE.
Работает только в режиме эмуляции реального устройства. Смотри 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
Работает только в режиме эмуляции реального устройства. Смотри 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
Работает только в режиме эмуляции реального устройства. Смотри 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"
Работает только в режиме эмуляции реального устройства. Смотри 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, работает идентично ; ... ваш код программы
Запускает внешнюю программу <имя_файла> используя необязательную командную строку <параметры>.
Пример В 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
Если результирующий файл меньше заданной длины, добавляется столько нулевых байт, сколько необходимо. Подробнее смотрите в OUTPUT.
Введите `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 - не экспортируется, чувствителен к регистру!
Работает только в режиме эмуляции реального устройства. Смотри 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" ;....
Завершает генерацию выходных данных компилятора в блок ленточного файла, указанного в 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-файл с содержимым экрана.
Аналог DISP.
Удаляет идентификатор, определенный с помощью 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
Аналог ENT.
В то время как выражение принимает ненулевое значение, генерирует следующие строки до тех пор, пока не встретится 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 */
Определяет слово. Значения должны находиться в диапазоне от -32787 до 65536.
Может оказаться полезным собрать часть исходника (или нет) в зависимости от определенного условия.
Если <выражение> отличается от нуля, следующие строки собираются до тех пор, пока не встретится опертор ELSE, ELSEIF или ENDIF.
Прямая ссылка на метку вызовет предупреждение, поскольку любой машинный код, выдаваемый внутри блока IF/IFN с таким выражением, может привести к нестабильным результатам. Если вы уверены, что позднее определение метки не повлияет на результирующий машинный код (блок IF не выдает никакого машинного кода и не определяет никакой метки), вы можете отключить предупреждение.
Ghbvth В 5.60.В
IF (aaa == 0) || (2 = aaa && ((bbb % 13) & 0x01)) ; некоторый код для сборки только в том случае, если символ `aaa` равен нулю ; или (логическое ИЛИ), когда символ `aaa` равен двум ; и (логическое И) остаток от деления на 13 от `bbb` является нечетным числом ENDIF
Если <выражение> равно нулю, следующие строки собираются до тех пор, пока не встретится оператор ELSE, ELSEIF или ENDIF.
Условие выполняется, если определен идентификатор. Это НЕ метки.
Условие истинно, если идентификатор не определен. Это НЕ метки.
Условие истинно, если где-то в коде используется метка. Вы можете создавать библиотеки полезных функций, используя псевдо-операцию 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 будет собран, и локальные метки тоже станут видимыми.
Условие истинно, если где-то в коде есть метка, которая не используется.
Смотри IF. Если условие IF равно false (во всех предыдущих блоках IF/ELSEIF), else-часть компилируется.
Если предыдущий IF-блок имел условие false, вычисляется выражение ELSEIF, и ELSEIF действует как новое IF.
За каждым 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
Структуры можно использовать для более легкого определения структур данных в памяти. Название структуры задается в соответствии с общим размером структуры.
Определение структуры начинается с: STRUCT
<имя>[,<начальное смещение>]
и заканчивается словами
ENDS
. Определения структуры являются локальными для текущего модуля, но, как и в случае с метками, '@' может использоваться для переопределения этого.
Строки между STRUCT и ENDS должны иметь следующий формат:
имя_участника псевдооперации операнды
Все поля являются необязательными. Строки без метки должны начинаться с пробела.
Когда используется ненулевое смещение
, оно действует так, как если бы
BLOCK with length
equal to
смещение
было определено как первый член структуры.
Между псевдо-инструкциями STRUCT и ENDS могут быть использованы следующие инструкции:
Определяет однобайтовый элемент. Значение по умолчанию используется, когда при объявлении структуры не задается значение инициализации. (Вместо BYTE могут использоваться DB и DEFB).
Определяет двухбайтовый элемент. Значение по умолчанию используется, когда при объявлении структуры не задается значение инициализации. (Вместо WORD могут использоваться DW и DEFW).
Определяет трехбайтовый элемент. Значение по умолчанию используется, когда при объявлении структуры не задается значение инициализации.
Определяет четырехбайтовый элемент. Значение по умолчанию используется, когда при объявлении структуры не задается значение инициализации. (Вместо DWORD могут использоваться DD и DEFD).
(начиная с версии v1.17) Для определения элемента указанной длины
в байтах.
Операнды отформатированы в DB-подобном формате, и последний явно определенный байт заполнит оставшиеся байты, зарезервированные при определении (обнуляются, если значение вообще не указано).
Значение по умолчанию может быть изменено с помощью значений init, когда используется структура, но тогда только заданные байты перезаписывают содержимое по умолчанию, НЕ заполняя его остальную часть.
Хотя операнды отформатированы в формате DB, они должны быть заключены в фигурные скобки. Также убедитесь, что фигурные скобки не перепутаны с необязательными фигурными скобками на границах подструктуры, при использовании элемента TEXT в подструктуре вам может потребоваться использовать фигурные скобки для самой подструктуры вокруг фигурных скобок, используемых для значений TEXT (что делает фигурные скобки подструктуры обязательными в таком случае). Длина может составлять от 1 до 8192 байт (если вам нужен еще более длинный "текст", используйте два члена и разделите свои аргументы).
Чтобы определить элемент из указанного количества байт. Аргументы задаются при определении текущей структуры и не являются частью значений init при последующем использовании структуры. (Вместо BLOCK могут использоваться '#', DS и DEFS).
(начиная с версии v1.11), если заполняющий_байт
опущен, содержимое памяти устройства в области блока сохраняется (не обнуляется).
Выравнивает смещение. Если выражение опущено, предполагается значение 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)
Почему скриптовый движок в виде 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 вы можете управлять некоторыми переменными и использовать функции компилятора. Полный список:
Вычисление выражения с помощью калькулятора компилятора (только 32-разрядный).
Пример: val = _c("SOMELABEL+12")
Анализ строки ассемблера Z80. Пример: _pc("ADD A,B")
Анализ строки ассемблера Z80. Пример: _pl("SOMELABEL ADD A,B")
Эта привязка делает почти все псевдоинструкции (директивы) доступными из Lua-скрипта со всеми опциями и функциями. В будущем API привязок будет в основном заморожен, расширяясь только в том случае, если использование_pl(...)
слишком громоздко.
Смотри _c
Смотри _pc
Смотри _pl
Печать сообщения об ошибке.
Вывести предупреждающее сообщение.
Проверить, существует ли файл.
Получает значение define, возвращает nil, если define не найдено. При желании можно также выполнить поиск аргументов макроса (с более высоким приоритетом).
Добавляет новое определение. Возвращает true, если define является новым, false, когда define уже существовал и значение было заменено, или когда id недействителен.
Получает адрес метки. Возвращает -1, если имя недопустимо, 0, если не найдено или все еще имеет неопределенное значение (вы также можете использовать _c("имя")
чтобы получить значение символа и выполнить с ним некоторые вычисления).
Добавляет новую метку. Возвращает true, если метка была успешно вставлена (или значение изменено в первый раз при следующем проходе сборки), false, если имя недопустимо или метка уже была определена.
Переменная, доступная только для чтения. Текущий адрес.
Переменная, доступная только для чтения. Количество ошибок.
Переменная, доступная только для чтения. Количество предупреждений.
Завершает работу компилятора.
Добавляет байт на вывод (или в память) и увеличивает на 1 sj.current_address
Добавляет слово на вывод (или в память) и увеличьте на 2 sj.current_address
Получает байт из памяти. Работает только в режиме эмуляции реального устройства и только на последнем этапе сборки.
Получает слово из памяти. Работает только в режиме эмуляции реального устройства и только на последнем этапе сборки.
Возвращает идентификатор текущего эмулируемого устройства. Возвращает "NONE", если режим эмуляции отсутствует.
Установливает идентификатор текущего эмулирующего устройства. Возвращает значение false, если запрошенный идентификатор устройства не найден и текущий набор устройств потерян (установлено значение "НЕТ").
Установливает "номер страницы" в текущий слот. Работает как псевдо-оператор PAGE.
Установите для текущего слота значение "номер". Работает как псевдо-оператор SLOT.
(начиная с версии v1.20.0) Вы также можете вместо этого использовать начальный адрес слота, например, для ZX128
sj.set_slot(0x8000)
является псевдонимом sj.set_slot(2)
.
Смотри псевдо-оператор SHELLEXEC.
Создает пустой файл TRD образа.
Сохраняет блок памяти в файл образа TRD. Работать только в режиме эмуляции реального устройства.
Сохранение моментального снимка памяти в формате 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
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 обеспечивает это).
Открывает файл 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 приведет к ошибке.
Установите минимально необходимую следующую версию ядра, может быть установлена в любое время до CLOSE.
Установите цвет границы (во время загрузки), следует ли переводить компьютер в состояние по умолчанию (PreserveNextRegs = 0 = по умолчанию), требуется ли приложению расширенная оперативная память (224 8k страниц) и как следует обращаться с дескриптором файла NEX: 0 = по умолчанию = закрыть, 1 = оставить открытым и передайте в BC, $4000..$FFFE = оставить открытым и записать в память по указанному адресу (после того, как банк ввода будет выгружен). Это может быть установлено в любое время до CLOSE.
Все это функции формата 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), двоеточие или нулевой байт (усеченный не содержит символа-ограничителя, просто заполняет полный буфер).
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 позже укажет какую-либо палитру (она все равно будет проигнорирована).
Загрузочный экран слоя 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 пикселей видно на многих экранах дисплеи тоже), вы можете организовать свой экран таким образом, чтобы отображать всю важную информацию в этой области, а остальную сделать "неважной", чтобы она могла скрываться за краем экрана.
Загрузочный экран LoRes (128x96), может использоваться между командами OPEN и первой AUTO/BANK.
Палитра похожа на режим Layer 2, только в режиме LoRes бит приоритета отсутствует.
Данные изображения представляют собой блок памяти объемом 12288 байт - либо последовательный блок, если указан конкретный адрес, либо без адреса хранится фактическая память банка 5 (берется 6144 байта с адреса 0x4000 и 6144 байта с адреса 0x6000).
Можно использовать только небольшое подмножество 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.
Экран загрузки режимов 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 вы должны указать цвет чернил (бумага должна быть заполнена чернилами).
Экран загрузки 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.
Может быть использован после OPENи перед первой командой AUTO или BANK (данные о меди сохраняются между экраном и банковскими данными).
Хранится ровно 2048 байт (полная память Copper), и загрузчик запустит код copper в режиме %01 (сбросит CPC на 0, затем запустит copper), так что код copper будет бесконечно повторяться после выполнения 1024-й инструкции. Процесс запускается после загрузки и отображения экранного блока.
Может быть использован после команды OPEN or SCREEN и перед CLOSE, но банки 16k i должны быть сохранены в правильном порядке: 5, 2, 0, 1, 3, 4, 6, 7, 8, 9, 10, ..., 111
Может быть использован после команды OPEN or SCREEN и перед CLOSE. sjasmplus сохранит каждый 16-килобайтный банк, содержащий по крайней мере один ненулевой байт; обнаруженный в правильном порядке (автоматически сохранит каждый ненулевой 16-килобайтный банк, обнаруженный в правильном порядке (автоматически начиная с первого возможного банка после предыдущих команд BANK /AUTO или из предоставленного "from Bank").
Для значения "_from Bank" используйте указанный выше порядок в команде BANK , т.е. 5, 2, 0, ...
Может быть использован после команды 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 добавлены просто в качестве примера)
Данные 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, но все еще зависит от отладчика, может ли он отображать как исходный код верхнего уровня, запускающий генератор, так и исходные строки, содержащие определения конкретных инструкций.
Формат файла все еще находится в стадии разработки. Если вы работаете над поддержкой в 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|