Здесь показаны различия между двумя версиями данной страницы.
Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
msx:basic_dialogue_programming_language:101 [2023-02-11 21:09] GreyWolf [Примеры] |
msx:basic_dialogue_programming_language:101 [2023-06-11 23:58] (текущий) GreyWolf [1.1. Связь программы на MSX BASIC с подпрограммами в машинных кодах] |
||
---|---|---|---|
Строка 4: | Строка 4: | ||
{{anchor:n101}} | {{anchor:n101}} | ||
====== Приложение 1. MSX BASIC и машинный язык ====== | ====== Приложение 1. MSX BASIC и машинный язык ====== | ||
- | FIXME | ||
<WRAP group 99%> | <WRAP group 99%> | ||
<WRAP half column> \\ </WRAP> | <WRAP half column> \\ </WRAP> | ||
- | <WRAP half column><WRAP justify> | + | <WRAP half column><WRAP right> |
Покажите, как операторы языка ассемблера можно | Покажите, как операторы языка ассемблера можно | ||
\\ чередовать с операторами данного языка. | \\ чередовать с операторами данного языка. | ||
Строка 22: | Строка 21: | ||
- | Перед выполнением оператора [[msx:basic:|]] выполняется проверка его правильности,и в случае обнаружения ошибок на экран выводятся сообщения. Выполнимый оператор сначала преобразуется в последовательность команд,которые может "понять" процессор. Эти подпрограммы заранее помещены в ROM на этапе изготовления компьютера. | + | Перед выполнением оператора [[msx:basic:|]] выполняется проверка его правильности,и в случае обнаружения ошибок на экран выводятся сообщения. Выполнимый оператор сначала преобразуется в последовательность команд,которые может "понять" процессор. Эти подпрограммы заранее помещены в ROM на этапе изготовления компьютера. |
- | Интерпретация операторов [[msx:basic:|]] занимает определенное время; в некоторых случаях, однако, это время должно быть сокращено (например, для игровых программ). Это можно сделать двумя способами: | + | Интерпретация операторов [[msx:basic:|]] занимает определенное время; в некоторых случаях, однако, это время должно быть сокращено (например, для игровых программ). Это можно сделать двумя способами: |
- | - основная программа пишется на [[msx:basic:|]], а в ситуациях, когда интерпретатор [[msx:basic:|]] не обеспечивает нужного быстродействия, используются подпрограммы, написанные в машинных кодах; | + | - основная программа пишется на [[msx:basic:|]], а в ситуациях, когда интерпретатор [[msx:basic:|]] не обеспечивает нужного быстродействия, используются подпрограммы, написанные в машинных кодах; |
- вся программа пишется на машинном языке. | - вся программа пишется на машинном языке. | ||
- | + | ||
- | Отметим, что существует обширная литература по этому кругу проблем, и читатель, овладевший языком [[msx:basic:|]] и желающий научиться хорошо программировать на машинном языке, может обратиться к этой литературе [ [[bibliography#b45|[45]]], [[bibliography#b66|[66]]], [[bibliography#b67|[67]]] ]. | + | Отметим, что существует обширная литература по этому кругу проблем, и читатель, овладевший языком [[msx:basic:|]] и желающий научиться хорошо программировать на машинном языке, может обратиться к этой литературе [ [[bibliography#b45|[45]]], [[bibliography#b66|[66]]], [[bibliography#b67|[67]]] ]. |
- | Для обращения к подпрограммам в машинных кодах из программ на языке [[msx:basic:|]] используются оператор ''[[#DEFUSR]]'' и функция ''[[#USR]]''. | + | Для обращения к подпрограммам в машинных кодах из программ на языке [[msx:basic:|]] используются оператор ''[[#DEFUSR]]'' и функция ''[[#USR]]''. |
- | {{anchor:usr}} | + | {{anchor:def_usr}} |
Оператор ''DEFUSR'' определяет начальный адрес машинной подпрограммы. | Оператор ''DEFUSR'' определяет начальный адрес машинной подпрограммы. | ||
Строка 47: | Строка 46: | ||
</WRAP> | </WRAP> | ||
</WRAP> | </WRAP> | ||
- | где: | + | где: |
* DEFUSR("DEFine USing Routine"-"определить используемую подпрограмму") — служебные слова; | * DEFUSR("DEFine USing Routine"-"определить используемую подпрограмму") — служебные слова; | ||
* ''n'' — целое число,принадлежащее [0,9] и указывающее номер подпрограммы (по умолчанию значение n равно 0); | * ''n'' — целое число,принадлежащее [0,9] и указывающее номер подпрограммы (по умолчанию значение n равно 0); | ||
* ''адрес'' — арифметическое выражение, целая часть значения которого определяет начальный адрес подпрограммы. | * ''адрес'' — арифметическое выражение, целая часть значения которого определяет начальный адрес подпрограммы. | ||
- | Таким образом, в программе на языке [[msx:basic:|]] может использоваться до //десяти// подпрограмм в машинных кодах одновременно.Они различаются по номеру (от 0 до 9), который записываются вслед за служебным словом ''DEFUSR''. | + | Таким образом, в программе на языке [[msx:basic:|]] может использоваться до //десяти// подпрограмм в машинных кодах одновременно.Они различаются по номеру (от 0 до 9), который записываются вслед за служебным словом ''DEFUSR''. |
Например, оператор ''DEFUSR1=&HA000'' указывает, что начальным адресом программы с номером 1 является &HA000 . | Например, оператор ''DEFUSR1=&HA000'' указывает, что начальным адресом программы с номером 1 является &HA000 . | ||
- | {{anchor:defusr}} {{anchor:def_usr}} | + | {{anchor:usr}} |
Функция | Функция | ||
Строка 70: | Строка 69: | ||
</WRAP> | </WRAP> | ||
</WRAP> | </WRAP> | ||
- | где: | + | где: |
* ''USR'' ("USer"-"пользователь") — служебное слово; | * ''USR'' ("USer"-"пользователь") — служебное слово; | ||
* ''n'' — десятичная цифра (0,1,2,3,4,5,6,7,8,9), причем по умолчанию n=0; | * ''n'' — десятичная цифра (0,1,2,3,4,5,6,7,8,9), причем по умолчанию n=0; | ||
* ''α'' — арифметическое или строковое выражение (которое, кстати,может отсутствовать), позволяет //выполнить// подпрограмму, написанную на машинном языке. | * ''α'' — арифметическое или строковое выражение (которое, кстати,может отсутствовать), позволяет //выполнить// подпрограмму, написанную на машинном языке. | ||
- | {{anchor:e10101-01}} __//Пример 1//__. | + | {{anchor:e10101-00}} __//Пример 1//__. |
- | \\ Пусть, например, одна машинная подпрограмма начинается с адреса &HD000, а другая - с адреса &HD100 : | + | \\ Пусть, например, одна машинная подпрограмма начинается с адреса &HD000, а другая - с адреса &HD100 : |
<code> | <code> | ||
DEFUSR0=&HD000:DEFUSR1=&HD100 | DEFUSR0=&HD000:DEFUSR1=&HD100 | ||
Строка 94: | Строка 93: | ||
Если аргументом функции ''USR'' является //нуль// , то в подпрограмму в машинных кодах ничего не передается! | Если аргументом функции ''USR'' является //нуль// , то в подпрограмму в машинных кодах ничего не передается! | ||
- | Отметим, что значение, возвращаемое функцией ''USR'', представляет собой значение ее аргумента. | + | Отметим, что значение, возвращаемое функцией ''USR'', представляет собой значение ее аргумента. |
- | Если α — арифметическое выражение, то адрес его значения хранится в регистре HL . | + | Если α — арифметическое выражение, то адрес его значения хранится в регистре HL . |
- | Если же α — строковое выражение, то ссылка на адрес, по которому хранится значение α, содержится в регистре DE. | + | Если же α — строковое выражение, то ссылка на адрес, по которому хранится значение α, содержится в регистре DE. |
Ниже мы расскажем Вам и о других способах передачи аргументов машинным подпрограммам. | Ниже мы расскажем Вам и о других способах передачи аргументов машинным подпрограммам. | ||
- | ===== Примеры ===== | + | **Примеры** |
<WRAP group 99%> | <WRAP group 99%> | ||
<WRAP half column> \\ </WRAP> | <WRAP half column> \\ </WRAP> | ||
- | <WRAP half column><WRAP justify> | + | <WRAP half column><WRAP right> |
Некоторые люди учатся читая, другие - делая. | Некоторые люди учатся читая, другие - делая. | ||
\\ Преуспевающие делают и то, и другое. | \\ Преуспевающие делают и то, и другое. | ||
Строка 116: | Строка 115: | ||
<WRAP group 99%> | <WRAP group 99%> | ||
<WRAP half column> \\ </WRAP> | <WRAP half column> \\ </WRAP> | ||
- | <WRAP half column><WRAP justify> | + | <WRAP half column><WRAP right> |
Примеры, немногочисленные, лаконичные, приведенные | Примеры, немногочисленные, лаконичные, приведенные | ||
- | \\ к месту, сообщают рассуждению блеск,глубину и | + | \\ к месту, сообщают рассуждению блеск,глубину и |
- | \\ убедительность, но оно становится невразумительным, | + | \\ убедительность, но оно становится невразумительным, |
- | \\ если примеров и подробностей чересчур много... | + | \\ если примеров и подробностей чересчур много... |
<WRAP rightalign> | <WRAP rightalign> | ||
—//Л.К.де Вовенарг. Размышления и максимы// | —//Л.К.де Вовенарг. Размышления и максимы// | ||
Строка 167: | Строка 166: | ||
- | {{anchor:e10101-03}} __//Пример 3//__. Загрузка содержимого регистра A в память по адресу, указанному в регистре BC. | + | {{anchor:e10101-03}} __//Пример 3//__. Загрузка содержимого регистра A в память по адресу, указанному в регистре BC. |
\\ {{.examples:10101-03.bas|}} \\ [[+tab|wmsxbpge>10101-03.bas]] | \\ {{.examples:10101-03.bas|}} \\ [[+tab|wmsxbpge>10101-03.bas]] | ||
<code> | <code> | ||
Строка 184: | Строка 183: | ||
</code> | </code> | ||
- | {{anchor:e10101-04}} __//Пример 4//__. Проиллюстрируем работу команды EX DE, HL. | + | {{anchor:e10101-04}} __//Пример 4//__. Проиллюстрируем работу команды EX DE, HL. |
\\ {{.examples:10101-04.bas|}} \\ [[+tab|wmsxbpge>10101-04.bas]] | \\ {{.examples:10101-04.bas|}} \\ [[+tab|wmsxbpge>10101-04.bas]] | ||
<code> | <code> | ||
Строка 301: | Строка 300: | ||
</code> | </code> | ||
+ | Напомним, что подрограмма в машинных кодах вызывается следующим образом: | ||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
<code> | <code> | ||
- | Напомним, что подрограмма в машинных кодах вызывается следующим обра- | + | Переменная = USR[n](аргумент) |
- | зом: ┌────────────────────────────────────────────────┐ | + | |
- | │ П е р е м е н н а я = USR[n](а р г у м е н т) │ , | + | |
- | └────────────────────────────────────────────────┘ | + | |
- | где n - целое число, принадлежащее отрезку [0,9], которое указывает но- | + | |
- | мер подпрограммы в машинных кодах. | + | |
- | Значение а р г у м е н т а передается подпрограмме в машинных кодах. | + | |
- | При вызове подпрограммы число байтов, занимаемое этим значением, однознач- | + | |
- | но связанное с его типом, заносится в регистр A микропроцессора Z80 и в | + | |
- | ячейку памяти F663h. Возможны следующие значения: | + | |
- | 2 - целочисленные, | + | |
- | 4 - вещественные с одинарной точностью, | + | |
- | 8 - вещественные с двойной точностью, | + | |
- | 3 - строковые. | + | |
- | Адрес числовой п е р е м е н н о й хранится в регистре HL; | + | |
- | адрес строковой п е р е м е н н о й находится в регистре DE. | + | |
</code> | </code> | ||
+ | |||
+ | </WRAP> | ||
+ | , | ||
+ | <WRAP half column> | ||
+ | |||
+ | </WRAP> | ||
+ | </WRAP> | ||
+ | где | ||
+ | * n — целое число, принадлежащее отрезку [0,9], которое указывает номер подпрограммы в машинных кодах. | ||
+ | |||
+ | Значение //аргумента// передается подпрограмме в машинных кодах. | ||
+ | При вызове подпрограммы число байтов, занимаемое этим значением, однозначно связанное с его типом, заносится в регистр A микропроцессора Z80 и в ячейку памяти F663h. Возможны следующие значения: | ||
+ | * 2 — целочисленные, | ||
+ | * 4 — вещественные с одинарной точностью, | ||
+ | * 8 — вещественные с двойной точностью, | ||
+ | * 3 — строковые. | ||
+ | Адрес числовой //переменной// хранится в регистре HL; адрес строковой //переменной// находится в регистре DE. | ||
{{anchor:e10101-09}} __//Пример 9//__. Нахождение большего из двух чисел. | {{anchor:e10101-09}} __//Пример 9//__. Нахождение большего из двух чисел. | ||
Строка 344: | Строка 347: | ||
Это есть адрес аргумента функции USR | Это есть адрес аргумента функции USR | ||
Проверяем этот факт:... и вправду 6 | Проверяем этот факт:... и вправду 6 | ||
- | Результат работы подпрограммы в машинных кодах: 12 | + | Результат работы подпрограммы в машинных кодах: 12 |
Ok | Ok | ||
</code> | </code> | ||
Строка 376: | Строка 379: | ||
Ok | Ok | ||
</code> | </code> | ||
- | Итак, информация о типе переменной A$ хранится в ячейке с адресом &HF663 , а ссылка на адрес переменной A$ (&H8183) хранится в регистре DE. | + | Итак, информация о типе переменной A$ хранится в ячейке с адресом &HF663, а ссылка на адрес переменной A$ (&H8183) хранится в регистре DE. |
- | + | ||
- | Если вы не тот, кто наверху, значит, | + | |
- | вы тот, кто внизу. | + | |
- | С.Поттер | + | |
+ | <WRAP group 99%> | ||
+ | <WRAP half column> \\ </WRAP> | ||
+ | <WRAP half column><WRAP right> | ||
+ | Если вы не тот, кто наверху, значит, | ||
+ | \\ вы тот, кто внизу. | ||
+ | <WRAP rightalign> | ||
+ | —//С.Поттер// | ||
+ | </WRAP></WRAP> | ||
+ | </WRAP></WRAP> | ||
- | {{anchor:e10101-11}} __//Пример 11//__. Сортировка целочисленного массива , содержащего 5 элементов. | + | {{anchor:e10101-11}} __//Пример 11//__. Сортировка целочисленного массива , содержащего 5 элементов. |
\\ {{.examples:10101-11.bas|}} \\ [[+tab|wmsxbpge>10101-11.bas]] | \\ {{.examples:10101-11.bas|}} \\ [[+tab|wmsxbpge>10101-11.bas]] | ||
<code> | <code> | ||
Строка 421: | Строка 429: | ||
40 IF F=0 OR F=1 THEN POKE &HC003,1:GOTO 90 | 40 IF F=0 OR F=1 THEN POKE &HC003,1:GOTO 90 | ||
50 CLEAR 200,&HD000:DEFUSR=&HD000:I=&HD000 | 50 CLEAR 200,&HD000:DEFUSR=&HD000:I=&HD000 | ||
- | 60 READ A$:IF A$="z" THEN 80 | + | 60 READ A$:IF A$="z" THEN 80 |
70 POKE I,VAL("&h"+A$):I=I+1:GOTO 60 | 70 POKE I,VAL("&h"+A$):I=I+1:GOTO 60 | ||
80 A=USR(0) | 80 A=USR(0) | ||
- | 90 PRINT "Факториал "PEEK(&HC000)"=" PEEK(&HC003):END | + | 90 PRINT "Факториал "PEEK(&HC000)"=" PEEK(&HC003):END |
- | 100 DATA 3A,00,C0 :'LD A,(C000h) | + | 100 DATA 3A,00,C0 :'LD A,(C000h) |
110 DATA FE,02 :'CP 2h | 110 DATA FE,02 :'CP 2h | ||
- | 120 DATA 28,0A :'JR Z,$+12 ───────────┐ | + | 120 DATA 28,0A :'JR Z,$+12 ───────────┐ |
130 DATA 47 :'LD B,A │ | 130 DATA 47 :'LD B,A │ | ||
140 DATA 05 :'DEC B │ | 140 DATA 05 :'DEC B │ | ||
Строка 434: | Строка 442: | ||
170 DATA 57 :'LD D,A │ │ | 170 DATA 57 :'LD D,A │ │ | ||
180 DATA 82 :'ADD A,D ◀────┐ │ │ | 180 DATA 82 :'ADD A,D ◀────┐ │ │ | ||
- | 190 DATA 10,FD :'DJNZ $-1h ────┘ │ │ | + | 190 DATA 10,FD :'DJNZ $-1h ────┘ │ │ |
- | 200 DATA 41 :'LD B,C │ │ | + | 200 DATA 41 :'LD B,C │ │ |
- | 210 DATA 10,F8 :'DJNZ $-6h ───────┘ │ | + | 210 DATA 10,F8 :'DJNZ $-6h ───────┘ │ |
- | 220 DATA 32,03,C0 :'LD (C003h),A ◀───────┘ | + | 220 DATA 32,03,C0 :'LD (C003h),A ◀───────┘ |
230 DATA C9,"z" :'RET | 230 DATA C9,"z" :'RET | ||
</code> | </code> | ||
Строка 459: | Строка 467: | ||
в исходное состояние | в исходное состояние | ||
160 DATA CB,39 :' MLOOP:SRL C ; Сдвиг множителя вправо | 160 DATA CB,39 :' MLOOP:SRL C ; Сдвиг множителя вправо | ||
- | 170 DATA 1F :' RRA ; Наименее значащий разряд к переносу | + | 170 DATA 1F :' RRA ; Наименее значащий разряд к переносу |
- | 180 DATA 30,01 :' JR NC,NOADD-S; Если нет переноса, то | + | 180 DATA 30,01 :' JR NC,NOADD-S; Если нет переноса, то |
пропуск суммирования | пропуск суммирования | ||
- | 190 DATA 19 :' ADD HL,DE ; Иначе суммирование мно- | + | 190 DATA 19 :' ADD HL,DE ; Иначе суммирование мно- |
жимого в частичный результат | жимого в частичный результат | ||
200 DATA EB :' NOADD:EX DE,HL ; Сдвиг множимого влево | 200 DATA EB :' NOADD:EX DE,HL ; Сдвиг множимого влево | ||
Строка 478: | Строка 486: | ||
</code> | </code> | ||
- | |||
- | FIXME DELETEME <hidden Временный вариант> | ||
- | |||
- | |||
- | [[bibliography#b101|[101]]] | ||
- | \\ [ [[msx:msx2_technical_handbook:msx2_technical_handbook|]]: {{msx:msx2_technical_handbook:th-2.txt}} ] | ||
- | * 4.1 USR Function | ||
- | * 4.2 Data Exchange by the Argument and Return Value of USR Function | ||
- | * 4.3 Making New Commands | ||
- | |||
- | [[bibliography#b96|[96]]] ⇒ [[msx:assembler_programming_guide-fakhrutdinov_bocharov:01#n15|Программирование на языке ассемблера в системе MSX-2 — Организация связей с программами на языке MSX BASIC]] | ||
- | |||
- | |||
- | **DEF USR** | ||
- | |||
- | FIXME | ||
- | |||
- | Оператор ''DEF USR'' определяет начальный адрес программы в машинных кодах для последующего использования. Можно использовать до 10 различных программ. Программы нумеруются от 0 до 9. По умолчанию берётся значение 0. | ||
- | |||
- | Синтаксис: | ||
- | <WRAP group> | ||
- | <WRAP half column> | ||
- | <code> | ||
- | DEF USR номер = адрес | ||
- | </code> | ||
- | |||
- | </WRAP> | ||
- | , | ||
- | <WRAP half column> | ||
- | |||
- | </WRAP> | ||
- | </WRAP> | ||
- | где | ||
- | * //номер// — номер программы в машинных кодах, может находиться в диапазоне от 0 до 9. Если не указано, то 0 | ||
- | * //адрес// — начальный адрес подпрограммы на в машинных кодах | ||
- | |||
- | |||
- | __//Пример//__: | ||
- | |||
- | <code> | ||
- | DEF USR 1 = &HA000 | ||
- | </code> | ||
- | В этом примере указано, что начальным адресом подпрограммы с номером 1 является &HA000. | ||
- | |||
- | |||
- | **USR()** | ||
- | |||
- | FIXME | ||
- | |||
- | Функция ''USR()'' передает переменную в подпрограмму на машинном языке. Сначала необходимо определить расположение подпрограммы с помощью [[#DEF USR]]. | ||
- | |||
- | Синтаксис: | ||
- | <WRAP group> | ||
- | <WRAP half column> | ||
- | |||
- | <code> | ||
- | USR [номер подпрограммы](аргумент) | ||
- | </code> | ||
- | </WRAP> | ||
- | , | ||
- | <WRAP half column> | ||
- | |||
- | </WRAP> | ||
- | </WRAP> | ||
- | где | ||
- | * //номер// — номер подпрограммы число в диапазоне от 0 до 9, если не указано то 0 | ||
- | * //аргумент// — имя переменной, или строка может быть получена машинной подпрограммой, если аргументом является 0 (нуль), в программу в машинных кодах ничего не переносится | ||
- | |||
- | Значение переменной передается подпрограмме в машинных кодах. При вызове программы число байтов, занимаемое этим значением, однозначно связанное с его типом, заносится в регистр А микропроцессора [[zilog_z80:zilog_z80|Z80]] и в ячейку памяти [[msx:assembler_programming_guide-fakhrutdinov_bocharov:02#valtyp|VALTYP]]. | ||
- | |||
- | Адрес переменной хранится в регистре HL. | ||
- | |||
- | Для строк имеется небольшое отличие. Адрес, где записана строка, находится в регистре DE. | ||
- | |||
- | </hidden> | ||
---- | ---- |