Инструменты пользователя

Инструменты сайта


msx:basic_dialogue_programming_language:101

Это старая версия документа!


Первая страницаПредыдущая страницаНазад к обзоруСледующая страницаПоследняя страница

Приложение 1. MSX BASIC и машинный язык

FIXME


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

Д.Уолш. Руководство по созданию документации
для математического обеспечения

1.1. Связь программы на MSX BASIC с подпрограммами в машинных кодах

FIXME

Перед выполнением оператора MSX BASIC выполняется проверка его правильности,и в случае обнаружения ошибок на экран выводятся сообщения. Выполнимый оператор сначала преобразуется в последовательность команд,которые может «понять» процессор. Эти подпрограммы заранее помещены в ROM на этапе изготовления компьютера.

Интерпретация операторов MSX BASIC занимает определенное время; в некоторых случаях, однако, это время должно быть сокращено (например, для игровых программ). Это можно сделать двумя способами:

  1. основная программа пишется на MSX BASIC, а в ситуациях, когда интерпретатор MSX BASIC не обеспечивает нужного быстродействия, используются подпрограммы, написанные в машинных кодах;
  2. вся программа пишется на машинном языке.

Отметим, что существует обширная литература по этому кругу проблем, и читатель, овладевший языком MSX BASIC и желающий научиться хорошо программировать на машинном языке, может обратиться к этой литературе [ [45], [66], [67] ].

Для обращения к подпрограммам в машинных кодах из программ на языке MSX BASIC используются оператор DEFUSR и функция USR.

Оператор DEFUSR определяет начальный адрес машинной подпрограммы.

Синтаксис оператора:

DEFUSR[n] = адрес

,

где:

  • DEFUSR(«DEFine USing Routine«-»определить используемую подпрограмму») — служебные слова;
  • n — целое число,принадлежащее [0,9] и указывающее номер подпрограммы (по умолчанию значение n равно 0);
  • адрес — арифметическое выражение, целая часть значения которого определяет начальный адрес подпрограммы.

Таким образом, в программе на языке MSX BASIC может использоваться до десяти подпрограмм в машинных кодах одновременно.Они различаются по номеру (от 0 до 9), который записываются вслед за служебным словом DEFUSR.

Например, оператор DEFUSR1=&HA000 указывает, что начальным адресом программы с номером 1 является &HA000 .

Функция

USR[n](α)

,

где:

  • USR («USer«-»пользователь») — служебное слово;
  • n — десятичная цифра (0,1,2,3,4,5,6,7,8,9), причем по умолчанию n=0;
  • α — арифметическое или строковое выражение (которое, кстати,может отсутствовать), позволяет выполнить подпрограмму, написанную на машинном языке.

Пример 1.
Пусть, например, одна машинная подпрограмма начинается с адреса &HD000, а другая - с адреса &HD100 :

DEFUSR0=&HD000:DEFUSR1=&HD100

Теперь выполнить эти подпрограммы можно при помощи операторов:

A=USR0(A):A=USR1(A)

Значение выражения α передается подпрограмме, написанной в машинных кодах. При вызове подпрограммы число байтов,занимаемое этим значением, заносится в регистр A микропроцессора Z80 и в ячейку памяти с адресом &HF663 .

Содержимое регистра А Тип значения выражения α
2 Целочисленный
4 Вещественный с одинарной точностью
8 Вещественный с двойной точностью
3 Строковый

Если аргументом функции USR является нуль , то в подпрограмму в машинных кодах ничего не передается!

Отметим, что значение, возвращаемое функцией USR, представляет собой значение ее аргумента.

Если α — арифметическое выражение, то адрес его значения хранится в регистре HL .

Если же α — строковое выражение, то ссылка на адрес, по которому хранится значение α, содержится в регистре DE.

Ниже мы расскажем Вам и о других способах передачи аргументов машинным подпрограммам.

Примеры


Некоторые люди учатся читая, другие - делая.
Преуспевающие делают и то, и другое.

П.Браун


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

