1.5. Р а б о т а с д в о и ч н ы м и ф а й л а м и Истинное красноречие состоит в том, чтобы сказать все, что нужно, но не более того. Ф.Ларошфуко Опишем последовательность написания программы в машинных кодах: 1. Вначале пишется программа на языке MSX-BASIC, которая будет загру- жать машинные подпрограммы в защищенную область RAM. Предположим, что ма- шинная программа вводится таким образом по адресам с α по β . 2. Машинная программа записывается на диск в двоичном формате командой ┌────────────────────────────┐ │ BSAVE "И м я",α,β,γ │ . └────────────────────────────┘ Отметим, что наличие последнего параметра (адреса выполнения γ) необя- зательно. Он указывает адрес запуска, когда программа загружается с добав- лением параметра R (автоматическое выполнение). Это удобно, если в начале машинной программы имеются подпрограммы. 3. Для использования программы загрузите программу с помощью команды: ┌────────────────────────────┐ │ BLOAD "И м я",R,δ │ . └────────────────────────────┘ Последний параметр (адрес смещения δ) не обязателен.Он указывает интер- вал между адресом α, который использовался для загрузки, и адресом, по ко- торому будет размещена программа. В н и м а н и е! Если программа содержит переходы по абсолютному адре- су, вызовы внутренних подпрограмм или данные, то не исключено, что ее не- возможно будет перемещать в памяти подобным образом. П р и м е р [2]. Программа устанавливает экран в режимы SCREEN 2,3 , ─────────────── загружает форму спрайта и позволяет перемещать спрайт по горизонтали при помощи клавиш управления курсором "──▶" и "◀──". 10 CLEAR 200,&HA000 'Программа размещается с адреса &HA000 20 A=&HA000 30 READ A$:IF A$="Z" THEN 50 40 POKE A, VAL("&H"+A$):A=A+1:GOTO 30 50 BSAVE"BSPRIT",&HA000,&HA073,&HA030 110 DATA 3E,E3 :'A000 LD A,E3 ;A=E3 ; Размер 120 DATA 32,E0,F3 :'A002 LD (F3E0),A ;A ─▶F3E0 VDP(1) ; спрайта 130 DATA CD,72,00 :'AOO5 CALL 0072 ; 140 DATA 21,50,A0 :'A008 LD HL,A050 ;HL=начало данных 150 DATA 11,00,38 :'A00B LD DE,3800 ;DE=начало SGT 160 DATA 01,20,00 :'A00E LD BC,0020 ;BC=длина данных 170 DATA CD,5C,00 :'A011 CALL 005C ;пересылка RAM──▶видеопамять 180 DATA C9 :'AO14 RET ;выход 190 DATA 00,00,00 :'A015 NOP 200 'A018 SAT 210 DATA 21,70,A0 :'A018 LD HL,A070 ;HL=начало данных 220 DATA 11,00,1B :'A01B LD DE,1B00 ;DE=начало SAT 230 DATA 01,04,00 :'A01E LD BC,0004 ;BC=длина данных 240 DATA CD,5C,00 :'A021 CALL 005C ;пересылка RAM──▶видеопамять 250 DATA C9 :'A024 RET ;выход 260 DATA 00,00,00 :'A025 NOP 270 'A028 STICK(0) 280 DATA 3E,00 :'А028 LD A,00 ;клавиши управления курсором 290 DATA CD,D5,00 :'A02A CALL 00D5 ;A=STICK(0) 300 DATA C9 :'A02D RET ;выход 310 DATA 00,00 :'A02E NOP 320 'A030 Основная программа 330 DATA CD,00,A0 :'A030 CALL A000 ;Экран/SGT 340 DATA CD,18,A0 :'A033 CALL A018 ;SAT 350 DATA CD,28,A0 :'A036 CALL AO28 ;STICK(0) 360 DATA 21,71,A0 :'A039 LD HL,A071 ;HL=X координатный указатель 370 DATA FE,03 :'A03C CP 03 ;A=3?─────────┐ 380 DATA 20,01 :'A03E JR NZ,01 ;нет──▶JUMP │ 390 DATA 34 :'A040 INC (HL) ;(HL)=(HL)+1 │ 400 DATA FE,07 :'A041 CP 07 ;A=7? ◀────┘ 410 DATA 20,01 :'A043 JR NZ,01 ;нет──▶JUMP───┐ 420 DATA 35 :'A045 DEC (HL) ;(HL)=(HL)-1 │ 430 DATA 01,FF,00 :'A046 LD BC,FF ;счетчик=255 ◀┘ 440 DATA 0B :'А049 DEC BC ;BC=BC-1 450 DATA 78 :'A04A LD A,B ;BC=0? 460 DATA B1 :'A04B OR C ;нет──▶цикл 470 DATA 20,FB :'A04C JR NZ,$-3 ;переход на A049 480 DATA 18,E3 :'A04E JR $-27 ;переход на A033 490 'A050 Начальные данные для ш а б л о н а спрайта 500 DATA FF,80,80,80,80,80,80,80 510 DATA 80,80,80,80,80,80,80,FF 520 DATA FF,01,01,01,01,01,01,01 530 DATA 01,01,01,01,01,01,01,FF 540 'A070 Начальные данные для а т р и б у т а спрайта 550 DATA 10,10,00,0F,"Z" Эта программа загружает машинную программу как двоичный файл с именем BSPRIT . Запуск программы выполняется командой: BLOAD"BSPRITE",R Отметим, что для изменения ф о р м ы спрайта достаточно изменить дан- ные в строках с 500 по 530. Для изменения с к о р о с т и перемещения спрайта измените значение счетчика по адресам A047h и A048h. В н и м а н и е! Единственный способ "выйти" из этой программы - это выключить компьютер или нажать кнопку сброса "RESET". П р и м е р. Перемещение спрайта при помощи клавиш управления курсо- ─────────── ром. 10 CLEAR 200,&HD000 20 DEFUSR=&HD00C 30 A=&HD000 40 READ K$:IF K$="z" THEN A=USR(0):END 50 POKE A,VAL("&h"+K$) 60 A=A+1:GOTO 40 70 DATA FF,FF,FF,FF :' ◀────────────────┐ Образ 80 DATA FF,FF,FF,FF :' ◀────────────────┘ спрайта 90 DATA 64,64,00,0F :' ◀───────────────── Y,X,шаблон,цвет 100 DATA CD,6F,00 :' CALL 006F SCREEN 1 110 DATA 21,00,D0 :' LD HL,D000 ─┐ Формирование 120 DATA 11,00,38 :' LD DE,3800 │ шаблона 130 DATA 01,08,00 :' LD BC,0008 │ спрайта 140 DATA CD,5C,00 :' CALL 005C ◀─┘ 150 DATA 21,08,D0 :'┌─▶LD HL,D008◀─┐ Рисование 160 DATA 11,00,1B :'│ LD DE,1B00 │ спрайта 170 DATA 01,04,00 :'│ LD BC,0004 │ 180 DATA CD,5C,00 :'│ CALL 005C ◀─┘ 190 DATA 3E,00 :'│ LD A,00 ◀─┐ Обращение 200 DATA CD,D5,00 :'│ CALL 00D5 ◀─┘ к подпрограмме BIOS 210 DATA FE,01 :'│ CP 01 ◀─┐ 220 DATA CC,7E,D0 :'│ CALL Z,D07E │ 230 DATA FE,02 :'│ CP 02 │ 240 DATA CC,7E,D0 :'│ CALL Z,D07E │ Проверка нажатия 250 DATA FE,02 :'│ CP 02 │ клавиш управления 260 DATA CC,8D,D0 :'│ CALL Z,D08D │ курсором 270 DATA FE,03 :'│ CP 03 │ и переход 280 DATA CC,8D,D0 :'│ CALL Z,D08D │ на подпрограмму 290 DATA FE,04 :'│ CP 04 │ изменения X,Y 300 DATA CC,83,D0 :'│ CALL Z,D083 │ 310 DATA FE,04 :'│ CP 04 │ 320 DATA CC,8D,D0 :'│ CALL Z,D08D │ 330 DATA FE,05 :'│ CP 05 │ 340 DATA CC,83,D0 :'│ CALL Z,D083 │ 350 DATA FE,06 :'│ CP 06 │ 360 DATA CC,83,D0 :'│ CALL Z,D083 │ 370 DATA FE,06 :'│ CP 06 │ 380 DATA CC,88,D0 :'│ CALL Z,D088 │ 390 DATA FE,07 :'│ CP 07 │ 400 DATA CC,88,D0 :'│ CALL Z,D088 │ 410 DATA FE,08 :'│ CP 08 │ 420 DATA CC,88,D0 :'│ CALL Z,D088 │ 430 DATA FE,08 :'│ CP 08 │ 440 DATA CC,7E,D0 :'│ CALL Z,D07E ◀─┘ 450 DATA CD,BA,00 :'│ CALL 00BA 460 DATA 21,FF,0F :'│ LD HL,0FFF ◀─┐ 470 DATA 2B :'│ DEC HL ◀──┐ │ 480 DATA 7D :'│ LD A,L │ │ 490 DATA FE,00 :'│ CP 00 │ │ Задержка 500 DATA C2,6E,D0 :'│ JP NZ,D06E ──┤ │ 510 DATA 7C :'│ LD A,H │ │ 520 DATA FE,00 :'│ CP 00 │ │ 530 DATA C2,6E,D0 :'│ JP NZ,D06E ──┘◀─┘ 540 DATA C3,1B,D0 :'└─ JP D01B 550 DATA 21,08,D0 :' LD HL,D008◀─┐ Подпрограмма 560 DATA 35 :' DEC (HL) │ уменьшения 570 DATA C9 :' RET ◀─┘ координаты Y 580 DATA 21,08,D0 :' LD HL,D008◀─┐ Подпрограмма 590 DATA 34 :' INC (HL) │ увеличения 600 DATA C9 :' RET ◀─┘ координаты Y 610 DATA 21,09,D0 :' LD HL,D009◀─┐ Подпрограмма 620 DATA 35 :' DEC (HL) │ уменьшения 630 DATA C9 :' RET ◀─┘ координаты X 640 DATA 21,09,D0 :' LD HL,D009◀─┐ Подпрограмма 650 DATA 34 :' INC (HL) │ увеличения 660 DATA C9 :' RET ◀─┘ координаты X 670 DATA z :' К о н е ц 1.6. Р е а л и з а ц и я в е щ е с т в е н н о й а р и ф м е т и к и н а м а ш и н н о м я з ы к е Изучай все не из тщеславия, а ради практической пользы. Г.Лихтенберг. Афоризмы В системной области имеются два вещественных "регистра" - а к к у м у- л я т о р а, при помощи которых компьютер осуществляет все арифметические операции: DAC ("Decimal ACcumulator"-"десятичный аккумулятор") - F7F6h, 16 байтов, ARG ("ARGument"-"аргумент") - F847h, 16 байтов. В е щ е с т в е н н о е число в аккумуляторах размещается следующим образом: F7F6h F7F7h F7FDh ┌──────────────┬───┬───┬───┬───┬───┬───┬───┐ │Знак и порядок│ М а н т и с с а │ DAC └──────────────┴───┴───┴───┴───┴───┴───┴───┘ F847h F848h F84Eh ┌──────────────┬───┬───┬───┬───┬───┬───┬───┐ │Знак и порядок│ М а н т и с с а │ ARG └──────────────┴───┴───┴───┴───┴───┴───┴───┘ Ц е л о е число в аккумуляторе располагается следующим образом: F7F6h F7F7h F7F8h F7F9h ┌────────┬────────┬─────────────┬─────────────┐ │ Незначащие байты│ Младший байт│ Старший байт│ DAC └────────┴────────┴─────────────┴─────────────┘ F847h F848h F849h F84Ah ┌────────┬────────┬─────────────┬─────────────┐ │ Незначащие байты│ Младший байт│ Старший байт│ ARG └────────┴────────┴─────────────┴─────────────┘ Подробнее о хранении чисел см. в разделе X.4.1. В ячейке VALTYP системной области (по адресу F663h) хранится тип числа, находящегося в аккумуляторе DAC, причем тип закодирован следующим образом: 2 - целое число; 4 - вещественное число одинарной точности; 8 - вещественное число двойной точности. В следующих табличках приведен список входных точек очень полезных под- программ ROM. 1.6.1. П е р е с ы л к и ┌────────┬───────┬────────────────┬────────┬──────────────────┐ │ Имя │ │ │ │ │ │ подпро-│ Адрес │ Выполняемые │ Т и п │ Изменяемые │ │ граммы │ │ действия │ │ регистры │ ├────────┼───────┼────────────────┼────────┼──────────────────┤ │ MAF │ 2C4Dh │ ARG := DAC │ Double │ A,B,D,E,H,L,ARG │ │ MAM │ 2C50h │ ARG := (HL) │ Double │ A,B,D,E,H,L,ARG │ │ MOV8DH │ 2C53h │ (DE):= (HL) │ Double │ A,B,D,E,H,L │ │ MFA │ 2C59h │ DAC := ARG │ Double │ A,B,D,E,H,L,DAC │ │ MFM │ 2C5Ch │ DAC := (HL) │ Double │ A,B,D,E,H,L,DAC │ │ MMF │ 2C67h │ (HL):= DAC │ Double │ A,B,D,E,H,L │ │ MOV8HD │ 2C6Ah │ (HL):= (DE) │ Double │ A,B,D,E,H,L │ │ XTF │ 2C6Fh │ (SP):= DAC │ Double │ A,B,D,E,H,L │ │ PHA │ 2CC7h │ ARG := (SP) │ Double │ A,B,D,E,H,L,ARG │ │ PHF │ 2CCCh │ DAC := (SP) │ Double │ A,B,D,E,H,L,DAC │ │ PPA │ 2CDCh │ (SP):= ARG │ Double │ A,B,D,E,H,L │ │ PPF │ 2CE1h │ (SP):= DAC │ Double │ A,B,D,E,H,L │ │ PUSHF │ 2EB1h │ DAC := (SP) │ Single │ D,E,DAC │ │ MOVFM │ 2EBEh │ DAC := (HL) │ Single │ B,C,D,E,H,L,DAC │ │ MOVFR │ 2EC1h │ DAC := (CBED) │ Single │ DAC,D,E │ │ MOVRF │ 2ECCh │ (CBED):= DAC │ Single │ B,C,D,E,H,L │ │ MOVRMI │ 2ED6h │ (CBED):= (HL) │ Single │ B,C,D,E,H,L │ │ MOVRM │ 2EDFh │ (BCDE):= (HL) │ Single │ B,C,D,E,H,L │ │ MOVMF │ 2EE8h │ (HL):= DAC │ Single │ B,C,D,E,H,L │ │ MOVE │ 2EEBh │ (HL):= (DE) │ Single │ B,C,D,E,H,L │ │ VMOVAM │ 2EEFh │ ARG := (HL) │ VALTYP │ B,C,D,E,H,L,ARG │ │ MOVVFM │ 2EF2h │ (DE):= (HL) │ VALTYP │ B,C,D,E,H,L │ │ VMOVE │ 2EF3h │ (HL):= (DE) │ VALTYP │ B,C,D,E,H,L │ │ VMOVFA │ 2F05h │ DAC := ARG │ VALTYP │ B,C,D,E,H,L,DAC │ │ VMOVFM │ 2F08h │ DAC := (HL) │ VALTYP │ B,C,D,E,H,L,DAC │ │ VMOVAF │ 2F0Dh │ ARG := DAC │ VALTYP │ B,C,D,E,H,L,ARG │ │ VMOVMF │ 2F10h │ (HL):= DAC │ VALTYP │ B,C,D,E,H,L │ └────────┴───────┴────────────────┴────────┴──────────────────┘ П р и м е р 1. Записать число в аккумулятор DAC,а затем прочитать его. ───────────── 10 CLEAR 200,&HF000:DEFUSR=&HF000 20 INPUT"Ваше число";N:A$=HEX$(VARPTR(N)) 30 POKE &HF100,VAL("&h"+RIGHT$(A$,2)):POKE&HF101,VAL("&h"+LEFT$(A$,2)) 40 DATA 2A,00,F1 :'LD HL,(F100h) 50 DATA CD,5C,2C :'CALL 2C5Ch 70 DATA 21,F6,F7 :'LD HL,F7F6h 80 DATA 11,00,F2 :'LD DE,F200h 90 DATA 01,10,00 :'LD BC,10h 100 DATA ED,B0 :'LDIR 130 DATA C9 :'RET 140 FOR T=0 TO 17:READ Z$:POKE &HF000+T,VAL("&h"+Z$):NEXT 150 X=USR(X) 160 FOR T=0 TO 15:PRINT HEX$(PEEK(VARPTR(N)+T)),HEX$(PEEK(&HF200+T)) 170 NEXT П р и м е р 2. Записать число в аккумулятор ARG,а затем прочитать его. ───────────── 10 CLEAR 200,&HF000:DEFUSR=&HF000 20 INPUT"Ваше число";N:A$=HEX$(VARPTR(N)) 30 POKE &HF100,VAL("&h"+RIGHT$(A$,2)):POKE&HF101,VAL("&h"+LEFT$(A$,2)) 40 DATA 2A,00,F1 :'LD HL,(F100h) 50 DATA CD,50,2C :'CALL 2C50h 70 DATA 21,47,F8 :'LD HL,F847h 80 DATA 11,00,F2 :'LD DE,F200h 90 DATA 01,10,00 :'LD BC,10h 100 DATA ED,B0 :'LDIR 130 DATA C9 :'RET 140 FOR T=0 TO 17:READ Z$:POKE &HF000+T,VAL("&h"+Z$):NEXT 150 X=USR(X) 160 FOR T=0 TO 15:PRINT HEX$(PEEK(VARPTR(N)+T)),HEX$(PEEK(&HF200+T)) 170 NEXT 1.6.2. А р и ф м е т и ч е с к и е о п е р а ц и и над ц е л ы м и ч и с л а м и Наиболее полезны те советы, которым легко следовать. Л.Вовенарг ┌────────┬───────┬────────────────────┬───────────────────────┐ │ Имя │ │ │ │ │ подпро-│ Адрес │Выполняемые действия│ Изменяемые регистры │ │ граммы │ │ │ │ ├────────┼───────┼────────────────────┼───────────────────────┤ │ UMULT │ 314Ah │ DE := BC·DE │ A,B,C,D,E │ │ ISUB │ 3167h │ HL := DE-HL │ A,B,C,D,E,H,L │ │ IADD │ 3172h │ HL := DE+HL │ A,B,C,D,E,H,L │ │ IMULT │ 3193h │ HL := DE·HL │ A,B,C,D,E,H,L │ │ IDIV │ 31E6h │ HL := DE/HL │ A,B,C,D,E,H,L │ │ IMOD │ 323Ah │ HL := DE mod HL │ A,B,C,D,E,H,L │ └────────┴───────┴────────────────────┴───────────────────────┘ П р и м е р 3. Умножение целых чисел (операнды находятся в регистрах ────────────── HL и DE). 10 CLEAR 200,&HD000 20 DEFUSR=&HD000 30 I=&HD000 40 READ A$:IF A$="z" THEN A=USR(0):PRINT PEEK(&H9000):END 60 POKE I,VAL("&h"+A$):I=I+1:GOTO 40 90 DATA 21,0A,00:' LD HL,000Ah ; Загрузка регистра HL константой 100 DATA 11,04,00:' LD DE,0004h ; Загрузка регистра DE константой 110 DATA CD,93,31:' CALL 3193h ; Вызов нужной подпрограммы 120 DATA 22,00,90:' LD (9000h),HL 130 DATA C9 :' RET 140 DATA "z" :' 1.6.3. А р и ф м е т и ч е с к и е о п е р а ц и и н а д в е щ е с т в е н н ы м и ч и с л а м и ┌────────┬───────┬────────────────────┬───────────────────────┐ │ Имя │ │ │ │ │ подпро-│ Адрес │Выполняемые действия│ Изменяемые регистры │ │ граммы │ │ │ │ ├────────┼───────┼────────────────────┼───────────────────────┤ │ DECSUB │ 268Ch │ DAC := DAC-ARG │ A,B,C,D,E,H,L,DAC │ │ DECADD │ 269Ah │ DAC := DAC+ARG │ A,B,C,D,E,H,L,DAC │ │ DECNRM │ 26FAh │ Нормализовать DAC │ A,B,C,D,E,H,L,DAC │ │ DECROU │ 273Ch │ Округлить DAC │ A,B,C,D,E,H,L,DAC │ │ DECMUL │ 27E6h │ DAC := DAC·ARG │ A,B,C,D,E,H,L,DAC │ │ DECDIV │ 289Fh │ DAC := DAC/ARG │ A,B,C,D,E,H,L,DAC │ │ COS │ 2993h │ DAC := COS(DAC) │ A,B,C,D,E,H,L,DAC,ARG │ │ SIN │ 29ACh │ DAC := SIN(DAC) │ A,B,C,D,E,H,L,DAC,ARG │ │ TAN │ 29FBh │ DAC := TAN(DAC) │ A,B,C,D,E,H,L,DAC,ARG │ │ ATN │ 2A14h │ DAC := ATN(DAC) │ A,B,C,D,E,H,L,DAC,ARG │ │ LOG │ 2A72h │ DAC := LOG(DAC) │ A,B,C,D,E,H,L,DAC,ARG │ │ SQR │ 2AFFh │ DAC := SQR(DAC) │ A,B,C,D,E,H,L,DAC,ARG │ │ EXP │ 2B4Ah │ DAC := EXP(DAC) │ A,B,C,D,E,H,L,DAC,ARG │ │ RND │ 2BDFh │ DAC := RND(DAC) │ A,B,C,D,E,H,L,DAC,ARG │ │ SIGN │ 2E71h │ A := SIGN(DAC) │ A │ │ ABSFN │ 2E82h │ DAC := ABS(DAC) │ A,B,C,D,E,H,L,DAC,ARG │ │ NEG │ 2E8Dh │ DAC := - DAC │ A,H,L,DAC │ │ SGN │ 2E97h │ DAC := SGN(DAC) │ A,H,L,DAC │ └────────┴───────┴────────────────────┴───────────────────────┘ П р и м е р 4. Сумма двух вещественных чисел. ───────────── 10 CLEAR 200,&HF000:DEFUSR=&HF000 20 DATA 21,00,00 :'LD HL,address(N1) ;F000h 30 DATA CD,5C,2C :'LD DAC,(HL) ;F003h 40 DATA 21,00,00 :'LD HL,address(N2) ;F006h 50 DATA CD,50,2C :'LD ARG,(HL) ;F009h 60 DATA CD,9A,26 :'DAC:=DAC+ARG ;F00Ch 70 DATA 21,00,00 :'LD HL,address(N1) ;F00Fh 80 DATA CD,67,2C :'LD (HL),DAC ;F012h 90 DATA C9 :'RET ;F015h 100 FOR T=0 TO &H15:READ Z$:POKE &HF000+T,VAL("&h"+Z$):NEXT 110 INPUT"Первое слагаемое";N1:INPUT"Второе слагаемое";N2 120 A$=HEX$(VARPTR(N1)):B$=HEX$(VARPTR(N2)) 130 L1$=RIGHT$(A$,2):L2$=RIGHT$(B$,2) 140 H1$=LEFT$(A$,2):H2$=LEFT$(B$,2) 150 POKE &HF001,VAL("&h"+L1$):POKE &HF002,VAL("&h"+H1$) 160 POKE &HF007,VAL("&h"+L2$):POKE &HF008,VAL("&h"+H2$) 170 POKE &HF010,VAL("&h"+L1$):POKE &HF011,VAL("&h"+H1$) 180 H=USR(H) 190 PRINT"Сумма:";N1 П р и м е р 5. Возведение в степень. ───────────── 10 CLEAR 200,&HF000:DEFUSR=&HF000 20 DATA 21,00,00 :'LD HL,address(N1) ;F000h 30 DATA CD,5C,2C :'LD DAC,(HL) ;F003h 40 DATA 21,00,00 :'LD HL,address(N2) ;F006h 50 DATA CD,50,2C :'LD ARG,(HL) ;F009h 60 DATA CD,D7,37 :'DAC:=DAC^ARG ;F00Ch 70 DATA 21,00,00 :'LD HL,address(N1) ;F00Fh 80 DATA CD,67,2C :'LD (HL),DAC ;F012h 90 DATA C9 :'RET ;F015h 100 FOR T=0 TO &H15:READ Z$:POKE &HF000+T,VAL("&h"+Z$):NEXT 110 INPUT"N1";N1:INPUT"N2";N2 120 A$=HEX$(VARPTR(N1)):B$=HEX$(VARPTR(N2)) 130 L1$=RIGHT$(A$,2):L2$=RIGHT$(B$,2) 140 H1$=LEFT$(A$,2):H2$=LEFT$(B$,2) 150 POKE &HF001,VAL("&h"+L1$):POKE &HF002,VAL("&h"+H1$) 160 POKE &HF007,VAL("&h"+L2$):POKE &HF008,VAL("&h"+H2$) 170 POKE &HF010,VAL("&h"+L1$):POKE &HF011,VAL("&h"+H1$) 180 H=USR(H) 190 PRINT"N1^N2=";N1 П р и м е р 6. Вычисление значения функции синус вещественного аргу- ────────────── мента. 10 CLEAR 200,&HF000:DEFUSR=&HF000 20 DATA 21,00,00 :'LD HL,address(N1) ;F000h 30 DATA CD,5C,2C :'LD DAC,(HL) ;F003h 60 DATA CD,AC,29 :'DAC:=SIN(DAC) ;F006h 70 DATA 21,00,00 :'LD HL,address(N1) ;F009h 80 DATA CD,67,2C :'LD (HL),DAC ;F00Ch 90 DATA C9 :'RET ;F00Fh 100 FOR T=0 TO 15:READ Z$:POKE &HF000+T,VAL("&h"+Z$):NEXT 110 INPUT"Число";N1:A$=HEX$(VARPTR(N1)) 130 L1$=RIGHT$(A$,2):H1$=LEFT$(A$,2) 150 POKE &HF001,VAL("&h"+L1$):POKE &HF002,VAL("&h"+H1$) 170 POKE &HF00A,VAL("&h"+L1$):POKE &HF00B,VAL("&h"+H1$) 180 H=USR(H):PRINT"Синус:";N1 П р и м е р 7. Генерация псевдослучайного числа. ────────────── 10 CLEAR 200,&HF000:DEFUSR=&HF000 20 DATA 21,00,00 :'LD HL,address(N1) ;F000h 30 DATA CD,5C,2C :'LD DAC,(HL) ;F003h 60 DATA CD,DF,2B :'DAC:=RND(DAC) ;F006h 70 DATA 21,00,00 :'LD HL,address(N1) ;F009h 80 DATA CD,67,2C :'LD (HL),DAC ;F00Ch 90 DATA C9 :'RET ;F00Fh 100 FOR T=0 TO 15:READ Z$:POKE &HF000+T,VAL("&h"+Z$):NEXT 110 INPUT"Число";N1 120 A$=HEX$(VARPTR(N1)) 130 L1$=RIGHT$(A$,2) 140 H1$=LEFT$(A$,2) 150 POKE &HF001,VAL("&h"+L1$):POKE &HF002,VAL("&h"+H1$) 170 POKE &HF00A,VAL("&h"+L1$):POKE &HF00B,VAL("&h"+H1$) 180 H=USR(H):PRINT"RND(n1)=";N1 П р и м е р 8. Вычислить значение функции двух переменных ────────────── z = cos(x)+ sin(y) 10 CLEAR 200,&HF000:DEFUSR=&HF000:T=0 20 INPUT"X=";X:INPUT"Y=";Y:A1$=HEX$(VARPTR(X)):A2$=HEX$(VARPTR(Y)) 30 L1=VAL("&h"+RIGHT$(A1$,2)):R1=VAL("&h"+LEFT$(A1$,2)) 'Адрес числа X 40 L2=VAL("&h"+RIGHT$(A2$,2)):R2=VAL("&h"+LEFT$(A2$,2)) 'Адрес числа Y 50 POKE &HF301,L1:POKE &HF302,R1:POKE &HF303,L2:POKE &HF304,R2 60 READ Z$:IF Z$<>"RET" THEN POKE &HF000+T,VAL("&h"+Z$):T=T+1:GOTO 60 70 DATA 2A,01,F3 :'LD HL,(F301h); HL содержит адрес переменной X 75 DATA E5 :'PUSH HL ; 80 DATA CD,5C,2C :'LD DAC,(HL) ; DAC:=X 90 DATA CD,93,29 :'DAC:=COS(DAC) ; DAC:=COS(X) 95 DATA E1 :'POP HL ; 97 DATA E5 :'PUSH HL ; 100 DATA CD,67,2C :'LD (HL),DAC ; Z:=COS(X)◀── "Прячем" результат в ; любую заранее зарезервированную ; группу ячеек памяти ; В нашем случае: Z ≡ X 110 DATA 2A,03,F3 :'LD HL,(F303h); HL содержит адрес переменной Y 120 DATA CD,5C,2C :'LD DAC,(HL) ; DAC:=Y 130 DATA CD,AC,29 :'DAC:=SIN(DAC) ; DAC:=SIN(Y) 140 DATA CD,4D,2C :'LD ARG,DAC ; ARG:=SIN(Y) 145 DATA E1 :'POP HL ; 147 DATA E5 :'PUSH HL ; 150 DATA CD,5C,2C :'LD DAC,(HL) ; DAC:=Z 160 DATA CD,9A,26 :'ADD DAC,ARG ; DAC:=Z+SIN(Y) 165 DATA E1 :'POP HL ; 170 DATA CD,67,2C :'LD (HL),DAC ; X:=DAC 180 DATA C9,"RET" :'RET 190 PRINT COS(X)+SIN(Y) 200 A=USR(A):PRINT X 'Результат \page 1.6.4. В о з в е д е н и е в с т е п е н ь ┌────────┬───────┬────────────────────┬───────────────────────┐ │ Имя │ │ │ │ │ подпро-│ Адрес │Выполняемые действия│ Т и п │ │ граммы │ │ │ │ ├────────┼───────┼────────────────────┼───────────────────────┤ │ SNGEXP │ 37C8h │ DAC := DAC^ARG │ Одинарная точность │ │ DBLEXP │ 37D7h │ DAC := DAC^ARG │ Двойная точность │ │ INTEXP │ 383Fh │ DAC := DE^HL │ Целая │ └────────┴───────┴────────────────────┴───────────────────────┘ П р и м е р 9. Вычислить 3² . ────────────── 10 CLEAR 200,&HF000:DEFUSR=&HF000 30 DATA 11,03,00 :'LD DE,0003h 40 DATA 21,02,00 :'LD HL,0002h 50 DATA CD,3F,38 :'CALL 383Fh 60 DATA 21,F6,F7 :'LD HL,F7F6h 70 DATA 11,00,F2 :'LD DE,F200h 80 DATA 01,10,00 :'LD BC,10h 90 DATA ED,B0 :'LDIR 130 DATA C9 :'RET 140 FOR T=0 TO 19:READ Z$:POKE &HF000+T,VAL("&h"+Z$):NEXT 150 X=USR(X) 160 FOR T=0 TO 15:PRINT HEX$(PEEK(&HF200+T));" ";:NEXT 1.6.5. С р а в н е н и е ┌────────┬───────┬─────────┬───────┬───────┬───────────────────────┐ │ Имя │ │ │ Левая │ Правая│ │ │ подпро-│ Адрес │ Тип │ часть │ часть │ Изменяемые регистры │ │ граммы │ │ │условия│условия│ │ ├────────┼───────┼─────────┼───────┼───────┼───────────────────────┤ │ FCOMP │ 2F21h │ Single │ CBED │ DAC │ HL │ │ ICOMP │ 2F4Dh │ Integer │ DE │ HL │ HL │ │ XDCOMP │ 2F5Ch │ Double │ ARG │ DAC │ A,B,C,D,E,H,L │ └────────┴───────┴─────────┴───────┴───────┴───────────────────────┘ Подпрограмма возвращает следующее содержимое регистра A -1, если левая часть условия < правой части условия, 0, если левая часть условия = правой части условия, 1, если левая часть условия > правой части условия. П р и м е р 10. Сравнение двух вещественных чисел. ────────────── 10 CLEAR 200,&HD000:DEFUSR=&HD000 20 DATA 21,00,00 :'LD HL,address(N1) 30 DATA CD,5C,2C :'LD DAC,(HL) 40 DATA 21,00,00 :'LD HL,address(N2) 50 DATA CD,50,2C :'LD ARG,(HL) 60 DATA CD,5C,2F :'Сравнить DAC и ARG 70 DATA 32,00,F1 :'LD (F100h),A 90 DATA C9 :'RET 100 FOR T=0 TO &H12:READ Z$:POKE &HD000+T,VAL("&h"+Z$):NEXT 110 INPUT"Left";N1:INPUT"Right";N2 120 A$=HEX$(VARPTR(N1)):B$=HEX$(VARPTR(N2)) 130 L1$=RIGHT$(A$,2):L2$=RIGHT$(B$,2) 140 H1$= LEFT$(A$,2):H2$= LEFT$(B$,2) 150 POKE &HD001,VAL("&h"+L1$):POKE &HD002,VAL("&h"+H1$) 160 POKE &HD007,VAL("&h"+L2$):POKE &HD008,VAL("&h"+H2$) 180 H=USR(H):A=PEEK(&HF100) 190 IF A=255 THEN PRINT"LEFT < RIGHT" 200 IF A=1 THEN PRINT"LEFT > RIGHT" 210 IF A=0 THEN PRINT"LEFT = RIGHT" 1.6.6. П р е о б р а з о в а н и е т и п о в ┌────────┬───────┬──────────────────────────────────────────────┐ │ Имя │ │ │ │ подпро-│ Адрес │ Выполняемые действия │ │ граммы │ │ │ ├────────┼───────┼──────────────────────────────────────────────┤ │ FRCINT │ 2F8Ah │ Содержимое DAC преобразуется к целому типу │ │ FRCSNG │ 2FB2h │ Содержимое DAC преобразуется к типу одинарной│ │ │ │ точности │ │ FRCDBL │ 303Ah │ Содержимое DAC преобразуется к типу двойной │ │ │ │ точности │ │ FIXER │ 30BEh │ DAC:=SGN(DAC)·INT(ABS(DAC)) │ └────────┴───────┴──────────────────────────────────────────────┘ После выполнения подпрограммы в ячейке с именем VALTYP будет находить- ся код типа числа, находящегося в DAC. 1.6.7. П р е о б р а з о в а н и е ч и с е л д л я в ы в о д а на п е ч а т ь Для преобразования из с т р о к и в ч и с л о используется подпро- грамма с именем ┌────────────────────────────────────────────────────────────────────┐ │ FIN (3299h) │ │ А р г у м е н т ы: HL - адрес строки символов, │ │ ───────────────── A - первый символ строки. │ │ Р е з у л ь т а т ы: DAC - вещественное число, │ │ ─────────────────── C - { 0 - была десятичная точка, │ │ { FFh - десятичной точки не было, │ │ B - количество цифр после десятичной точки, │ │ D - количество цифр в числе. │ └────────────────────────────────────────────────────────────────────┘ Для в ы в о д а имеются две подпрограммы: ┌─────────────────────────────────────────────────┐ │ FOUT (3425h) - неформатный вывод, │ │ PUFOUT (3426h) - форматный вывод. │ └─────────────────────────────────────────────────┘ Эти подпрограммы преобразуют число, находящееся в DAC, в строку симво- лов. Аргументы: A - формат; содержимое его битов может быть следующим: ───────── bit7: если 1, то вывод осуществляется по формату; bit6: если 1, то через каждые 3 цифры вставляются запятые; bit5: если 1, то первые нули заменить на символ "*"; bit4: если 1, то перед числом вставить символ "$"; bit3: если 1, то число выводится всегда со знаком; bit2: если 1, то вставить знак после числа; bit1: не используется; bit0:{если 0, то число выводится с фиксированной точкой; {если 1, то число выводится с плавающей точкой; B - количество цифр перед точкой; C - количество цифр после точки + 1. Результаты: HL - начальный адрес строки символов. ────────── П р и м е р 11. Вычисление косинуса вещественного числа. ────────────── 10 CLEAR 200,&HD000:DEFUSR=&HD000:A=&HD000 20 A=A+1:READ R$:IF R$="z" THEN 40 30 POKE A,VAL("&h"+R$):GOTO 20 40 M=USR(0) 50 DATA CD,B4,00 :'CALL 00B4h ;Ввод строки с клавиатуры 60 DATA 23 :'INC HL 70 DATA 7E :'LD A,(HL) 80 DATA CD,99,32 :'CALL 3299h ;Преобразование из строки в число 90 DATA 3E,08 :'LD A,08h 100 DATA 32,63,F6 :'LD (F663h),A ;VALTYP:=8 110 DATA CD,93,29 :'CALL 2993h ;Нахождение функции COS() 120 DATA CD,25,34 :'CALL 3425h ;Преобразование числа в строку 130 DATA 06,11 :'LD B,11h 140 DATA 7E :'LD A,(HL) ◀───┐ 150 DATA 23 :'INC HL │ 160 DATA CD,A2,00 :'CALL 00A2h ;Вывод символа на монитор │ 170 DATA 10,F9 :'DJNZ $-5 ;Конец цикла ───┘ 180 DATA C9 :'RET 190 DATA "z" Остальные подпрограммы перечислены ниже: ┌────────┬───────┬────────────────────────────────────────┐ │ Имя │ │ │ │ подпро-│ Адрес │ Выполняемые действия │ │ граммы │ │ │ ├────────┼───────┼────────────────────────────────────────┤ │ FOUTB │ 371Ah │ Целое число ──▶ в двоичный вид │ │ FOUTO │ 371Eh │ Целое число ──▶ в восьмеричный вид │ │ FOUTH │ 3722h │ Целое число ──▶ в шестнадцатеричный вид│ └────────┴───────┴────────────────────────────────────────┘ Для этих подпрограмм: А р г у м е н т ы: DAC - целое число, ───────────────── VALTYP = 2. Р е з у л ь т а т ы: HL - начальный адрес строки. ───────────────────