Files
snark13 c71e249a4e Add full compiler toolchain, libc, examples and reference docs
First substantive commit: the entire Sprinter C compiler tree on top of
the bare README+gitignore initial commit.

What's in here:
  bin/sprinter-cc        — driver script invoking SDCC + linker + mkexe
  libc/                  — Sprinter-specific libc layer over ESTEX/BIOS
                           (conio, gfx, io, mem, stdio + headers)
  runtime/               — crt0 variants (default/small/banked/minimal)
                           + heap + bank trampolines
  toolchain/             — mkexe (SprintEXE packer, C + tests)
  examples/              — 30 demo programs (gfx, file I/O, env, time, …)
  lib/Makefile           — builds the libc archive (sprinter.lib)
  docs/                  — converted Sprinter manuals + asm reference samples
  third_party/           — solid-c reference compiler dump + sdcc setup script
  release_docs/          — packaging / release notes

gitignore overhaul:
  • Drop dangerous blanket patterns: *.asm (would hide docs/samples/*.asm)
    and *.exe (case-insensitive match was hiding third_party/solid-c/*.EXE
    on macOS APFS).  Replaced with examples/*/*.{asm,exe,…} and lib/*.lib.
  • Restore tracking of toolchain/mkexe/tests/{one,big}.bin — those are
    INPUT fixtures, not build outputs.
  • Collapse the duplicated SDCC/C/Sdcc sections into one section per
    concern (build outputs / vendored / OS-junk).
  • Add .sprinter-cc-*/, build/ (catches lib/build/ too), .claude/.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 16:13:21 +03:00

1218 lines
73 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Макроассемблер M80
===================
Содержание
1 Назначение и условия применения макроассемблера.....
2 Элементы и основные конструкции языка...............
2.1 Основные элементы языка.............................
2.1.1 Символы.............................................
2.1.2 Числа, константы и строки...........................
2.1.3 Символические имена.................................
2.2 Выражения...........................................
2.2.1 Арифметические и логические операции................
2.2.2 Абсолютные и перемещаемые имена.....................
2.2.3 Внешние ссылки......................................
2.3 Синтаксис ассемблерных предложений..................
2.3.1 Метка...............................................
2.3.2 Оператор............................................
2.3.3 Операнды и примечания...............................
2.4 Псевдокоманды.......................................
2.4.1 Псевдокоманды перемещения...........................
2.4.1.1 ASEG................................................
2.4.1.2 COMMON..............................................
2.4.1.3 CSEG................................................
2.4.1.4 DSEG................................................
2.4.2 DB - определить байт................................
2.4.3 DC - определить символ..............................
2.4.4 DS - определить область.............................
2.4.5 DW - определить слово...............................
2.4.6 END.................................................
2.4.7 ENTRY/PUBLIC........................................
2.4.8 EQU.................................................
2.4.9 EXT/EXTRN...........................................
2.4.10 INCLUDE.............................................
2.4.11 NAME................................................
2.4.12 ORG - задать счетчик адреса.........................
2.4.13 PAGE................................................
2.4.14 ASET................................................
2.4.15 TITLE...............................................
2.4.16 SUBTTL..............................................
2.4.17 .COMMENT............................................
2.4.18 .PRINTX.............................................
2.4.19 .RADIX..............................................
2.4.20 .REQUEST............................................
2.4.21 Условные псевдокоманды.............................
2.4.21.1 ELSE...............................................
2.4.21.2 ENDIF..............................................
2.4.23 Перемещение перед загрузкой........................
2.5 Макрокоманды и блоки...............................
2.5.1 Терминология.......................................
2.5.2 Блок REPT-ENDM.....................................
2.5.3 Блок IRP-ENDM.....................................
2.5.4 Блок IRPC-ENDM.....................................
2.5.5 MACRO..............................................
2.5.6 EXITM..............................................
2.5.7 LOCAL..............................................
2.5.8 Специальные макрооператоры и формы.................
3 Руководство по эксплуатации компилятора M80........
3.1 Обращение к компилятору. Входные и выходные данные.
3.2 Опции компиляции...................................
3.3 Формат листинга....................................
3.4 Сообщения об ошибках...............................
1. Назначение и условия применения макроассеблера
Макроассемблер - это компилятор с символического машинно-
ориентированного языка (языка ассемблера). Он преобразует ис-
ходную программу, написанную на языке макроассемблера, в пере-
мещаемый модуль. В дальнейшем с помощью линкера модуль может
быть собран (один или с другими модулями) в программу, готовую
к выполнению.
Применение макросредств позволяет наиболее часто встреча-
ющиеся участки программы оформлять в виде макрокоманд.
2. Элементы и основные конструкции языка
2.1. Основные элементы языка
2.1.1. Символы
Все сложные элементы языка М80 формируются из символов.
В качестве символов могут использоваться:
- буквы латинского алфавита от A до Z
- цифры от 0 до 9
- специальные символы + - , : ; ( ) ' # $ пробел ;
2.1.2. Числа, константы и строки
Числа - это беззнаковые 16-битные величины. Число всегда
вычисляется в системе счисления по умолчанию, если оно не за-
дано в специальном виде:
nnnnnnnnB - двоичное (где n - 0 или 1)
nnnnO или nnnnQ - восьмеричное (где n - 0..7)
nnnnH или nnnnX - шестнадцатиричное (где n - 0..9,
A,B,C,D,E,F), если первый символ не
цифра, то перед ним должен стоять 0
0nnnnH или 0nnnnX
По умолчанию все числа считаются в десятичной системе
счисления. Этот режим можно изменить. С помощью команды .RADIX
можно выбрать любое основание системы счисления от 2 до 16.
Переполнение при вычислении числа игнорируется и значащими яв-
ляются младшие 16 бит.
Символьная константа - это строка, содержащая один или
два символа в апострофах.
Значением символьной константы, содержащей один символ,
является величина численного значения соответствующего кода,
принятого в операционной системе (ОС). Например, значением
константы "A" будет 41h.
Значением символьной константы, содержащей два символа,
будет двухбайтовое число, причем в старшем байте будет значе-
ние первого символа, а в младшем байте - значение второго
символа. Например, значением константы "AB" будет число
41h*256+42h.
Строка - это набор символов, заключенных в кавычки или
апострофы. Кавычки также могут быть элементом строки, но при
этом они должны удваиваться. Например, предложение
DB "Я""ИДУ""ГУЛЯТЬ"
запомнит строку
Я"ИДУ"ГУЛЯТЬ
Если между кавычками нет символов, то такая строка будет
пустой строкой.
2.1.3. Символьные имена (метки)
Символические имена могут содержать любое количество сим-
волов, но значащими являются:
а) в локальной метке значащими являются первые 16 символов.
б) в метках глобального и внешнего типов линкеру передаются
первые шесть символов, остальные символы отсекаются.
В именах допустимы следующие символы:
буквы от A до Z, цифры от 0 до 9, $ . ? @
Символическое имя не может начинаться с цифры.
При обработке имен буквы из нижнего регистра переводятся
в буквы верхнего регистра.
2.2. Выражения
2.2.1. Арифметические и логические операции
В выражениях допустимы следующие операции, приведенные в
порядке убывания приоритета их выполнения.
NUL
LOW, HIGH
*, /, MOD, SHR, SHL
Унарный минус
+, -
EQ, NE, LT, LE, GT, GE
NOT
AND
OR, XOR
Для изменения порядка выполнения операций надо использо-
вать скобки. При вычислении выражений сначала выполняются опе-
рации, имеющие более высокий приоритет. Все подвыражения,со-
держащие операции с более высоким приоритетом, вычисляются в
первую очередь.
Все операции, кроме +, -, *, /, должны быть отделены от
операндов по крайней мере одним пробелом. Операции выделения
байта HIGH, LOW выделяют старшие или младшие 8 бит из абсолют-
ной 16-битной величины. Если в качестве операнда используется
перемещаемая величина, то HIGH и LOW интерпретируются как опе-
рации, работающие с адресом ноль.
2.2.2. Абсолютные и перемещаемые имена
Все символические имена, используемые в качестве операн-
дов в выражениях, есть либо абсолютные имена, либо перемещае-
мые имена. Перемещаемые имена подразделяются на программные
перемещаемые имена, перемещаемые имена данных и COMMON (п.
2.4.1.).
Все символические имена, ассемблированные для псевдоко-
манд ASEG (по умолчанию), CSEG или DSEG, относятся к абсолют-
ным, перемещаемым программным или перемещаемым данным соот-
ветственно. Количество имен COMMON в программе зависит от чис-
ла блоков COMMON, поименованных в программе с помощью псевдо-
команды COMMON. Два символических имени COMMON считаются раз-
ными, если они присутствуют в разных блоках COMMON.
При любой операции, кроме сложения и вычитания, оба опе-
ранда должны быть абсолютными.
Для сложения применяются следующие правила:
1) по крайней мере один из операндов должен быть абсолютным;
2) абсолютное + перемещаемое = перемещаемое
Для вычитания действуют правила:
1) перемещаемое - абсолютное = перемещаемое
2) перемещаемое - перемещаемое = абсолютное
Причем в 2) оба имени должны быть перемещаемыми именами
одного типа.
Для каждого промежуточного шага при вычислении выражения
должны выполняться вышеуказанные правила, иначе будет выдано
сообщение об ошибке. Например, если FOO, BAZ и ZAZ - три симво-
лических перемещаемых имени, то выражение:
FOO + BAZ - ZAZ
выработает сообщение об ошибке, т.к. на первом шаге будут
складываться два перемещаемых имени. Этого можно избежать, ис-
пользуя скобки:
FOO + (BAZ - ZAZ)
2.2.3. Внешние ссылки
Символическое имя может быть внешним (EXTRN) или нет
(см.п. 2.2.9.). Внешнее имя ассемблируется в 2 байта. При ис-
пользовании внешних имен в выражениях должны выполняться сле-
дующие правила:
1) EXTRN допустимы только при сложении и вычитании;
2) если в выражении используется имя типа EXTRN,
то результат всегда будет EXTRN;
3) при сложении любой операнд (но не оба одновременно)
может быть EXTRN;
4) при вычитании только первый операнд может быть EXTRN.
2.3. Синтаксис ассемблерных предложений
Ассемблерная программа состоит из последовательности
предложений. Каждое предложение имеет следующую структуру:
метка: (оператор) (операнды) ;примечание
Совсем необязательно, чтобы предложение начиналось с
метки.
2.3.1. Метка
Метка - это символическое имя, после которого следует
двоеточие. Если метка присутствует, то она должна быть первым
элементом предложения. Значение метки есть текущее значение
счетчика адреса. Если после метки стоят два двоеточия "::", то
такая метка объявляется глобальной (PUBLIC) и к ней можно обра-
щаться из другой программы.
2.3.2. Оператор
Следующим элементом после метки или первым, если нет мет-
ки идет оператор. В качестве оператора может быть:
1) мнемокод микропроцессора Z80 (I8080);
2) макровызов;
3) псевдокоманда;
4) выражение.
Если в поле оператора стоит выражение, то ассемблер расс-
матривает его как псевдокоманду DB.
2.3.3. Операнды и примечания
Следующим элементом предложения являются операнды. В за-
висимости от оператора в поле операндов может быть один, два
или несколько операндов.
Примечания являются последним элементом предложения. При-
мечания всегда начинаются с символа ";" и заканчиваются CR (ВК).
2.4. Псевдокоманды
2.4.1. Псевдокоманды перемещения
Отличительной особенностью макроассемблера М80 является
создание им перемещаемых модулей. Перемещаемость модуля облег-
чает его отладку и тестирование, позволяет компоновать пограм-
му из нескольких модулей, написанных на разных языках. Кроме
того, программу можно разбивать на сенгменты и указать, какие
сегменты должны размещаться только в ОЗУ (сегменты данных), а
какие могут быть занесены в ПЗУ (сегменты содержащие програм-
му). Эти сегменты создаются с помощью псевдокоманд DSEG и
CSEG. Псевдокоманда ASEG используется при создании неперемеща-
емых (абсолютных) кодов. Псевдокоманда COMMON создает общие
области данных для каждого поименованного в программе блока
COMMON.
Для каждого сегмента программы ASEG, CSEG или DSEG заво-
дится свой счетчик адреса, который приостанавливает отсчет при
смене типа сегмента и возобновляет отсчет, когда снова встре-
чается соответствующий сегмент. Значение счетчика адреса в лю-
бом сегменте можно изменить с помощью псевдокоманды ORG
(п.2.4.12). По умолчанию всегда действует пседокоманда ASEG.
2.4.1.1. ASEG
Формат псевдокоманды: ASEG
ASEG устанавливает значение счетчика адреса на абсолютный
сегмент в памяти. Значение счетчика будет продолжением преды-
дущего ASEG (по умолчанию 0), если после ASEG не стоит ORG.
Для ассемблера ASEG является псевдокомандой по умолчанию.
2.4.1.2. COMMON
Формат псевдокоманды: COMMON /имя блока/
COMMON устанавливает счетчик адреса на адрес выбранного
общего блока памяти. Для совместимости с оператором COMMON в
ФОРТРАНЕ этот адрес всегда указывает на начало области. Если
"имя блока" опущено или состоит из пробелов, то блок COMMON
считается пустым.
2.4.1.3. CSEG
Формат псевдокоманды: CSEG
CSEG устанавливает значение счетчика адреса на смещение
относительно начала сегмента памяти, содержащего коды команд.
Значение адреса будет соответствовать значению предыдущего
CSEG (по умолчанию 0), если только после CSEG не стоит псевдо-
команда ORG.
2.4.1.4. DSEG
Формат псевдокоманды: DSEG
DSEG устанавливает значение счетчика сегмента адреса на
относительный адрес сегмента памяти, содержащего данные. Зна-
чение адреса будет соответствовать адресу последнего DSEG (по
умолчанию 0), если не было псевдокоманды ORG.
2.4.2. DB - определить байт
Формат псевдокоманды:
DB "выражение","выражение",...
или
DB "строка" ["строка"...]
Аргументами для DB могут быть выражения или строки. DB
запоминает значения выражений или символов в строках в после-
довательных адресах памяти, начиная с адреса, указанного в
счетчике адреса. Значение выражения должно помещаться в одном
байте. Если старший байт результата 0 или 255, то сообщение об
ошибке не выдается. В противном случае выдается ошибка A.
В выражениях не могут присутствовать строки, содержащие
более 2-х символов. Старший бит каждого байта, отведенного под
соответствующий символ, равен нулю.
Примеры:
0000 41 42 DB 'AB'
0002 42 DB 'AB' AND 0FFh
0003 41 42 43 DB 'ABC'
2.4.3. DC - определить символ
Формат псевдокоманды:
DC "строка"
DC запоминает символы, заданные в "строке", последова-
тельно, начиная с адреса, указанного в счетчике адреса. В от-
личие от DB, в байте, содержащем последний символ строки, в
старшем разряде стоит 1. Если строка пустая, то выдается сооб-
щение об ошибке.
2.4.4. DS - определить область
Формат псевдокоманды:
DS "выражение"
DS резервирует область памяти. Значение выражения показы-
вает, сколько байтов должно быть зарезервировано. Все имена,
присутствующие в выражени, должны быть определены к моменту
вычисления выражения при первом проходе макроассемблера. В
противном случае при первом проходе появится флаг V, а при
втором проходе - флаг U. Если втором проходе флаг U не появит-
ся, то все равно в модуле может быть ошибка, т.к. DS обрабаты-
вается при первом проходе.
2.4.5. DW - определить слово
Формат псевдокоманды:
DW "выражение","выражение",...
DW последовательно записывает значения выражений в ячейки
памяти, начиная с адреса, содержащегося в счетчике адреса. Зна-
чения выражений есть двух-байтовые величины.
2.4.6. END
Формат псевдокоманды:
END "выражение"
Оператор END указывает на конец программы. Если присутс-
твует "выражение", то оно указывает на стартовый адрес прог-
раммы. Если "выражение" отсутствует, то линкеру стартовый адрес
не передается.
*) Примечание.
Если ассемблерная программа является основной програм-
мой при компоновке, то в ней должен быть указан стар-
товый адрес. В противном случае линкер выдаст сообще-
ние об ошибке "нет стартового адреса". Если же ассемб-
лерная программа является подпрограммой по отношению
к программе, написанной, например на ФОРТРАНЕ, то стар-
товый адрес можно не задавать, т.к. он будет задан в
основной программе.
2.4.7. ENTRY/PUBLIC
Формат псевдокоманды:
ENTRY "имя","имя",...
или
PUBLIC "имя","имя",...
ENTRY или PUBLIC объявляют все имена, присутствующие в
списке, как доступные извне. После этого, к таким именам можно
обращаться из других программ. Все имена в списке ENTRY/PUBLIC
должны быть определены, иначе будет сообщение об ошибке U.
Имена, объявленные ENTRY или PUBLIC, заносятся в список глобаль-
ных имен и используются линкером при удовлетворении внешних
ссылок.
2.4.8. EQU
Формат псевдокоманды:
"имя" EQU "выражение"
По команде EQU символическому имени присваивается значе-
ние выражения. Если "выражение" имеет EXTRN, то выдается сооб-
щение об ошибке.
2.4.9. EXT/EXTRN
Формат псевдокоманды:
EXT "имя","имя",...
или
EXTRN "имя","имя",...
EXT или EXTRN объявляют указанные имена внешними (EXTRN),
т.е. определенными в другой программе. Объявить имя внешним
можно также поставив в конце имени два символа решетки "##".
Если имя, указанное в списке, определено в данной программе,
то будет выдано сообщение об ошибке M.
2.4.10. INCLUDE
Формат псевдокоманды:
INCLUDE имя файла
Три псевдокоманды INCLUDE, $INCLUDE и MACLIB эквивалент-
ны. Псевдокоманда INCLUDE позволяет включать в текст исходной
программы программы, записанные в других файлах. "имя файла" -
это имя файла, содержащего включаемую программу. Тип файла
должен быть ASM.
Файл, присутствующий в псевдокоманде INCLUDE, открывается
и транслируется в текущую программу сразу же за псевдокомандой
INCLUDE.
При выводе листинга в каждой строке, содержащей элемент
включенного файла, сразу же после кода команды стоит буква
"C". Вложение псевдокоманд INCLUDE не допускается. Если файл,
указанный в INCLUDE, не существует, то будет выдано сообщение
об ошибке "V" и данная псевдокоманда игнорируется.
2.4.11. NAME
Формат псевдокоманды:
NAME ('имя программы')
NAME задает имя программы. Значащими в "имени" являются
только первые шесть знаков. Имя можно задавать и с помощью
псевдокоманды TITLE. Если в программе отсутствует NAME и TIT-
LE, то в качестве имени берется имя исходного файла.
2.4.12. ORG - задать счетчик адреса
Формат псевдокоманды:
ORG "выражение"
Счетчику адреса присваивается выражение. Все имена в вы-
ражении должны быть определены при первом проходе.
2.4.13. PAGE
Формат псевдокоманды:
PAGE "выражение"
Пседокоманда PAGE дает указание ассемблеру начать новую
страницу вывода листинга. Если в псевдокоманде присутствует
"выражение", то оно задает число строк на странице. Это число
должно быть в диапазоне от 1 до 255. По умолчанию это число
равно 63.
2.4.14. ASET
Формат псевдокоманды:
"имя" ASET "выражение"
ASET осуществляет то же действие, что и EQU, но имя в
псевдокоманде ASET может быть определено ранее. Тогда после вы-
полнения ASET имя будет переопределено.
2.4.15. TITLE
Формат псевдокоманды:
TITLE "текст"
TITLE задает заголовок программы, который может печатать-
ся в первой строке каждой страницы. В тексте программы может
быть только одна псевдокоманда TITLE иначе быдет сообщение об
ошибке Q. Если не задана псевдокоманда NAME , то первые шесть
символов заголовка зададут имя модуля. Если в программе нет ни
NAME, ни TITLE, то имя модуля будет задано из имени исходного
файла.
2.4.16. SUBTTL
Формат псевдокоманды:
SUBTTL "текст"
Эта псевдокоманда выводит заголовок после заголовка, вы-
веденного псевдокомандой TITLE. Длина "текста" не должна пре-
вышать 60 знаков. В программе может быть любое количество
SUBTTL.
2.4.17. .COMMENT
Формат псевдокоманды:
.COMMENT "разделитель" "текст" "разделитель"
Первый символ, идущий после .COMMENT и отличный от пробе-
ла, считается разделителем. Текст после разделителя считается
примечаниями и может занимать произвольное количество строк.
Примечания заканчиваются, когда встречается второй разделитель
- тот же самый символ, который был использован в качестве пер-
вого разделителя.
2.4.18. .PRINTX
Формат псевдокоманды:
.PRINTX "разделитель""текст""разделитель"
Первый символ после .PRINTX, отличный от пробела, счита-
ется разделителем. Текст, идущий после разделителя, во время
трансляции выводится на терминал до тех пор, пока не встретит-
ся второй разделитель - тот же самый символ.
*) Примечание.
.PRINTX выводит листинг при каждом проходе ассемблера,
поэтому, если листинг нужен только при одном какомлибо
проходе, то следует использовать псевдокоманды IF1 или
IF2.
2.4.19. .RADIX
Формат псевдокоманды:
.RADIX "выражение"
По умолчанию система счисления всех констант - десятич-
ная. Псевдокоманда .RADIX позволяет изменить основание системы
счисления по умолчанию (от 2 до 16). "Выражение" в .RADIX
всегда в десятичной системе счисления независимо от основания
системы счисления, действующей в данный момент.
2.4.20. .REQUEST
Формат псевдокоманды:
.REQUEST "имя файла","имя файла",...
Эта псевдокоманда передает запрос линкеру на поиск неу-
довлетворенных внешних имен в файлах, указанных в списке.
Имена файлов в списке не должны содержать типов файла и ссы-
лок на диски. Линкер ведет поиск файла с заданным именем и
с типом - REL на диске по умолчанию.
2.4.21. Условные псевдокоманды
Список условных псевдокоманд
IF/IFT "выражение" Истина, если "выражение" не равно 0
IFE/IFF "выражение" Истина, если "выражение" равно 0
IF1 Истина при первом проходе
IF2 Истина при втором проходе
IFDEP "символ" Истина, если "символ" определен или
объявлен EXTERNAL
IFDEF "символ" Истина, если "символ" не определен и
не объявлен EXTERNAL
IFB "аргумент" Истина, если "аргумент" есть пробел.
аргумент должен быть в угловых скобках
IFNB "аргумент" Истина, если "аргумент" не пробел.
Используется для проверки некоторых
параметров. Аргумент должен быть в
угловых скобках.
IFIDN "аргумент1", Истина, если строка "аргумент1" иден-
"аргумент2" тична строке "аргумент2". Аргументы
должны быть в угловых скобках.
IFDIF "аргумент1", Истина, если строка "аргумент1" отли-
"аргумент2" чается от строки "аргумент2".
Все условные псевдокоманды имеют формат:
IF XXX [аргумент]
.
.
[ELSE
.
.
]
ENDIF
Допускается вложение условных псевдокоманд, т.е. псевдо-
команда внутри псевдокоманды. Во избежание ошибок все аргумен-
ты условных псевдокоманддолжны быть известны при первом прохо-
де. Для IF, IFT, IFF и IFE выражения должны содержать только
определенные символы и все выражения должны быть абсолютными.
2.4.21.1. ELSE
Каждая псевдокоманда IF должна иметь соответствующую ей
псевдокоманду ENDIF, заканчивающую условие.
2.4.22. Псевдокоманды, управляющие выводом листинга
Выводом листинга в файл можно управлять с помощью двух
псевдокоманд:
.LIST и .XLIST
Если листинг не выводится, то данные псевдокоманды игно-
рируются.
По умолчанию действует псевдокоманда .LIST, инициирующая
вывод листинга. Если встречается псевдокоманда .XLIST, то вы-
вод листинга прекращается, пока не встретится псевдокоманда
.LIST.
Вывод условных блоков, имеющих значение ложь, употребляет-
ся тремя псевдокомандами:
.SFCOND подавление вывода условных блоков, имеющих
значение "ложь";
.LFCOND восстановить вывод условных блоков, имеющих
значение "ложь";
.TFCOND управлять выводом условных блоков, имеющих
значение "ложь", в зависимости от опции /X.
Вывод таблицы перекрестных управляется псевдокомандами
.CREF и .XCREF. Если кросс-средства не используются, то эти
псевдокоманды игнорируются. Условие по умолчанию - .CREF. Если
встречается псевдокоманда .XCREF, то вывод перекрестных ссылок
прекращается до тех пор, пока снова не встретится псевдокоман-
да .CREF.
Вывод расширений MACRO/REPT/IRP/IRPC управляется тремя
псевдокомандами:
.LALL выводит полный макротекст для всех расширений;
.SALL выводит только сгенерированные объектные коды;
.XALL выводит сгенерированные объектные коды и соот-
ветствующий им текст (условие по умолчанию).
2.4.23. Перемещение перед загрузкой
С помощью двух псевдокоманд: .PHAZE и .DEPHAZE некоторые
участки программ могут находится в одной области, а выполнять-
ся лишь в другой, заданной, области.
Псевдокоманда .PHAZE обозначает начало такого участка, а
псевдокоманда .DEPHAZE - конец участка.
Пример:
0000 .PHAZE
0100 CD 0106 F00: CALL BAZ
0103 C3 0007 JMP Z00
0106 C9 BAZ: RET
0007 C3 0005 Z00: JMP 5
Все метки внутри блока .PHAZE получают абсолютные значе-
ния в зависимости от значения счетчика адреса .PHAZE. Однако
коды, загружаются в текущую область памяти (т.е. с 0000 в этом
примере). Позже их можно переслать по адресу 100h и выполнить.
2.5. Макрокоманды и блоки
Макросредства ассемблера MACRO включают в себя три макро-
команды повторения (REPT, IRP, IRPC) и операцию макроопределе-
ния (MACRO). Каждая макрокоманда должна заканчиваться псевдо-
командой ENDM.
2.5.1. Терминология
Для описания макрокоманд используются следующие термины:
1) "фор.пар." - формальный параметр
Все формальные парметры являются допустимыми символическими
именами, которые появляются в теле макрорасширения;
2) "список форм.пар." - список формальных параметров, разделен-
ных запятыми;
3) "список арг." - список аргументов, разделенных запятыми.
Список аргументов всегда заключен в угловые скобки. Если
в угловых скобках нет символа или между двумя запятыми нет
символа, то это нулевой аргумент в списке. При вложении уг-
ловых скобок (скобки в скобках) каждый внутренний уровень
скобок удаляется при использовании соответствующего аргу-
мента. Строка в кавычках является допустимым аргументом;
4) "список пар." - список параметров, разделенных запятыми.
2.5.2. Блок REPT-ENDM
Формат макрокоманды:
REPT "выражение"
.
.
ENDM
Вычисляется значение "выражения" и группа предложений,
заключенная между REPT и ENDM, повторяется полученное число
раз. "выражение" не может содержать внешние и неопределенные
имена.
Пример:
X ASET 0
REPT 10 ;генерирует DB 1 - DB 10
X ASET X+1
DB X
ENDM
2.5.3. Блок IRP-ENDM
Формат макрокоманды:
IRP "фор.пар.",<список арг.>
.
.
ENDM
Число аргументов в списке определяет, сколько раз будет
повторена группа предложений, заключенная между IRP и ENDM.
При каждом повторении вместо всех вложений формального пара-
метра подставляется очередное значение из списка аргументов.
Если список аргументов пуст (<>), то группа предложений обра-
батывается 1 раз и формальный параметр удаляется из всех вхож-
дений.
Пример:
IRP X, <1,2,3,4,5,6,7,8,9,10>
DB X
ENDM
Результат будет аналогичен предыдущему примеру.
2.5.4. Блок IRPC-ENDM
Формат макрокоманды:
IRPC "фор.пар.", строка (или "строка")
.
.
ENDM
Количество знаков в строке указывает, сколько раз будет
повторена группа предложений между IRPC и ENDM. В данном слу-
чае угловые скобки не обязательны. При каждом повторении вмес-
то формального параметра будет подставляться очередной знак из
строки.
Пример:
IRPC X, 0123456789
DB X+1
ENDM
Результат аналогичен двум предыдущим примерам.
2.5.5. MACRO
Формат макрокоманды:
"имя" MACRO "список форм.пар."
.
.
ENDM
С помощью MACRO пользователь может создавать свои макро-
команды и помещать их в различные участки программы.
"имя" - это символическое имя, по которому впоследствии
будут вызывать данную макрокоманду.
"список форм.пар." - это список парметров, которые будут
изменяться (замещаться фактическими параметрами) при каждом
вызове макрокоманды. Предложения между MACRO и ENDM составляют
тело макрокоманды.
Форма обращения к макрокоманде следующая:
"имя" "список пар."
где "имя" - это имя присвоенное MACRO в макроопределении;
"список пар." - это список фактических параметров, которые
при вызове макрокоманды заменят соответствующие формальные
параметры.
Если число фактических параметров превышает количество
формальных параметров, то лишние фактические параметры игнори-
руются. Если же число параметров меньше числа формальных пара-
метров, то вместо недостающих фактических параметров будут
подставлены нули.
Пример:
F00 MACRO X
Y ASET 0
REPT X
Y ASET Y+1
DB Y
ENDM
ENDM
При обращении F00 10 эта макрокоманда сгенерирует те же
предложения, что и в предыдущих примерах.
2.5.6. EXITM
Псевдокоманда EXITM используется для завершения
REPT/IRP/IRPC или вызова MACRO. При выполнении EXITM макрорас-
ширение немедленно выводится, а все оставшееся расширение или
повторение не генерируется. Если блок, содержащий EXITM, вхо-
дит в другой блок, то внешний уровень продолжает расширяться.
2.5.7. LOCAL
Формат команды:
LOCAL "список фор.пар."
Эта псевдокоманда допустима только внутри макроопределе-
ния MACRO. При выполнении LOCAL ассемблер создает уникальное
символическое имя для каждого формального параметра из списка
и подставляет потом это символическое имя при каждом вхождении
данного формального параметра в макрорасширение. Обычно, эти
уникальные символические имена используются для задания меток
внутри MACRO. Это исключает возможность появления многократно
определенных меток при неоднократных вызовах данной макроко-
манды. Символические имена, создаваемые при помощи LOCAL, на-
ходятся в диапазоне от ..0001 до ..FFFF. Поэтому пользователю
в своих программах следует избегать имен типа ..NNNN. Если в
макрокоманде есть LOCAL , то LOCAL должна быть в первом прело-
жении макроопределения.
2.5.8. Специальные макрооператоры и формы
& амперсанд используется для конкатенации текста или
символических имен. Формальный параметр, представляю-
щий собой строку в апострофах, не будет заменен в рас-
ширении, если перед ним не будет стоять амперсанд. Для
образования символического имени из текста и формаль-
ного параметра между ними надо поставить &;
Пример:
ERG MACRO X
ERROR&X: PUSH BC
LD B,'&X'
JP ERROR
ENDM
В этом примере вызов ERG A создаст следующую последова-
тельность предложений:
ERROR&A: PUSH BC
LD B,'A'
JP ERROR
*) Примечание.
Два символических имени считаются одинаковыми, если
одно имя отличается от другого только наличием амперсанда. Так
символическое имя ERRORA эквивалентно имени ERROR&A.
;; Если в макрокоманде перед комментариями стоят две
точки с запятой, то эти коментарии не появляются в
макрорасширениях даже, если есть указание .LALL;
$ ссылка на текущее значение счетчика адреса;
! символ, стоящий после восклицательного знака вводит-
ся литерально;
NUL это оператор, возвращающий значение "истина", если
его аргумент есть нуль. Остаток строки после NUL
рассматривается как аргумент для NUL. Условие IF NUL
аргумент будет "ложным", если при расширении первый
символ аргумента будет отличен от точки с запятой
или "CR" (ВК). Этот оператор рекомендуется исполь-
зовать для проверки наличия нулевых параметров в
условных псевдокомандах IFB и IFNB;
% этот оператор может использоваться только в аргумен-
те макрокоманды. % преобразует следующее за ним вы-
ражение (обычно символическое имя) в число в текущей
системе счисления. Во время макрорасширения получен-
ное число подставляется в формальный параметр. Ис-
пользование % позволяет вызывать макрокоманду с чис-
лом (обычно макровызов - это вызов с текстом из ар-
гументов). Выражение, следующее за % должно удовлет-
ворять тем же требованиям, что и в псевдокоманде DS.
Пример:
Нормально LB, являющееся аргументом для MACLAB, должно бы-
ло подставляться аргументом MACRO. % преобразует LB в число и
вместо Y подставляется уже число. Без % результат трансляции
был бы 'ERROR LB'.
MACLAB MACRO Y
ERR&Y: DB 'ERROR &Y',0
ENDM
MACERR MACRO X
LB ASET 0
REPT X
LB ASET LB+1
MACLAB %LB
ENDM
ENDM
После макровызова MACERR 3 получим:
ERR1: DB 'ERROR 1',0
ERR2: DB 'ERROR 2',0
ERR3: DB 'ERROR 3',0
TYPE оператор TYPE возвращает байт, который описывает
две характеристики аргумента: перемещаемость и яв-
ляется ли аргумент внешним (EXTRN) или нет. Аргу-
ментом для TYPE может быть любое выражение (стро-
ковое, числовое, логическое). Если выражение не
верно, то TYPE вернет ноль. Структура возвращаемого
байта следующая:
младшие два бита определяют перемещаемость аргу-
мента следующим образом:
0 абсолютный;
1 перемещаемый относительно кода;
2 перемещаемый относительно данных;
3 COMMON перемещаемый.
Старший бит (80h) - бит EXTRN. Когда выражение со-
держит внешний символ, то бит равен 1.
Бит определенности - (20h). Когда выражение опре-
делено, то этот бит равен 1. Если же выражение не
определено или содержит EXTRN, то этот бит равен 0.
TYPE обычно используют внутри макрокоманд, когда
необходимо проверить тип аргумента.
3. Руководство по эксплуатации компилятора M80
3.1. Обращение к компилятору. Входные и выходные данные
Исходными данными для компилятора является файл, содержа-
щий программу написанную на макроассемблере, и имеющий тип
ASM. В результате работы компилятор создает файл типа REL, со-
держащий модуль в перемещаемой форме. Кроме того, по желанию
пользователя может быть создан файл с листингом и файл перек-
рестных ссылок.
Запуск макроассемблера осуществляется следующей командой:
M80 "командная строка"
Формат командной строки:
"имя 1", "имя 2" ="имя 3"
где "имя 1" - имя файла, в который будет записан переме-
щаемый модуль;
"имя 2" - устройство, на которое будет выводится
листинг. Таким устройством может быть консоль (CON:),
принтер (PRN:) или файл на диске;
"имя 3" - имя файла, содержащего исходный текст про-
граммы.
Если "имя 1" и "имя 2" опущены, то по умолчанию берется
имя файла исходного текста. Тип файла в "имя 1" всегда REL, в
"имя 2" (если задан файл) всегда PRN, а в "имя 3" всегда ASM.
Если перемещаемый модуль и листинг не нужны, то слева от знака
равенства надо поставить запятую.
Примеры:
M80 =SOURSE.ASM транслировать программу SOURSE.ASM и
поместить объектный код в файл SOURSE.REL
M80 ,PRN:=TEST транслировать программу TEST.ASM и вывес-
ти листинг на устройство PRN (принтер);
M80 SMALL,CON:=TEST транслировать программу TEST.ASM, объект-
ный файл записать в SMALL.REL, а листинг
вывести на консоль.
3.2. Опции компиляции
В командной строке может быть задано несколько опций, ко-
торые будут влиять на формат выводимого листинга.
Опция Действие
----- --------
/L создать файл с листингом
/O печатать в листинге все адреса и т.п. в восьмерич-
ной системе счисления
/H печатать в листинге все адреса и т.п. в шестнадца-
тиричной системе счисления (действует по умолчанию)
/X подавить вывод листинга условий, значение которых
есть "ложь"
/R создать объектный файл (действует по умолчанию)
/P создать объектный файл (переполнение стека при
опции /R)
/C создать файл перекрестных ссылок
/M инициализация нулями псевдооператора(ов) "DS"
/I настроить ассемблер на мнемоники I8080
/Z настроить ассемблер на мнемоники Z80 (по-умолчанию)
Пример:
M80 =TEST/L/P оттранслировать файл TEST.ASM. Объектный
файл вывести в TEST.REL, а листинг в файл
TEST.LST.
3.3. Формат листинга
На каждой странице листинга первые две строки содержат:
[TITLE ТЕКСТ] MACRO PAGE X [-Y]
[SUBTITLE ТЕКСТ]
где TITLE ТЕКСТ - текст заданный псевдокомандой TITLE;
X - основной номер страницы. Он увеличивается только
при появлении из исходного файла символа подачи новой
страницы. Когда печатается таблица символов X=S;
Y - младший номер страницы. Он увеличивается при появ-
лении псевдокоманды PAGE или при заполнении текущей
страницы;
SUBTITLE ТЕКСТ- текст, заданный псевдокомандой SUBTITLE.
После вывода этих двух строк выводится одна пустая
строка, а затем очередная строка программы. Строка
программы имеет вид:
[CRF#] [ERROR] LOC#M !XX!XXXX! ..... исходный текст
Если выводится таблица перекрестных ссылок, то первый
элемент в строке - номер для таблицы, после него стоит символ
табуляции.
ERROR - это флаг ошибки, если в строке есть ошибка. Если
в стороке нет ошибки, то вместо ERROR стоит пробел. Если таб-
лица перекрестных ссылок не создается, то флаг ошибки стоит в
первой колонке.
LOG#M - значение счетчика адреса, которое в зависимости
от опций /H или /O, представляет собой 16-ричное число, содер-
жащее 4 цифры или 8-ричное число, содержащее 6 цифр. Символ
после числа - это индикатор перемещаемости:
' перемещаемый относительно кода;
" перемещаемый относительно данных;
! COMMON перемещаемый;
ПРОБЕЛ абсолютный;
* внешний.
Далее печатаются три пробела, после которых идет код ко-
манды и операндов (если они есть у данной команды). Если стро-
ка листинга появилась из файла, включенного по псевдокоманде
INCLUDE, то после кодов идет буква "C". Если строка содержит
макрорасширение (MACRO, REPT, IRP, IRPT), то после кодов стоит
знак "+". Остаток строки содержит исходный текст.
В конце листинга выводится таблица символических имен
(меток). Сначала в алфавитном порядке печатаются имена всех
макрокоманд, после этого выводятся все символические имена
программы. После каждого символического имени выводится знак
табуляции, а затем печатается значение символического имени.
Если имя типа PUBLIC, то после его значения печатается буква
I. Далее печатается один из следующих знаков:
U имя неопределено;
C имя блока COMMON;
* внешнее имя;
ПРОБЕЛ абсолютное имя;
' перемещаемый относительно кода;
" перемещаемый относительно данных;
! COMMON относительный.
3.4. Сообщения об ошибках
Сообщения об ошибках индицируются одной буквой (флагом) в
первой колонке листинга. Если файл с листингом не выводится на
консоль, то ошибочные строки все равно выводятся.
Флаг Значение
---- --------
A Ошибка в аргументе.
Неправильный формат аргумента псевдокоманды
или аргумент вне допустимых границ.
C Ошибка условного вложения.
ELSE без IF; ENDIF без IF; два ELSE на один IF.
D Двойное определение символического имени.
E Ошибка при использовании EXTRN.
Недопустимое использование символического име-
ни, объявленного EXTRN.
M Многократно определенное символическое имя.
N Ошибка в числе.
Неверное задание числа (например 8Q)
O Неверный код операции или ошибочный синтаксис
ENDM, LOCAL вне блока; ASET, EQU или MACRO без
имени; неверный синтаксис в коде команды; не-
верный синтаксис в выражении.
P Ошибка фазы.
Значение метки или имени в EQU изменилось при
втором проходе.
Q Вопрос.
Обычно означает, что строка окончена неверно.
Это предупреждение о возможной ошибке.
R Перемещение.
Недопустимое использование перемещения в выра-
жении.
U Символическое имя не определено.
V Ошибка значения.
При первом проходе псевдокоманда не может полу-
чить необходимого определенного значения. Если
символ, встретившийся в псевдокоманде, опреде-
лен ниже, то при втором проходе ошибка U выда-
ваться не будет.