Л.К.де Вовенарг. Размышления и максимы

Пример 1. Загрузка регистров A и BC константами.
10101-01_.bas
10101-01}.bas

10 CLEAR 200,&HD000:DEFUSR=&HD000
20 DATA 3E,C3         :'LD  A,C3h
30 DATA 01,A1,56      :'LD  BC,56A1h
40 DATA 32,10,D0      :'LD  (D010h),A
50 DATA ED,43,11,D0   :'LD  (D011h),BC
60 DATA C9,"RET"      :'RET
80 READ A$
90 IF A$="RET" THEN 120
100 POKE &HD000+T,VAL("&h"+A$)
110 T=T+1:GOTO 80
120 A=USR(A)
130 PRINT "A=";HEX$(PEEK(&HD010))
140 PRINT "BC=";HEX$(PEEK(&HD012));HEX$(PEEK(&HD011))
run
A=C3
BC=56A1
Ok

П р и м е р 2. Пересылка содержимого регистра C в регистр A .

   10 CLEAR 200,&HD000:DEFUSR=&HD000
   20 DATA 0E,C3         :'LD  C,C3h
   30 DATA 79            :'LD  A,C
   40 DATA 32,10,D0      :'LD  (D010h),A
   50 DATA C9,"RET"      :'RET
   70 READ A$:IF A$="RET" THEN 110
   90 POKE &HD000+T,VAL("&h"+A$)
   100 T=T+1:GOTO 70
   110 A=USR(A)
   120 PRINT "C=A= ";HEX$(PEEK(&HD010))
   run
   C=A= C3
   Ok

П р и м е р 3. Загрузка содержимого регистра A в память по адресу, указанному в регистре BC.

   10 CLEAR 200,&HD000:DEFUSR=&HD000
   20 DATA 3E,C3         :'LD  A,C3h
   30 DATA 01,10,D0      :'LD  BC,D010h
   40 DATA 02            :'LD  (BC),A
   50 DATA C9,"RET"      :'RET
   70 READ A$:IF A$="RET" THEN 110
   90 POKE &HD000+T,VAL("&h"+A$):T=T+1:GOTO 70
   110 A=USR(A)
   120 PRINT "A=";HEX$(PEEK(&HD010))
   run
   A=C3
   Ok

П р и м е р 4. Проиллюстрируем работу команды EX DE,HL .

   10 CLEAR 200,&HD000:DEFUSR=&HD000
   20  DATA 11,C3,98      :'LD  DE,98C3h
   30  DATA 21,A1,56      :'LD  HL,56A1h
   40  DATA ED,53,30,D0   :'LD  (D030h),DE
   50  DATA ED,63,32,D0   :'LD  (D032h),HL
   60  DATA EB            :'EX  DE,HL
   70  DATA ED,53,34,D0   :'LD  (D034h),DE
   80  DATA ED,63,36,D0   :'LD  (D036h),HL
   90  DATA EB            :'EX  DE,HL
   100 DATA ED,53,38,D0   :'LD  (D038h),DE
   110 DATA ED,63,3A,D0   :'LD  (D03Ah),HL
   120 DATA C9,"RET"      :'RET
   140 READ A$
   150 IF A$="RET" THEN 180
   160 POKE &HD000+T,VAL("&h"+A$)
   170 T=T+1:GOTO 140
   180 A=USR(A)
   190 PRINT "До команды EX DE,HL:"
   200 PRINT " DE=";HEX$(PEEK(&HD031));HEX$(PEEK(&HD030))
   210 PRINT " HL=";HEX$(PEEK(&HD033));HEX$(PEEK(&HD032))
   220 PRINT "После команды EX DE,HL:"
   230 PRINT " DE=";HEX$(PEEK(&HD035));HEX$(PEEK(&HD034))
   240 PRINT " HL=";HEX$(PEEK(&HD037));HEX$(PEEK(&HD036))
   250 PRINT "После еще одной команды EX DE,HL:"
   260 PRINT " DE=";HEX$(PEEK(&HD039));HEX$(PEEK(&HD038))
   270 PRINT " HL=";HEX$(PEEK(&HD03B));HEX$(PEEK(&HD03A))
   run
   До команды EX DE,HL:
    DE=98C3
    HL=56A1
   После команды EX DE,HL:
    DE=56A1
    HL=98C3
   После еще одной команды EX DE,HL:
    DE=98C3
    HL=56A1
   Ok

