Здесь показаны различия между двумя версиями данной страницы.
Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
msx:assembler_programming_guide-fakhrutdinov_bocharov:03 [2020-05-11 16:22] GreyWolf [3.1.2. Генерация текста с параметрами] |
msx:assembler_programming_guide-fakhrutdinov_bocharov:03 [2020-11-25 09:56] (текущий) GreyWolf |
||
---|---|---|---|
Строка 7: | Строка 7: | ||
До сих пор созданием текстов на языке ассемблера (программированием) занимались мы сами, а ассемблер транслировал их в программы на машинном языке. Однако большинство ассемблеров могут кроме этого по определенным правилам сами генерировать команды на языке ассемблера из команд условной генерации и макрокоманд, написанных программистом. | До сих пор созданием текстов на языке ассемблера (программированием) занимались мы сами, а ассемблер транслировал их в программы на машинном языке. Однако большинство ассемблеров могут кроме этого по определенным правилам сами генерировать команды на языке ассемблера из команд условной генерации и макрокоманд, написанных программистом. | ||
- | Такие ассемблеры называют макроассемблерами. К ним относится и макроассемблер M80. Процесс трансляции макроассемблером может состоять из двух этапов: | + | Такие ассемблеры называют макроассемблерами. К ним относится и макроассемблер [[msx:macro-80_assembler:macro-80_assembler|M80]]. Процесс трансляции макроассемблером может состоять из двух этапов: |
- анализ программы и генерация текста на языке ассемблера; | - анализ программы и генерация текста на языке ассемблера; | ||
- генерация программы в машинных кодах. | - генерация программы в машинных кодах. | ||
Строка 45: | Строка 45: | ||
</code> | </code> | ||
- | После трансляции макроассемблером M80 получим следующий листинг: | + | После трансляции макроассемблером [[msx:macro-80_assembler:macro-80_assembler|M80]] получим следующий листинг: |
<code> | <code> | ||
MSX.M-80 1.00 01-Apr-85 PAGE 1 | MSX.M-80 1.00 01-Apr-85 PAGE 1 | ||
Строка 100: | Строка 100: | ||
</code> | </code> | ||
- | Параметр — это любое допустимое имя языка ассемблера. Ассемблер M80 допускает имена, содержащие знак "$". Их удобно использовать для обозначения параметров. | + | Параметр — это любое допустимое имя языка ассемблера. Ассемблер [[msx:macro-80_assembler:macro-80_assembler|M80]] допускает имена, содержащие знак "$". Их удобно использовать для обозначения параметров. |
Команда IRP генерирует команды, каждый раз заменяя параметр в командах очередным значением из списка, а команда IRPC подставляет вместо параметра очередной символ строки. | Команда IRP генерирует команды, каждый раз заменяя параметр в командах очередным значением из списка, а команда IRPC подставляет вместо параметра очередной символ строки. | ||
Строка 116: | Строка 116: | ||
END | END | ||
</code> | </code> | ||
- | После трансляции M80 получим: | + | После трансляции [[msx:macro-80_assembler:macro-80_assembler|M80]] получим: |
<code> | <code> | ||
MSX.M-80 1.00 01-Apr-85 PAGE 1 | MSX.M-80 1.00 01-Apr-85 PAGE 1 | ||
Строка 158: | Строка 158: | ||
==== 3.1.3. Условная генерация ==== | ==== 3.1.3. Условная генерация ==== | ||
- | Условная генерация — генерация в зависимости от некоторых условий различающихся или различных последовательностей команд ассемблера. Для условной генерации в системе DUAD и в M80 используются конструкции вида: | + | Условная генерация — генерация в зависимости от некоторых условий различающихся или различных последовательностей команд ассемблера. Для условной генерации в системе [[msx:duad:duad|]] и в [[msx:macro-80_assembler:macro-80_assembler|M80]] используются конструкции вида: |
<code> | <code> | ||
IF условие IF условие | IF условие IF условие | ||
Строка 166: | Строка 166: | ||
ENDIF | ENDIF | ||
</code> | </code> | ||
- | Команды-ассемблера-1 генерируются, если условие истинно, команды-ассемблера-2 генерируются, если условие ложно. | + | ''Команды-ассемблера-1'' генерируются, если условие истинно, ''команды-ассемблера-2'' генерируются, если условие ложно. |
Команды условной генерации применяются обычно, когда одна и та же исходная программа должна быть настраиваемой на различные условия эксплуатации. Изменив несколько строк в начале программы и перетранслировав её, можно получить объектный код, рассчитанный например, на другой тип машины или другую её конфигурацию. | Команды условной генерации применяются обычно, когда одна и та же исходная программа должна быть настраиваемой на различные условия эксплуатации. Изменив несколько строк в начале программы и перетранслировав её, можно получить объектный код, рассчитанный например, на другой тип машины или другую её конфигурацию. | ||
Строка 193: | Строка 193: | ||
</code> | </code> | ||
- | После трансляции ассемблером DUAD получим следующий листинг: | + | После трансляции ассемблером [[msx:duad:duad|]] получим следующий листинг: |
<code> | <code> | ||
Z80-Assembler Page: 1 | Z80-Assembler Page: 1 | ||
Строка 218: | Строка 218: | ||
</code> | </code> | ||
- | Обратите внимание, что код, соответствующий MSX, не генерировался. Ниже приведен пример трансляции ассемблером M80 для других условий. Сгенерировано всего 6 байт. | + | Обратите внимание, что код, соответствующий MSX, не генерировался. Ниже приведен пример трансляции ассемблером [[msx:macro-80_assembler:macro-80_assembler|M80]] для других условий. Сгенерировано всего 6 байт. |
<code> | <code> | ||
MSX.M-80 1.00 01-Apr-85 PAGE 1 | MSX.M-80 1.00 01-Apr-85 PAGE 1 | ||
Строка 245: | Строка 245: | ||
</code> | </code> | ||
- | Для команд условной генерации обычно не допускается вложенность одного оператора IF в другой. Если же вложенность макроассемблером допускается, ELSE отвечает ближайшему IF, не имеющему ELSE. | + | Для команд условной генерации обычно не допускается вложенность одного оператора ''IF'' в другой. Если же вложенность макроассемблером допускается, ''ELSE'' отвечает ближайшему ''IF'', не имеющему ''ELSE''. |
{{anchor:n32}} | {{anchor:n32}} | ||
Строка 254: | Строка 254: | ||
Однако адрес может быть как абсолютным, так и заданным относительно данных, кодов или общей памяти. Относительный адрес задает смещение к абсолютному стартовому адресу. | Однако адрес может быть как абсолютным, так и заданным относительно данных, кодов или общей памяти. Относительный адрес задает смещение к абсолютному стартовому адресу. | ||
- | Тип адресации задается директивами ассемблеру — ASEG, CSEG, DSEG, COMMON. | + | Тип адресации задается директивами ассемблеру — ''ASEG'', ''CSEG'', ''DSEG'', ''COMMON''. |
==== Определение абсолютного сегмента ==== | ==== Определение абсолютного сегмента ==== | ||
- | Директива ASEG задает абсолютный режим адресации. При этом генерируются абсолютные коды, жестко привязанные к одному участку памяти. | + | Директива ''ASEG'' задает абсолютный режим адресации. При этом генерируются абсолютные коды, жестко привязанные к одному участку памяти. |
- | После директивы ASEG директива ORG должна использоваться с аргументом 103h или больше, причем она задаёт абсолютный адрес трансляции. | + | После директивы ''ASEG'' директива ''ORG'' должна использоваться с аргументом 103h или больше, причем она задаёт абсолютный адрес трансляции. |
==== Определение сегмента относительно кодов ==== | ==== Определение сегмента относительно кодов ==== | ||
Строка 277: | Строка 277: | ||
==== Определение сегмента относительно данных ==== | ==== Определение сегмента относительно данных ==== | ||
- | Для задания этого режима адресации используется директива DSEG. Признаком этого режима трансляции являются двойные кавычки после адреса (%% " %%). | + | Для задания этого режима адресации используется директива ''DSEG''. Признаком этого режима трансляции являются двойные кавычки после адреса (%% " %%). |
- | Как и в режиме CSEG, устанавливается то значение счетчика адреса, которое было последним в режиме DSEG, а директива ORG задает относительное смещение адреса. | + | Как и в режиме ''CSEG'', устанавливается то значение счетчика адреса, которое было последним в режиме ''DSEG'', а директива ''ORG'' задает относительное смещение адреса. |
- | Для установки абсолютного адреса в сборщике используется ключ /D. | + | Для установки абсолютного адреса в сборщике используется ключ ''/D''. |
==== Определение блока общей области ==== | ==== Определение блока общей области ==== | ||
Строка 303: | Строка 303: | ||
Ниже приводится пример программы, использующей некоторые директивы управления адресами. Эта программа работает посредством обработки прерываний от таймера (60 раз в секунду). Напомним, что по этому прерыванию центральный процессор выполняет подпрограмму обработки прерывания, находящуюся по адресу 0038h. | Ниже приводится пример программы, использующей некоторые директивы управления адресами. Эта программа работает посредством обработки прерываний от таймера (60 раз в секунду). Напомним, что по этому прерыванию центральный процессор выполняет подпрограмму обработки прерывания, находящуюся по адресу 0038h. | ||
- | Как и любая другая подпрограмма обработки прерывания, она начинается с сохранения регистров (путем засылки их в стек), затем вызывается ловушка этого прерывания (0FD9Ah), в которой вначале находится команда возврата (RET). | + | Как и любая другая подпрограмма обработки прерывания, она начинается с сохранения регистров (путем засылки их в стек), затем вызывается ловушка этого прерывания (0FD9Ah), в которой вначале находится команда возврата (''RET''). |
- | При инициализации наша программа перемещает свой код в область, начиная с адреса 4000h (которая интерпретатором языка BASIC не используется) и через ловушку прерывания устанавливает | + | При инициализации наша программа перемещает свой код в область, начиная с адреса 4000h (которая интерпретатором языка [[msx:basic:|]] не используется) и через ловушку прерывания устанавливает |
точку входа. | точку входа. | ||
- | Суть самой программы заключается в том, что она два раза в секунду печатает системное время в правом верхнем углу экрана (SCREEN 0, WIDTH 80). Мы уже сказали, что используемое прерывание происходит 60 раз в секунду (во всей доступной авторам литературе указывается число 50), т.е. каждый тридцатый вызов этого прерывания указывает на то, что прошло 1/2 секунды. | + | Суть самой программы заключается в том, что она два раза в секунду печатает системное время в правом верхнем углу экрана (''SCREEN 0'', ''WIDTH 80''). Мы уже сказали, что используемое прерывание происходит 60 раз в секунду (во всей доступной авторам литературе указывается число 50), т.е. каждый тридцатый вызов этого прерывания указывает на то, что прошло 1/2 секунды. |
Наша программа имеет счетчик, который увеличивается при каждом вызове подпрограммы обработки прерывания (поскольку сначала выполняется наша подпрограмма, а затем уже подпрограмма обработки прерывания), и если этот счетчик получает значение 29, то он обнуляется и выводится новое время. | Наша программа имеет счетчик, который увеличивается при каждом вызове подпрограммы обработки прерывания (поскольку сначала выполняется наша подпрограмма, а затем уже подпрограмма обработки прерывания), и если этот счетчик получает значение 29, то он обнуляется и выводится новое время. | ||
Строка 478: | Строка 478: | ||
RET | RET | ||
END | END | ||
- | <code> | + | </code> |
- | После его трансляции M80 получим: | + | После его трансляции [[msx:macro-80_assembler:macro-80_assembler|M80]] получим: |
<code> | <code> | ||
MSX.M-80 1.00 01-Apr-85 PAGE 1 | MSX.M-80 1.00 01-Apr-85 PAGE 1 | ||
Строка 589: | Строка 589: | ||
==== Дополнительные возможности макрокоманд ==== | ==== Дополнительные возможности макрокоманд ==== | ||
- | Во время компиляции можно использовать так называемые переменные времени компиляции. Для присваивания значения такой переменной используется директива SET: | + | Во время компиляции можно использовать так называемые переменные времени компиляции. Для присваивания значения такой переменной используется директива ''SET'': |
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
<code> | <code> | ||
- | имя SET выражение. | + | имя SET выражение |
</code> | </code> | ||
+ | </WRAP> | ||
+ | |||
+ | <WRAP half column> | ||
+ | . | ||
+ | </WRAP> | ||
+ | </WRAP> | ||
+ | |||
Для управления печатью листинга макроассемблера можно использовать директивы: | Для управления печатью листинга макроассемблера можно использовать директивы: | ||
- | * LALL — выводит полный текст макрорасширения; | + | * ''LALL'' — выводит полный текст макрорасширения; |
- | * SALL — только объектный код расширения без текста; | + | * ''SALL'' — только объектный код расширения без текста; |
- | * XALL — выводит те строки, которые генерируют текст. | + | * ''XALL'' — выводит те строки, которые генерируют текст. |
Операции: | Операции: | ||
- | * & — связывание метки и параметра, например, ERROR&X; | + | * & — связывание метки и параметра, например, ''ERROR&X''; |
* ;; — макрокомментарий; | * ;; — макрокомментарий; | ||
* ! — означает, что за ним — литерал. Например, "!;" означает символ точка с запятой. | * ! — означает, что за ним — литерал. Например, "!;" означает символ точка с запятой. | ||
- | * % — преобразование выражения в число. Например, %X+Y. | + | * % — преобразование выражения в число. Например, %X+Y'. |
Строка 612: | Строка 621: | ||
Желаем Вам успехов в программировании и надеемся, что эта книга предоставила Вам ответы на многие вопросы, касающиеся системы MSX-2. Авторы будут благодарны за все замечания и предложения по содержанию книги. | Желаем Вам успехов в программировании и надеемся, что эта книга предоставила Вам ответы на многие вопросы, касающиеся системы MSX-2. Авторы будут благодарны за все замечания и предложения по содержанию книги. | ||
- | |||
---- | ---- | ||
Строка 619: | Строка 627: | ||
- | {{tag>MSX assembler Programming Book_apguidefb on_github}} | + | {{tag>MSX Book_apguidefb on_github}} |