П р и м е р 5. Сложение целых чисел, принадлежащих отрезку [0,255].

   10 CLEAR 100,&HD000    'Очистка памяти
   20 POKE &HD000,9       'Запись в память первого операнда
   30 POKE &HD001,9       'Запись в память второго операнда
   40 AD=&HD003           'Адрес начала подпрограммы
   50 READ T$:IF T$="z" THEN 90
   70 POKE AD,VAL("&h"+T$):AD=AD+1:GOTO 50
   90 DEFUSR=&HD003:H=USR(0)
   105 PRINT PEEK(&HD002)  'Печать результата
   110 DATA 3A,00,D0      :'LD   A,(D000) ;  (D000h) ──▶  А 
   120 DATA 47            :'LD   B,A      ;  (A)     ──▶  B  
   130 DATA 3A,01,D0      :'LD   A,(D001) ;  (D001h) ──▶  А 
   140 DATA 80            :'ADD  A,B      ;  (A)+(B) ──▶  A 
   150 DATA 32,02,D0      :'LD   (D002),A ;  (А)     ──▶ (D002h)
   160 DATA C9,"z"        :'RET           ;  Возврат из подпрограммы

П р и м е р 6. Умножение содержимого двух ячеек памяти.

   10 CLEAR 200,&HA000
   20 INPUT A,B:POKE &HA100,A:POKE &HA101,B 'Ввод начальных данных
   30 FOR I=0 TO 15:READ R$:POKE &HA000+I,VAL("&h"+R$):NEXT
   40 DEFUSR=&HA000:Z=USR(0)
   50 PRINT PEEK(&HA102)
   60 DATA 3A,00,A1     :'  LD    A,(A100h)
   70 DATA 47           :'  LD    B,A
   80 DATA 05           :'  DEC   B
   90 DATA 3A,01,A1     :'  LD    A,(A101h)
   100 DATA 57          :'  LD    D,A
   110 DATA 82          :'  ADD   A,D ◀────┐
   120 DATA 10,FD       :'  DJNZ  $-1  ────┘
   130 DATA 32,02,A1    :'  LD    (A102h),A
   150 DATA C9          :'  RET

П р и м е р 7. Нахождение суммы целых чисел от 1 до 10 .

   10 CLEAR 100,&HD000:DEFUSR=&HD000:AD=&HD000
   40 READ A$:IF A$="Z"THEN 80
   60 POKE AD,VAL("&h"+A$):AD=AD+1:GOTO 40
   80 A=USR(0):PRINT"Сумма:"PEEK(&HD00C):END
   110 DATA 06,0A      :' LD    B,0Ah
   120 DATA 3E,00      :' LD    A,00h
   130 DATA 80         :' ADD   A,B      ;◀──┐
   140 DATA 10,FD      :' DJNZ  D004h    ;───┘
   150 DATA 32,0C,D0   :' LD    (D00C),A
   160 DATA C9,"Z"     :' RET

П р и м е р 8. Нахождение большего из двух чисел.

   10 PRINT"Найду большее из двух чисел (0÷255)"
   20 INPUT"Первое число ";N1:INPUT"Второе число ";N2
   40 POKE &HC000,N1:POKE &HC001,N2
   50 CLEAR 200,&HD000:DEFUSR=&HD000:I=&HD000
   70 READ A$:IF A$="z" THEN 110
   90 POKE I,VAL("&h"+A$):I=I+1:GOTO 70
   110 A=USR(0)
   120 PRINT"Большее число:";PEEK(&HC003):END
   130 DATA 3A,00,C0    :'LD A,(C000h)
   140 DATA 47          :'LD B,A
   150 DATA 3A,01,C0    :'LD A,(C001h)
   160 DATA B8          :'CP B
   170 DATA F2,0C,D0    :'JP P,D00Ch
   180 DATA 78          :'LD A,B
   190 DATA 32,03,C0    :'LD (C003h),A
   200 DATA C9,"z"      :'RET
Напомним, что подрограмма в машинных кодах вызывается следующим  обра-
зом:       ┌────────────────────────────────────────────────┐
           │  П е р е м е н н а я = USR[n](а р г у м е н т) │ ,
           └────────────────────────────────────────────────┘
где  n - целое число, принадлежащее отрезку [0,9], которое  указывает  но-
мер подпрограммы в машинных кодах.
   Значение  а р г у м е н т а  передается подпрограмме в машинных  кодах.
При вызове подпрограммы число байтов, занимаемое этим значением, однознач-
но связанное с его типом, заносится в регистр A микропроцессора  Z80  и в
ячейку памяти F663h. Возможны следующие значения:
     2 - целочисленные,
     4 - вещественные с одинарной точностью,
     8 - вещественные с двойной точностью,
     3 - строковые.
   Адрес числовой  п е р е м е н н о й  хранится в регистре HL;
   адрес строковой п е р е м е н н о й  находится в регистре DE.

   П р и м е р 9.
   ─────────────
   10 CLEAR 200,&HF000
   20 DATA ED,63,02,F3        :'LD  (F302h),HL
   30 DATA 3A,F8,F7           :'LD  A,(F7F8h)
   40 DATA 4F                 :'LD  C,A
   50 DATA 81                 :'ADD A,C
   60 DATA 32,00,C0           :'LD  (C000h),A
   70 DATA C9,"RET"           :'RET
   80 DEFUSR=&HF000
   90 READ Z$:POKE &HF000+T,VAL("&H"+Z$)
   100 T=T+1:IF Z$<>"RET" THEN 90
   110 A=USR(6)   'Обратите внимание на то, что аргумент имеет целый тип!
   120 PRINT" В регистре HL находится число: &h";HEX$(PEEK(&HF303));RIGHT
   $("00"+HEX$(PEEK(&HF302)),2)
   125 PRINT" Это есть адрес аргумента функции USR"
   130 PRINT" Проверяем этот факт:... и вправду ";LEFT$(HEX$(PEEK(&HF7F7)
   ),1)
   140 PRINT" Результат работы подпрограммы в машинных кодах: ";PEEK(&HC0
   00)
   run
    В регистре HL находится число: &hF7F6
    Это есть адрес аргумента функции USR
    Проверяем этот факт:... и вправду 6
    Результат работы подпрограммы в машинных кодах:  12
   Ok

   П р и м е р  10.
   ───────────────
   10 CLEAR 200,&HF000
   20 DATA 32,00,F3            :'LD  (F300h),A
   30 DATA 3A,63,F6            :'LD  A,(F663h)
   40 DATA 32,01,F3            :'LD  (F301h),A
   50 DATA ED,53,02,F3         :'LD  (F302h),DE
   60 DATA C9,"RET"            :'RET
   70 DEFUSR=&HF000
   80 READ Z$:POKE &HF000+T,VAL("&h"+Z$)
   90 T=T+1:IF Z$<>"RET" GOTO 80
   100 A$="MSX":A$=USR(A$) 'Обратите внимание на то, что тип аргумента - 
   строковый !
   110 PRINT"В регистре А:";PEEK(&HF300)
   120 PRINT"В ячейке F663h:";PEEK(&HF301)
   130 PRINT"Адрес переменной:";HEX$(PEEK(&HF303));
   RIGHT$("00"+HEX$(PEEK(&HF302)),2)
   run
   В регистре А: 3
   В ячейке F663h: 3
   Адрес переменной:8183
   Ok
   ?hex$(peek(&h8185));hex$(peek(&h8184))
   80E7
   Ok
   ?chr$(peek(&h80E7))
   M
   Ok
   Итак, информация о типе переменной  A$ хранится  в  ячейке  с  адресом
&HF663 , а ссылка на адрес переменной A$ (&H8183) хранится в регистре DE.

                                      Если вы не тот, кто наверху, значит,
                                      вы тот, кто внизу.
                                                                 С.Поттер

   П р и м е р  11.  Сортировка  целочисленного  массива , содержащего  5
   ───────────────   элементов.
   10 CLEAR 200,&HA000:DEFUSR=&HA000:AD=&HA000
   20 READ A$:IF A$="z" THEN 50
   30 POKE AD,VAL("&h"+A$)
   40 AD=AD+1:GOTO 20
   50 FOR I=0 TO 4:INPUT A:POKE &HB000+I,A:NEXT
   60 A=USR(0)
   70 FOR I=0 TO 4:PRINT PEEK(&HC000+I):NEXT
   80 END
   90  DATA 0E,00     :'LD   C,00
   100 DATA 11,00,C0  :'LD   DE,C000
   110 DATA 21,00,B0  :'LD   HL,B000    ◀────┐
   120 DATA 06,05     :'LD   B,05            │
   130 DATA 7E        :'LD   A,(HL) ◀─┐      │
   140 DATA B9        :'CP   C        │      │
   150 DATA C2,11,A0  :'JP   NZ,A011  │  ──┐ │
   160 DATA 12        :'LD   (DE),A   │    │ │
   170 DATA 13        :'INC  DE       │    │ │
   180 DATA 23        :'INC  HL       │ ◀──┘ │
   190 DATA 10,F6     :'DJNZ A00A   ──┘      │
   200 DATA 79        :'LD   A,C             │
   210 DATA FE,FF     :'CP   FF              │
   220 DATA CA,1E,A0  :'JP   Z,A01E  ──┐     │
   230 DATA 0C        :'INC  C         │     │
   240 DATA C3,05,A0  :'JP   A005    ──│─────┘
   250 DATA C9,"z"    :'RET         ◀──┘

   П р и м е р  12.  Вычисление факториала "маленьких" целых чисел
   ───────────────
   10 CLS:KEYOFF:PRINT"Найду факториал заданного Вами целого числа"
   20 INPUT"Введите целое число, меньшее 6";F
   30 POKE &HC000,F
   40 IF F=0 OR F=1 THEN POKE &HC003,1:GOTO 90
   50 CLEAR 200,&HD000:DEFUSR=&HD000:I=&HD000
   60 READ A$:IF A$="z" THEN 80 
   70 POKE I,VAL("&h"+A$):I=I+1:GOTO 60
   80 A=USR(0)
   90 PRINT "Факториал "PEEK(&HC000)"=" PEEK(&HC003):END 
   100 DATA 3A,00,C0      :'LD   A,(C000h) 
   110 DATA FE,02         :'CP   2h
   120 DATA 28,0A         :'JR   Z,$+12 ───────────┐      
   130 DATA 47            :'LD   B,A               │
   140 DATA 05            :'DEC  B                 │
   150 DATA 05            :'DEC  B                 │
   160 DATA 48            :'LD   C,B ◀───────┐     │
   170 DATA 57            :'LD   D,A         │     │
   180 DATA 82            :'ADD  A,D ◀────┐  │     │
   190 DATA 10,FD         :'DJNZ $-1h ────┘  │     │    
   200 DATA 41            :'LD   B,C         │     │    
   210 DATA 10,F8         :'DJNZ $-6h ───────┘     │    
   220 DATA 32,03,C0      :'LD   (C003h),A ◀───────┘  
   230 DATA C9,"z"        :'RET

   П р и м е р  13.  Умножение шестнадцатиразрядных целых чисел без знака.
   ───────────────
   20 CLEAR 200,&HF000
   40 INPUT"Первое целое число";N1%
   50 INPUT"Второе целое число";N2%
   60 POKE &HF000,PEEK(VARPTR(N1%)):POKE &HF001,PEEK(VARPTR(N1%)+1)
   70 POKE &HF002,PEEK(VARPTR(N2%)):POKE &HF003,PEEK(VARPTR(N2%)+1)
   80 DEFUSR=&HF006
   90 DATA  ED,6B,00,F0 :' ARG1: LD   HL,(F000)
   100 DATA ED,5B,02,F0 :' ARG2: LD   DE,(F002)
   110 DATA 06,10       :'       LD   B,10
   120 DATA 4A          :'       LD   C,D       ; Пересылка множителя
   130 DATA 7B          :'       LD   A,E
   140 DATA EB          :'       EX   DE,HL     ; Пересылка множимого
   150 DATA 21,00,00    :'       LD   HL,0000   ; Установка частичного ре-
                                                ; зультата в исходное сос-
                                                ; тояние
   160 DATA CB,39       :' MLOOP:SRL  C         ; Сдвиг множителя вправо
   170 DATA 1F          :'       RRA            ; Наименее  значащий  раз-
                                                ; ряд к переносу
   180 DATA 30,01       :'       JR   NC,NOADD-S; Если  нет  переноса, то 
                                                  пропуск суммирования
   190 DATA 19          :'       ADD  HL,DE     ; Иначе суммирование  мно-
                                                ; жимого в частичный резу-
                                                ; льтат
   200 DATA EB          :' NOADD:EX   DE,HL     ; Сдвиг множимого влево
   210 DATA 29          :'       ADD  HL,HL     ; при умножении на 2
   220 DATA EB          :'       EX   DE,HL
   230 DATA 10,F5       :'       DJNZ MLOOP-S   ; Повторение до последнего
                                                ; разряда
   240 DATA ED,63,04,F0 :'  REZ: LD   (F004),HL
   250 DATA C9          :'       RET
   260 FOR T=0 TO 31:READ Z$:POKE &HF006+T,VAL("&h"+Z$):NEXT
   270 X=USR(X) 'Выполним умножение чисел N1% и N2%
   280 MULT=256*PEEK(&HF005)+PEEK(&HF004)
   290 IF MULT>32767 THEN MULT=MULT-65536!
   300 PRINT"Ваш результат:";MULT:END

FIXME DELETEME

Временный вариант

Временный вариант

[101]
[ 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

[96]Программирование на языке ассемблера в системе MSX-2 — Организация связей с программами на языке MSX BASIC

DEF USR

FIXME

Оператор DEF USR определяет начальный адрес программы в машинных кодах для последующего использования. Можно использовать до 10 различных программ. Программы нумеруются от 0 до 9. По умолчанию берётся значение 0.

Синтаксис:

DEF USR номер = адрес

,

где

  • номер — номер программы в машинных кодах, может находиться в диапазоне от 0 до 9. Если не указано, то 0
  • адрес — начальный адрес подпрограммы на в машинных кодах

Пример:

DEF USR 1 = &HA000

В этом примере указано, что начальным адресом подпрограммы с номером 1 является &HA000.

USR()

FIXME

Функция USR() передает переменную в подпрограмму на машинном языке. Сначала необходимо определить расположение подпрограммы с помощью DEF USR.

Синтаксис:

USR [номер подпрограммы](аргумент)

,

где

  • номер — номер подпрограммы число в диапазоне от 0 до 9, если не указано то 0
  • аргумент — имя переменной, или строка может быть получена машинной подпрограммой, если аргументом является 0 (нуль), в программу в машинных кодах ничего не переносится

Значение переменной передается подпрограмме в машинных кодах. При вызове программы число байтов, занимаемое этим значением, однозначно связанное с его типом, заносится в регистр А микропроцессора Z80 и в ячейку памяти VALTYP.

Адрес переменной хранится в регистре HL.

Для строк имеется небольшое отличие. Адрес, где записана строка, находится в регистре DE.


Первая страницаПредыдущая страницаНазад к обзоруСледующая страницаПоследняя страница

msx/basic_dialogue_programming_language/101.1676137185.txt.gz · Последние изменения: 2023-02-11 20:39 — GreyWolf