ПРИМЕНЕНИЕ АССЕМБЛЕРА ДЛЯ СОЗДАНИЯ БЫСТРОРАБОТАЮЩИХ ПРОГРАММ
Перевод с английского Пашорина В.И.
Редактирование текста "ИНФОРКОМ".
Окончание.
Начало см. с. 9-12, 48-61, 97-103, 139-144, 187-189.
10. ПЕРЕВОД БЕЙСИК-ПРОГРАММЫ В МАШИННЫЕ КОДЫ
Если Вы дошли до этой главы с ясным пониманием всего прочитанного, то примите поздравления, теперь у Вас не должно быть проблем с программированием в машинных кодах.
В этой же главе мы разберем способ создания игровой программы полностью в машинных кодах, используя в качестве примера программу на БЕЙСИКе. Мы полагаем, что, Вы уже умеете программировать на этом языке.
Весьма важно перед созданием любой программы отработать ее алгоритм в виде структурной схемы. Это облегчит выполнение перевода BASIC-программы в машинные коды. Мы займемся переводом в машинные коды игровой БЕЙСИК-программы "CROSS", что позволит приобрести навыки для перевода прочих собственных программ.
Идея игровой программы "CROSS" состоит в том, чтобы управляя перемещением человечка вернуть его домой целым и невредимым, несмотря на обилие всевозможных препятствий (Лист._1).
Главная программа включает в себя инициализацию программных переменных, вывод на экран инструкции пользователю и цикл перемещения человечка по экрану с определением его текущего положения. Существует две точки выхода из этого цикла:
1. Если человечек сталкивается с препятствием, то осуществляется переход к процедуре HIT и проводится проверка оставшегося числа жизней. Если это число равно нулю, то игра заканчивается, в противном случае осуществляется переход к основному циклу главной программы.
2. Выход к процедуре HOME. Здесь производится проверка числа занятых домов, а затем увеличивается значение скорости перемещения и добавляется еще один паук-людоед. Из процедуры HOME возврат осуществляется к основному циклу главной программы.
БЕЙСИК-программа довольно проста, хотя для задания UDG, цвета и звука, а также попиксельного перемещения экрана используются фрагменты в машинных кодах, так как на БЕЙСИКе это выполнялось бы крайне медленно. Машинные коды вводятся в программу через оператор РОКЕ. Хорошо разберитесь с работой БЕЙСИК-программы, потому что мы переходим к построчному переводу ее в машинные коды.
Листинг_1.
Программа CROSS на БЕЙСИКе (с сокращениями).
Внимание: Символы графики пользователя [UDG] в тексте программы взяты в квадратные скобки [...]. Они набираются в графическом режиме.
20 CLEAR 32243: GO TO 40
25 BEEP .01,b-a
30 PRINT OVER 1; PAPER 8; INK 8; AT a,y2; "[G]": RETURN
40 PRINT AT 11,5; "Please wait"
50...140 - запись кодов процедуры ROLL через цикл FOR...NEXT с помощью READ...DATA и POKE.
150 LET a=PEEK 23675 + 256*PEEK 23676
160 FOR b=a TO a+167: READ c: POKE b,c: NEXT c 180 DATA.... Данные по конструкции
............. символов UDG-графики
270 DATA..... (168 байтов)
280 PRINT AT 11,3; "Do you want instructions?";AT 13,11; "(Y)es"; AT 15,11;"(n)o" 290 LET a$=INKEY$: IF a$="" THEN GO TO 290 295 IF a$<>"y" THEN GO TO 400
300 CLS: PRINT AT 0,11;"OBJECT": PRINT: PRINT "To guide a [G] across a road and a river,
avoiding [AB] [CDE] [F] [GRRS] [TU]": 310 PRINT: PRINT "A [OP] patrols the central island.":
320 PRINT: PRINT "There are 4 HOMES to be filled. i.e. gaps in fence [NNN] [NNN]"
330 PRINT: PRINT "Once all 4 HOMES are filled the speed will increase, an extra spider is
added and the HOMES will empty" 340 PRINT AT 18,9; "Press any Key" 350 PAUSE 0
370 CLS: PRINT AT 7,11; "CONTROLS": PRINT
375 PRINT " ! 380 PRINT AT 11,6; "1"; FLASH 0
385 PRINT AT 18,5; "Press any Key to PLAY" 390 PAUSE 0
400 BRIGHT 1: PAPER 5: BORDER 5: CLS 410 LET hi=0
420 PRINT PAPER 4; AT 10,0;"
<0>"; FLASH 1 FLASH 0;" 2 3 4 5 6 7 8
LET score=0: LET home=0: POKE 32425,201: POKE 32450,201: POKE 32469,201
450 PRINT AT 0,0; PAPER 4; "[NNNN]"; PAPER 7;
PAPER 4 PAPER 4 PAPER 4 PAPER 4
455 IF home<>0 THEN GO TO 660
'[NNNNNN]"; PAPER 7;" ' '[NNNNNNN]"; PAPER 7;"
'[NNNNNNN]"; PAPER 7;" [
460 PRINT PAPER 4 470 PRINT 480 PRINT INK 7 490 PRINT INK 2 500 PRINT INK 7 510 PRINT INK 1 520 PRINT INK 7 530 PRINT 540 PRINT PAPER 4 550 PRINT PAPER 0 560 PRINT PAPER 0 570 PRINT PAPER 0 580 PRINT PAPER 0 590 PRINT PAPER 0 600 PRINT PAPER 0 610 PRINT PAPER 0 620 PRINT PAPER 0 630 PRINT PAPER 4 640 PRINT PAPER 4 650 PRINT PAPER 1 [QRRRS QRRRS QRRSB QRRS [ MMM MMMM MMM MM [ TU TU TU TU TU [MM M MMMMM MMM [ RS QRRS QRRRRS [ MM MMMMMMM MMM [U TU TU TU [NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN [NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
SCORE ";AT 21,11;" MEN "; PAPER 5; INK 0; " LIVES "; PAPER 1; INK
INK 7 7; " HI SCORE " 660 LET X1=20: LET y1 = 16: LET x2=x1: LET y2=y1 670 PRINT PAPER 8; INK 8; AT x1,y1; " " 680 RANDOMIZE USR 32295 690 IF SCREEN$ (x2,y2)=" " THEN GO TO 880 700 LET a=x2: FOR b=25 TO 35: GO SUB 25: GO SUB 25: NEXT b 730 FOR a=x2 TO 20 STEP 2: GO SUB 25: GO SUB 25: NEXT a 740 LET lives=lives-1: PRINT AT 21,16; lives 750 LET x2 = 20
760 IF lives <> 0 THEN GO TO 680
770 IF hi >score THEN GO TO 790
780 LET hi = score: PRINT AT 21,27; hi
790 PRINT FLASH 1; PAPER 7; AT 12,0; " GAME OVER
800 PRINT AT 14,0; "Another game? (y)es (n)o "
[ AB F AB CDCDE
[ AB AB
AB AB
EDCDC
[NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
840 IF INKEY$ = "n" THEN RANDOMIZE USR 0 850 IF INKEY$ <> "y" THEN GO TO 840 860 PRINT PAPER 5; AT 21,7;" ": GO TO 480 880 IF x2<>0 THEN GO TO 1050
890 PRINT PAPER 8; INK 8; AT x1,y1;" ": PRINT AT x2,y2;"[G]" 900 RESTORE 920: FOR a=1 TO 8: READ b,c 910 BEEP b,c: NEXT a
920 DATA .1,11,.1,11,.8,16,.05,11,.05,16,.05,11,.05,16,1,20
930 LET home=home+1: LET score=score+50: PRINT AT 21,7; score
950 IF home/4<>INT(home/4) THEN GO TO 660
960 IF home=4 THEN POKE 32425,0
970 IF home=8 THEN POKE 32450,0
980 IF home=12 THEN POKE 32469,0
985 IF home>36 THEN GO TO 450
990 LET a=RND*30
1000 LET a=a+1
1005 IF a>31 THEN LET a=0
1010 IF SCREEN$(10,a)="" THEN GO TO 1000
1020 IF SCREEN$(10,a+1) = "" THEN GO TO 1000
1030 PRINT PAPER 4; AT 10,a; "[OP]"
1035 RESTORE 920: FOR a=1 TO 8: READ b,c: BEEP b,c: NEXT a 1040 GO TO 450
1050 PRINT PAPER 8; INK 8; AT x2,y2; "[G]" 1060 LET x1=x2: LET y1=y2 1070 IF INKEY$ <> "1" THEN GO TO 1100 1080 BEEP .001,33
1090 LET x2=x2-2: LET score=score+5: PRINT AT 21,7; score 1100 LET y2=y2+(INKEY$="0" AND y2<>31)-(INKEY$="9" AND y2<>0) 1110 GO TO 670
СТРОКА 20. Эта строка не нужна в окончательной версии, так как она устанавливает верхнюю границу RAMTOP для БЕЙСИК-программы.
СТРОКИ 25 и 30. Это две строки подпрограммы, вызываемой в строках 700 и 730. Размещение ее в начальных строках необходимо для сокращения времени поиска при вызове этой подпрограммы, так как всегда поиск нужных подпрограмм начинается с начальных строк БЕЙСИКа. Машинные коды, соответствующие этим двум строкам, размещаются в участке памяти, где будет записана процедура HIT.
СТРОКА 40. Для того, чтобы ввести фрагменты программы в кодах с помощью РОКЕ требуется время. Поэтому в БЕЙСИК-программе и введена эта строка с сообщением о необходимости немного подождать. В программе, написанной полностью в кодах, давать такое сообщение, конечно, нет необходимости.
СТРОКИ 50... 140. Это строки для ввода через POKE процедуры "ROLL", обеспечивающей попиксельное смещение изображения на экране. Понятно, что для программы в машинных кодах эту операцию выполнять также не нужно, так как эти коды будут записаны в соответствующие адреса при загрузке программы в память (см. листинг процедуры ROLL в конце статьи).
СТРОКИ 150...270. Это первые строки, которые нуждаются в преобразовании для перехода к программе в машинных кодах. Здесь осуществляется запись в область UDG всех графических элементов пользователя, так как этот участок памяти занимает 158 байтов, то и в строках DATA записаны 168 чисел, определяющих форму UDG.
В дальнейшем, конечно, для задания UDG мы будем непосредственно записывать в участок памяти UDG значение этих 168 байтов. Сначала мы разместим данные, характеризующих форму UDG, начиная с адреса 24001, а затем перешлем их в участок памяти UDG, использовав команду LDIR. При этом в регистровую пару DE записывается начальный адрес участка UDG из системной переменной 5С7В (83675), а в регистровую пару HL начальный адрес данных, характеризующих форму UDG. Процедура пересылки, написанная в машинных кодах, размещается сразу же за данными 168 байтами. Вызов этой процедуры поэтому производится по команде RANDOMIZE USR 24169.
|
UDG- |
графика. |
|
|
|
5DC1H |
|
|
|
|
|
|
|
DEFB |
0F |
12 |
22 |
7F |
FF |
FF |
28 |
10 |
DEFB |
80 |
40 |
20 |
FE |
FE |
FF |
28 |
10 |
DEFB |
7F |
7F |
7F |
7F |
7F |
FF |
15 |
08 |
DEFB |
FF |
FE |
FE |
FE |
FF |
FF |
40 |
80 |
DEFB |
00 |
F8 |
C4 |
C4 |
FE |
FE |
28 |
10 |
DEFB |
18 |
18 |
24 |
7E |
3C |
5A |
A5 |
42 |
DEFB |
38 |
28 |
92 |
72 |
38 |
38 |
28 |
6C |
DEFB |
01 |
02 |
04 |
7F |
7F |
FF |
14 |
08 |
DEFB |
F0 |
48 |
44 |
FE |
FF |
FF |
14 |
08 |
DEFB |
00 |
1F |
23 |
23 |
7F |
7F |
14 |
08 |
DEFB |
7F |
7F |
7F |
7F |
FF |
FF |
02 |
01 |
DEFB |
FE |
FE |
FE |
FE |
FE |
FF |
A8 |
10 |
DEFB |
10 |
29 |
C7 |
00 |
26 |
00 |
00 |
00 |
DEFB |
00 |
44 |
FF |
44 |
44 |
FF |
44 |
00 |
DEFB |
00 |
22 |
55 |
8F |
97 |
A3 |
A0 |
00 |
DEFB |
00 |
44 |
AA |
F1 |
E9 |
C5 |
05 |
00 |
DEFB |
10 |
10 |
10 |
FE |
3F |
IF |
0F |
07 |
DEFB |
00 |
00 |
00 |
00 |
1E |
FF |
FF |
FF |
DEFB |
60 |
7C |
54 |
78 |
7F |
FF |
FE |
7C |
DEFB |
00 |
00 |
03 |
02 |
0F |
3F |
FF |
00 |
DEFB |
05 |
0C |
96 |
F0 |
E0 |
55 |
FF |
00 |
5E69
24169 LD DE,(5C7B) 24173 LD HL,5DC1 24175 LD BC,00AB 24179 LDIR 24181 JR,5EA2
СТРОКА 280. Сообщение, выводимое на экран по команде PRINT в этой строке, можно выводить на экран, используя процедуру ОЗУ, находящуюся по адресу 3252 (203СН). Машинные коды этой процедуры записаны в участке 5ЕА2... 5EAF, а сам текст сообщения - в участке 5Е77...5ЕА1 (Листинг-4).
Печать сообщения.
5E77H
DEFB |
16 |
0B |
03 |
44 |
5F |
20 |
79 |
6F |
DEFB |
75 |
20 |
77 |
61 |
6E |
74 |
20 |
69 |
DEFB |
6E |
73 |
74 |
72 |
75 |
63 |
74 |
69 |
DEFB |
6F |
6E |
73 |
3F |
16 |
0D |
0B |
28 |
DEFB |
79 |
29 |
65 |
73 |
16 |
0F |
0B |
28 |
DEFB |
6E |
29 |
6F |
|
|
|
|
|
5EA2
24225 LD A,02 24228 CALL 1601H 24231 LD DE,5E77H 24234 LD BC,002BH 24237 CALL 203CH
СТРОКИ 290 и 295. Эти строки необходимы, чтобы приостановить выполнение программы до тех пор, пока не будет нажата клавиша. Если будет нажата клавиша "y", то на экране появится инструкция по правилам игры. Если же будет нажата любая другая клавиша, то произойдет переход к адресу 608AH. Машинные коды, соответствующие этим строкам, записаны по адресу с 5ЕВ0Н по 5ЕВЕН (Лист.5)
Проверка нажатия клавиши "y".
24240 HALT
24241 BIT 5,(IY+01) 24245 JR Z,-07
24247 LD A,(5C08H) 24250 CP 79 24252 JP NZ,608AH
СТРОКА 300:1 CLS - Перевод этой команды в машинные коды мы уже разбирали (Листинг-6).
Очистка экрана.
5EBFH
24255 LD A,02 24257 CALL 1601H 24260 CALL 0D6BH 24263 JP 5F73H
СТРОКИ 300:2...350. Для вывода сообщений на экран снова будем использовать процедуру вывода на экран последовательности символов ПЗУ, коды которых записаны в участок памяти с именем DATA. Коды символов первого сообщения находятся в памяти с 5ЕСАН по 5F72H, а второго сообщения 5F84H...5FF9H. Процедуры же вывода PRINT DATA находятся соответственно 5F73H...5F83H и 5FFAH... 6002Н (Листинг_7).
В ячейках с 6003H по 600CH находятся машинные коды, реализующие команду PAUSE 0. Не забывайте, что бит 5 переменной 23611 (IY+1) должен быть сброшен (ожидание нажатия клавиши).
Печать сообщений, пауза.
5ECAH |
|
|
|
|
|
|
|
DEFB 16 |
00 |
0B |
4F |
42 |
4A |
45 |
43 |
DEFB 54 |
0D |
0D |
54 |
6F |
20 |
67 |
75 |
DEFB 69 |
64 |
65 |
20 |
61 |
20 |
96 |
20 |
DEFB 61 |
63 |
72 |
6F |
73 |
73 |
20 |
61 |
DEFB 20 |
72 |
6F |
61 |
64 |
20 |
61 |
6E |
DEFB 64 |
20 |
61 |
72 |
69 |
76 |
65 |
72 |
DEFB 2C |
61 |
76 |
6F |
69 |
64 |
69 |
6E |
DEFB 67 |
20 |
90 |
91 |
20 |
92 |
93 |
94 |
DEFB 20 |
95 |
20 |
A0 |
A1 |
A1 |
A2 |
20 |
DEFB A3 |
A4 |
0D |
0D |
41 |
20 |
9E |
9F |
DEFB 20 |
70 |
61 |
74 |
72 |
6F |
6C |
73 |
DEFB 20 |
74 |
68 |
65 |
20 |
63 |
65 |
6E |
DEFB 74 |
72 |
61 |
6C |
20 |
69 |
73 |
6C |
DEFB 61 |
6E |
64 |
EE |
0D |
0D |
54 |
68 |
DEFB 65 |
72 |
65 |
20 |
61 |
72 |
65 |
20 |
DEFB 34 |
20 |
48 |
4F |
4D |
45 |
53 |
20 |
DEFB 74 |
6F |
20 |
62 |
65 |
20 |
66 |
69 |
DEFB 6C |
6C |
65 |
64 |
2E |
20 |
69 |
2E |
DEFB 65 |
2E |
20 |
67 |
61 |
70 |
73 |
20 |
DEFB 69 |
6E |
20 |
65 |
65 |
6E |
63 |
65 |
DEFB 20 |
9D |
9D |
9D |
20 |
9D |
9D |
9D |
DEFB 0D |
|
|
|
|
|
|
|
5F73H |
|
|
|
|
|
|
|
24435 |
LD |
A,02 |
|
|
|
|
24437 |
CALL |
601H |
|
|
|
24440 |
LD |
DE |
,5ECAH |
|
|
|
24443 |
LD |
BC |
00A9H |
|
|
|
24446 |
CALL |
03CH |
|
|
|
24449 |
JP |
5FFAH |
|
|
|
|
5FB4H |
|
|
|
|
|
|
|
DEFB 0D |
4F |
6E |
63 |
65 |
20 |
61 |
6C |
DEFB 6C |
20 |
34 |
20 |
48 |
4F |
4D |
45 |
DEFB 53 |
20 |
61 |
72 |
65 |
20 |
66 |
69 |
DEFB 6C |
6C |
65 |
64 |
20 |
74 |
68 |
65 |
DEFB 20 |
73 |
70 |
65 |
65 |
64 |
20 |
77 |
DEFB |
59 |
6C |
6C |
20 |
69 |
6E |
63 |
72 |
DEFB |
65 |
61 |
73 |
65 |
2C |
20 |
61 |
6E |
DEFB |
20 |
65 |
78 |
74 |
72 |
61 |
20 |
73 |
DEFB |
70 |
69 |
64 |
65 |
72 |
20 |
59 |
73 |
DEFB |
20 |
61 |
64 |
64 |
65 |
64 |
20 |
61 |
DEFB |
6E |
64 |
20 |
74 |
68 |
65 |
20 |
48 |
DEFB |
4F |
4D |
45 |
53 |
20 |
77 |
69 |
6C |
DEFB |
6C |
65 |
6D |
70 |
74 |
79 |
16 |
12 |
DEFB |
09 |
50 |
72 |
65 |
73 |
73 |
20 |
61 |
DEFB |
6E |
79 |
20 |
6B |
65 |
79 |
|
|
5FFAH
24570 LD DE,5F84H 24573 LD BC,0076H 24576 CALL 203CH 24579 RES 5,(IY+01)
24583 HALT
24584 BIT 5,(IY+01) 24568 JR Z,-07
СТРОКА 370: 1 CLS. В участке памяти с 600E по 6012 записаны машинные коды процедуры очистки экрана. Здесь применяется другой способ, основанный на применении процедуры ПЗУ 0E44^ которая очищает столько строк экрана (считая снизу), сколько установлено в регистре B(Листинг_8).
Очистка экрана.
600EH
24590 LD B,18H 2459E CALL 0E44H 24595 JP 6076H
СТРОКИ 370:2...390. Коды символов, выводимых на экран, записаны в участке 6016Н... 6075Н, а сама же процедура печати находится в адресах - 6076Н... 607ЕН. Здесь опять же имеются машинные коды, реализующие команду PAUSE 0 (Листинг_9).
Печать сообщений, пауза.
6015H
DEFB |
16 |
07 |
0B |
43 |
4F |
4E |
54 |
52 |
DEFB |
4F |
4C |
53 |
0D |
0D |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
5E |
20 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
3C |
30 |
3E |
12 |
01 |
DEFB |
16 |
0B |
06 |
31 |
12 |
00 |
20 |
32 |
DEFB |
20 |
33 |
20 |
34 |
20 |
35 |
20 |
36 |
DEFB |
20 |
37 |
20 |
38 |
30 |
12 |
01 |
39 |
DEFB |
12 |
00 |
20 |
12 |
01 |
30 |
12 |
00 |
DEFB |
16 |
12 |
05 |
50 |
72 |
65 |
73 |
73 |
DEFB |
20 |
61 |
6E |
79 |
20 |
6B |
65 |
79 |
DEFB |
20 |
74 |
6F |
20 |
50 |
4C |
41 |
59 |
6076H
24694 LD DE,6016H 24897 LD BC,0060H 24700 CALL 203CH 24703 RES 5,(IY+01)
24707 HALT
24708 BIT 5,(IY+01) 24712 JR Z,-07
Строка 400. В первой главе обсуждался порядок перевода всех операторов этой строки в машинные коды. Вызов процедуры CLS здесь необходим для установки на экране соответствующих атрибутов, как и в БЕЙСИК-программе. Машинные коды записаны в
участке 608АН...609BH.
Установка атрибутов
608AH
24714 LD A,05
24716 CALL 229BH
24719 LD A,68H
24721 LD (5C8D),A
24724 LD A,02
24725 CALL 1601H
СТРОКА 410. В этой строке переменной hi, являющейся показателем достигнутого уровня, присваивается нулевое начальное значение. Полагая, что значение этой переменной не может быть больше 65535, выделим в буфере принтера 2 байта для хранения значения этой переменной. Соответствующие этому оператору машинные коды записаны в участке памяти 609СН ...60А1Н.
Инициализация переменной hi.
609CH
24732 LD HL,0000
24735 LD (5B00H),HL
24738 JR +25H
СТРОКА 420. Коды символов сообщения, выводимого на экран, записаны в адресах 60А4Н...60С8Н. Процедура печати - 60С9Н...60D6H.
Печать строки.
60A4H
DEFB |
11 |
04 |
16 |
0A |
00 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
20 |
9E |
9F |
20 |
20 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
20 |
20 |
|
|
|
60C9H
24777 LD A,02
24779 CALL 1601H 24782 LD DE,60A4H 24785 LD BC,0025H
24788 CALL 203CH
СТРОКА 430. В этой строке определяются исходные значения количества "жизней", занятых домов и достигнутого уровня. Эти значения также хранятся в буфере принтера по следующим адресам:
количество "жизней" - 5В02 достигнутый уровень - 5В03/4 количество домов - 5В05
Машинные коды, соответствующие этой строке, см. 60D7H...60E5H.
Инициализация переменных.
60D7H
24791 LD A,09 24793 LD(5B02H),A 24796 LD HL,0000 24799 LD (5B03H),HL
24802 XOR A
24803 LD (5B05),A
СТРОКА 440. Операторы этой строки обнуляют скорость перемещения и устанавливают команды RET в соответствующих ячейках подпрограммы LINE ROLL.
Машинные коды см. 60E6H...60F3H.
Коррекция процедуры ROLL.
60E6H
24806 LD A,C9H
24808 LD (7EA9H),A
24811 LD (7EC2H),A
24814 LD (7ED5H),A
24817 JP 6129H
СТРОКА 450. Коды символов этой строки и процедура печати:
Печать строки.
60F4H
DEFB |
16 |
00 |
00 |
11 |
04 |
9D |
9D |
9D |
DEFB |
9D |
11 |
07 |
20 |
11 |
04 |
9D |
9D |
DEFB |
9D |
9D |
9D |
9D |
11 |
07 |
20 |
11 |
DEFB |
04 |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
DEFB |
11 |
07 |
20 |
11 |
04 |
9D |
9D |
9D |
DEFB |
9D |
9D |
9D |
9D |
11 |
07 |
20 |
11 |
DEFB |
04 |
9D |
9D |
9D |
9D |
|
|
|
6129H
24873 LD A, 24875 CALL 1601H 24878 LD DE,60F4H 24881 LD BC,0035 24884 CALL 203CH
СТРОКА 455. В этой строке проверяется количество домов и, если оно равно нулю, то осуществляется перевод к строке 660. Для реализации этой строки в машинных кодах необходимо извлечь содержимое ячейки 5В05Н, где записано количество домов, записать это значение в регистр A и использовать для проверки на нулевое значение команду AND А. Если флаг нуля (ZERO) после этой операции не будет установлен, то осуществляется переход к процедуре PRINT DISPLAY. Если же этот флаг не включен, то эта процедура пропускается и начинается игра. Машинные коды, соответствующие этой строке, записаны в ячейках 6137H...6140K
Проверка переменной home.
6137H
24687 LD A,(5B05H)
24890 AND A
24891 JP NZ,641EH 24894 JP 63D2H
СТРОКИ 460...640. Машинные коды, соответствующие этим строкам, занимают большой объем памяти. Коды всех символов сообщений этих строк записаны в участке памяти 6141Н... 63D1H, а процедура печати - 63D2H...63DFH.
Инициализация экрана.
6141H |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DEFB |
11 |
04 |
10 |
05 |
8C |
8C |
8C |
8C |
DEFB |
9C |
9C |
20 |
20 |
20 |
20 |
20 |
9C |
DEFB |
9C |
9C |
20 |
20 |
20 |
20 |
10 |
01 |
DEFB |
8C |
8C |
8C |
8C |
8C |
8C |
8C |
8C |
DEFB |
9C |
9C |
20 |
20 |
20 |
20 |
20 |
20 |
DEFB |
A1 |
A2 |
20 |
20 |
20 |
20 |
20 |
00 |
DEFB |
8C |
8C |
8C |
8C |
8C |
8C |
8C |
8C |
DEFB |
9C |
10 |
02 |
20 |
20 |
A3 |
A4 |
20 |
DEFB |
A1 |
A1 |
A2 |
20 |
20 |
20 |
20 |
20 |
DEFB |
8C |
8C |
8C |
8C |
11 |
05 |
10 |
00 |
DEFB |
20 |
20 |
20 |
20 |
A3 |
A4 |
20 |
20 |
DEFB |
20 |
A0 |
A1 |
A1 |
A1 |
A1 |
AE |
20 |
DEFB |
20 |
A0 |
A1 |
A1 |
A2 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
A3 |
A4 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
20 |
A0 |
A1 |
A1 |
A1 |
DEFB |
A0 |
A1 |
A1 |
A1 |
A2 |
20 |
20 |
20 |
DEFB |
20 |
A3 |
A4 |
20 |
20 |
20 |
20 |
20 |
DEFB |
10 |
07 |
20 |
20 |
20 |
9C |
9C |
20 |
DEFB |
20 |
A0 |
A1 |
A1 |
A3 |
20 |
20 |
20 |
DEFB |
20 |
A3 |
A4 |
20 |
10 |
07 |
9C |
9C |
DEFB |
20 |
9C |
9C |
9C |
9C |
9C |
20 |
20 |
DEFB |
A0 |
A1 |
A1 |
A2 |
20 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
9C |
20 |
20 |
20 |
20 |
DEFB |
20 |
9C |
9C |
20 |
E0 |
20 |
20 |
20 |
DEFB |
10 |
07 |
20 |
20 |
20 |
9C |
9C |
9C |
DEFB |
20 |
20 |
9C |
9C |
9C |
9C |
9C |
20 |
DEFB |
20 |
9C |
9C |
9C |
20 |
20 |
20 |
80 |
DEFB |
20 |
20 |
20 |
20 |
20 |
9C |
9C |
9C |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
9C |
DEFB |
20 |
20 |
10 |
00 |
A4 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
A3 |
A4 |
DEFB |
07 |
2D |
2D |
2D |
2D |
2D |
3D |
2D |
DEFB |
07 |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
DEFB |
20 |
20 |
20 |
20 |
20 |
A3 |
A4 |
20 |
DEFB |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
DEFB |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
DEFB |
20 |
20 |
20 |
20 |
20 |
A3 |
A4 |
20 |
DEFB |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
DEFB |
2D |
2D |
2D |
2D |
2D |
ED |
2D |
2D |
DEFB |
20 |
20 |
20 |
A3 |
11 |
04 |
9D |
9D |
DEFB |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
DEFB |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
2D |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
DEFB |
2D |
10 |
05 |
20 |
90 |
92 |
20 |
20 |
DEFB |
2D |
10 |
06 |
9A |
9B |
20 |
20 |
20 |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
DEFB |
20 |
20 |
90 |
91 |
20 |
20 |
20 |
E0 |
DEFB |
97 |
98 |
20 |
20 |
97 |
98 |
20 |
95 |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
DEFB |
90 |
91 |
20 |
20 |
90 |
91 |
20 |
20 |
DEFB |
20 |
20 |
95 |
20 |
20 |
99 |
9A |
9B |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
11 |
00 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
90 |
91 |
DEFB |
9A |
9B |
20 |
20 |
20 |
95 |
20 |
20 |
DEFB |
10 |
07 |
16 |
0B |
00 |
9D |
9D |
9D |
DEFB |
20 |
20 |
20 |
10 |
07 |
3D |
3D |
3D |
DEFB |
20 |
20 |
99 |
11 |
04 |
10 |
00 |
9D |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
DEFB |
3D |
3D |
3D |
3D |
3D |
3D |
3D |
3D |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
DEFB |
3D |
3D |
3D |
3D |
3D |
3D |
3D |
3D |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
DEFB |
3D |
3D |
3D |
3D |
3D |
3D |
3D |
3D |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
DEFB |
9D |
9D |
9D |
9D |
9D |
10 |
03 |
80 |
DEFB |
3D |
3D |
3D |
3D |
3D |
10 |
04 |
98 |
DEFB |
9D |
9D |
9D |
9D |
9D |
9D |
9D |
11 |
DEFB |
90 |
91 |
20 |
95 |
20 |
20 |
90 |
91 |
DEFB |
20 |
20 |
20 |
20 |
20 |
97 |
98 |
20 |
DEFB |
04 |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
DEFB |
20 |
20 |
92 |
93 |
92 |
93 |
94 |
20 |
DEFB |
20 |
20 |
97 |
98 |
20 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
DEFB |
95 |
20 |
95 |
20 |
20 |
20 |
92 |
93 |
DEFB |
20 |
20 |
20 |
97 |
98 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
DEFB |
94 |
20 |
20 |
20 |
20 |
20 |
20 |
10 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
97 |
10 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
63D2H
25554 LD A,02
25556 CALL 1601H
25559 LD DE,6141H 25562 LD BC,0291H 25565 CALL 203CH
СТРОКА 650. Для реализации этой строки в машинных кодах необходимо предварительно преобразовать число, записанное в ячейке 5В02Н. Для этого оно извлекается из этой ячейки, суммируется с числом 48 и результат записывается в ячейку 6402. Машинные коды этой операции 63Е0Н...63Е9Н. Коды символов сообщения для вывода на экран записаны в 63EAH...640FH, а процедура печати - 6410H...641EH.
Инициализация строки результата
63E0H
25568 LD A,(5B02H) 25571 ADD A,30 25573 LD (6401H),A 25576 JR +26
63EAH
DEFB |
11 |
01 |
10 |
07 |
20 |
53 |
43 |
4F |
DEFB |
52 |
45 |
20 |
16 |
15 |
0B |
20 |
4D |
DEFB |
45 |
4E |
20 |
11 |
05 |
10 |
00 |
39 |
DEFB |
11 |
01 |
10 |
07 |
20 |
48 |
49 |
2D |
DEFB |
53 |
43 |
4F |
52 |
45 |
20 |
|
|
6410H
25616 LD A,02
25618 CALL 1601H
25621 LD DE,63E1H 25624 LD BC,0026H 25627 CALL 203CH
СТРОКА 660. В этой строке определяются исходные координаты положения человечка на экране x1 и y1, а также координаты его нового положения x2 и y2. Для программы в машинных кодах эти координаты хранятся также в буфере принтера: x1 - 5B06H x2 - 5B08H y1 - 5B07H y2 - 5B09H
Для записи в буфер принтера координат лучше использовать шестнадцатиричную систему счисления, тогда процедура записи будет иметь следующий вид:
Инициализация координат героя.
641FH
25630 LD HL,1014H
25633 LD (5B06H),HL
25636 LD (5B08H),HL
Из этого примера понятно, что использовать десятичную систему счисления для записи координат в регистровую пару HL не удобно, т.к. трудно будет представить положение объекта на экране.
СТРОКА 670. Поскольку здесь необходимо выводить на экран только один символ, то лучше использовать команду RST 10H.
|
Печать героя. |
6427H |
|
25639 |
LD A,02 |
25641 |
CALL 1601H |
25644 |
LD A,11H |
25646 |
RST 10H |
25647 |
LD A,08 |
25649 |
RST 10H |
25650 |
LD A,10H |
25652 |
RST 10H |
25653 |
LD A,08 |
25655 |
RST 10H |
25656 |
LD A,16H |
25658 |
RST 10H |
25659 |
LD A,(5B06H) |
25662 |
RST 10H |
25663 |
LD A,(5B07H) |
25666 |
RST 10H |
25667 |
LD A,20H |
25669 |
RST 10H |
СТРОКА 680. В этой строке производится вызов процедуры ROLL, записанной в машинных кодах с адреса 7Е27Н. Код, соответствующий этой строке:
Вызов процедуры ROLL.
6446H
25670 CALL 7E27H
СТРОКА 690. в этой строке проверяется состояние символьной ячейки с координатами x2, y2. Для реализации этой строки в машинных кодах будем использовать процедуру SCREEN$, описанную в главе 8, передающую значение параметров исследуемой ячейки на стек калькулятора и затем в регистры A,B,C,D,E. Для определения состояния ячейки используем:
LD A,(DE)
CP 20Н
Помните, что для продолжения программы, после использования калькуляторного стека, необходимо очистить рабочий участок. Если в исследуемой ячейке не пробел, то осуществляется переход к процедуре HIT, которая начинается с адреса 6548Н. В БЕЙСИК-программе соответственно переход к строке 880. Машинные коды, соответствующие этой строке записаны в участке 6449K..645DH.
Проверка местоположения героя.
6449H
25673 LD BC,(5B08H)
25677 CALL 2538H
25680 CALL 2BF1H
25683 LD A,(DE)
25684 PUSH AF
25685 CALL 16BFH
25688 POP AF
25689 CP 20H 25691 JP NZ,6548H
СТРОКА 880. В этой строке проверяется: достиг ли человечек вершины экрана, т.е. дошел ли он до дома. В машинных кодах для этого записываем значение координаты x2 в регистр A:
LD A,(5B08)
и сравниваем это значение с нулем. Если это значение равно нулю, то выполняется переход к процедуре HOME, которая начинается с адреса 66А6Н. В Бейсик-программе соответственно осуществляется переход к строке 1050. Машинные коды, соответствующие этой строке 645ЕН...6465Н.
Проверка достижения "дома"
645EH
25694 LD A,(5B08H)
25697 CP 00
25699 JP Z,66A6H
СТРОКА 1050. Здесь также для вывода на экран одного символа в позицию с координатами x2, y2 лучше использовать команду RST 10H, как и в строке 670. Машинные коды - 6466Н... 6484Н.
Печать героя в новой координате
6466H |
|
25702 |
LD A,02 |
25704 |
CALL 1601H |
25707 |
LD A,11 |
25709 |
RST 10H |
25710 |
LD A,08 |
25712 |
RST 10H |
25713 |
LD A,10H |
25715 |
RST 10H |
25716 |
LD A,08 |
25718 |
RST 10H |
25719 |
LD A,16H |
25721 |
RST 10H |
25722 |
LD A,(5B08H) |
25725 |
RST 10H |
25726 |
LD A,(5B09H) |
25729 |
RST 10H |
25730 |
LD A,96H |
25733 |
RST 10H |
СТРОКА 1060. Для реализации этой строки в машинных кодах достаточно переписать значение ячеек 5B08 и 5В09 в ячейки 5В06 и 5В07 соответственно.
Запоминание новой координаты.
6485H
25733 LD HL,(5B08H)
25736 LD (5B06H),HL
СТРОКА 1070. Чтобы улучшить работу програлмы в машинных кодах для проверки состояния клавиатуры и контроля нажатия клавиши лучше использовать не системную переменную LAST KEY, а непосредственно команду IN A,(C). Причем, чтобы проверить нажата ли клавиша "1", достаточно проверить состояние только клавиш "1"..."5" так, как это описано в главе 5. Машинные коды - 648ВН...6493Н.
Проверка нажатия клавиши "1".
648BH
25739 LD BC,F77EH 25742 IN A,(C) 25744 BIT 0,A 25746 JR NZ,+1C
СТРОКА 1080. Поскольку длительность и тональность звукового сигнала принципиального значения не имеют, то для реализации этой строки в машинных кодах достаточно только вызвать процедуру BEEP из ПЗУ - CALL 03B5H.
Генерация звукового сигнала.
6494H
25748 LD HL,0032H 25751 LD DE,0005H 25754 CALL 03B5H
СТРОКА 1090. Для записи этой строки в машинных кодах необходимо извлечь содержимое ячейки 5В08 и вычесть из этого значения число 2, а результат вновь записать в эту же ячейку. Значение текущего счета, записанное в ячейках 5В03/4, увеличивается на 5 и вновь записывается в эти ячейки. Машинные коды этих операций - 649DH...64AFH. Для вывода на экран текущего значения счета используются процедуры STACK ВС и PRINT VALUE ON STACK, но первоначально определяются параметры PRINT AT. Машинные коды -64В1Н...64С8Н.
Коррекция счета (score).
649D2H |
|
25757 |
LD A,(5B08H) |
25760 |
DEC A |
25761 |
DEC A |
25763 |
LD (5B08H),A |
25765 |
LD HL,(5B03H) |
25768 |
INC HL |
25769 |
INC HL |
25770 |
INC HL |
25771 |
INC HL |
25772 |
INC HL |
25773 |
LD (5B03H),HL |
25776 |
NOP |
25777 |
LD A,02 |
25779 |
CALL 1601H |
25782 |
LD A,16H |
25785 |
LD A,15H |
25787 |
RST 10H |
25788 |
LD A,07 |
25790 |
RST 10H |
25791 |
LD BC,(5B03H) |
25795 |
CALL 2D2BH |
25798 |
CALL 2DE3H |
СТРОКА 1100. Опять же, для чтения состояния клавиатуры и установки значения y2 используем команду IN A,^). В программе в машинных кодах добавлена процедура, которой нет в БЕЙСИК программе. В участке памяти 64F3H...64F4H записаны машинные коды, которые составляют процедуру проверки нажатия клавиши "6". Если эта клавиша нажата, то осуществляется выход из программы. На этом главный цикл программы заканчивается.
Если теперь Вы запустите эту программу, то перемещение человечка по экрану будет настолько быстрым, что Вы не будете его замечать. Поэтому необходимо в главный цикл программы в машинных кодах включить замедляющую процедуру.
Этот же эффект можно получить, если в главный цикл включить дополнительно процедуру музыкального сопровождения перемещения. Машинные коды этой процедуры 64F5H...650ВН. Завершающей командой главного цикла является команда JP 6427, обеспечивающая переход на начало главного цикла. В БЕЙСИК-программе это выполняется переходом к строке 670.
Опрос клавиатуры, музыка.
64C9H |
|
25801 |
LD BC,EFFEH |
25804 |
IN A,(C) |
25806 |
BIT 0,A |
25808 |
JR NZ,+0EH |
25810 |
LD A,(5B09H) |
25813 |
CP 1F |
25815 |
JR Z,+01 |
25817 |
INC A |
25818 |
LD (5B09H),A |
25831 |
JP 64F5H |
25834 |
BIT 1,A |
25836 |
JR NZ,02 |
25838 |
LD A,(5B09H) |
25831 |
CP 00 |
25833 |
JR Z,+01 |
25835 |
DEC A |
25836 |
LD (5B09H),A |
25839 |
JP 64F5H |
64F3H |
|
25843 |
BIT 4,A |
25844 |
RET Z |
64F5H |
|
25845 |
LD B,0A |
25847 |
LD DE,0078H |
25850 |
LD HL,0001H |
25853 |
PUSH HL |
25854 |
PUSH DE |
25855 |
PUSH BC |
25856 |
CALL 03B5 |
25859 |
POP BC |
25860 |
POP DE |
25861 |
POP HL |
25883 |
INC A |
25864 |
LD L,A |
25865 |
NOP |
25866 |
DJNZ -0F |
25868 |
JP 6427 |
Процедура HIT
СТРОКА 700. В этой строке вводится новая переменная a = x2. Для того, чтобы сохранить значение этой переменной, будем использовать свободную ячейку 5СВ0Н из области системных переменных. Переменная b цикла FOR/NEXT записывается в регистр B:
LD Б.19Н (25D)
и в ячейку 5СВ1Н для использования в следующей процедуре. Машинные коды, соответствующие этой строке - 6548Н...6561 H. Вызов процедуры, соответствующей БЕЙСИК-оператору GO SUB 35, выполняется командой CALL 650FH.
Непосредственно связаны с этой строкой строки 25 и 30 и мы рассмотрим их здесь совместно в едином блоке.
СТРОКА 25. Для перевода этой строки в машинные коды необходимо использовать калькуляторный стек, куда записывается число 0.1 и результат операции b-a. Вычитание проще выполнить, используя последовательность команд: LD HL,(5СB0Н) LD A,H SUB L
Затем, используя процедуру 2D28H переписываем значение со стека в регистр A и
вызываем процедуру ВЕЕР - CALL 03F8H. Машинные коды, соответствующие этой строке, 650F...6521.
СТРОКА 30. Для вывода символа на экран соответственно в позицию a,72 используем команды LD A,n и RST 10H. Машинные коды - 6522H...6547K
Расчет b-а, генерация звука.
650FH
25871 RST 28Н ;Калькулятор.
DEFB 34 EA 23 D7 0A 3D 38
25679 LD HL,(5CB0H)
25882 LD A,H
25883 SUB L
25884 CALL 2D2BH 25887 CALL 03F8H
Печать "героя"
6522H
25890 LD A,02 25892 CALL 1601H 25895 LD A,15H
25897 RST 10H
25898 LD A,01
25900 RST 10H
25901 LD A,11H
25903 RST 10H
25904 LD A,08
25906 RST 10H
25907 LD A,10H
25909 RST 10H
25910 LD A,68
25912 RST 10H
25913 LD A,16H
25915 RST 10H
25916 LD A,(5CB0H)
25919 RST 10H
25920 LD A,(5B09H)
25923 RST 10H
25924 LD A,96H
25925 RST 10H 25927 RET
Создание переменной "а".
6548H
25928 LD A,(5B08H) 25931 LD (5CB0H),A 25934 LD B,19H
25936 LD A,B
25937 PUSH BC
25938 LD (5CB1),A 25941 CALL 650FH 25944 CALL 650FH 25947 POP BC 25048 INC B
25949 LD A,B
25950 CP 23 25952 JR NZ,-11
СТРОКА 730. Поскольку переменная цикла этой строки у нас хранится в ячейке 5СВ0Н, то организовать цикл в машинных кодах не представляется особенно трудным. Для этого необходимо извлекать это значение из этой ячейки, увеличивать его на 2 при каждом проходе и сравнивать с числом 14Н (20D). Машинные коды - 6562Н......6573H
Цикл по "a".
6562H |
|
25954 |
CALL 650FH |
25957 |
CALL 650FH |
25960 |
LD A,(5CB0H) |
25963 |
INC A |
25964 |
INC A |
25965 |
LD (5CB0H),A |
25968 |
CP 14H |
25970 |
JR NZ,-12H |
СТРОКА 740. В этой строке производится подсчет числа "жизней". Для реализации этой строки в машинных кодах необходимо извлекать значение из ячейки 5В02Н, уменьшать его на 1 и результат опять записывать в эту ячейку. Для вывода на экран этого значения необходимо первоначально установить необходимые параметры PRINT AT, a затем к числу, записанному в ячейке 5B02H добавить 30H(48D) для перевода его в код ASCII. Машинные коды 6574K..658EH.
Коррекция числа "жизней".
6574H |
|
25972 |
LD A,(5B02H) |
25975 |
DEC A |
25976 |
LD (5B02H),A |
25979 |
LD A,02 |
25981 |
CALL 1601H |
25984 |
LD A,16H |
25986 |
RST 10H |
25987 |
LD A,16H |
25989 |
RST 10H |
25990 |
LD A,10H |
25992 |
RST 10H |
25993 |
LD A,(5B02H) |
25996 |
ADD 30H |
25998 |
RST 10H |
СТРОКА 750. В этой строке переписывается значение переменной x2 так, чтобы x2 = 14Н (20D). Машинные коды 658FH...6593K
Коррекция переменной x2.
658FH
25999 LD A,14H
26001 LD (5B02H),A
СТРОКА 760. В этой строке выполняется условный переход. Если число "жизней" не равно 0, то выполняется возврат к началу главного цикла - строке 680. Для программы в машинных кодах это переход по адресу 6446. Машинные коды, соответствующие этой строке - 6594Н...659АН.
Проверка на конец "жизней".
6594H
26004 LD A,(5B02H)
25007 AND A
26008 JP NZ,5446H
Процедура END GAME
СТРОКА 770. В этой строке сравнивается достигнутый счет в этой игре с лучшим результатом прошлых игр. Если новый результат выше, то осуществляется переход к строке 790. Эту операцию легко выполнить для программы в машинных кодах, используя команду
SBC HL,DE
и проверяя значение флага переноса (CARRY). Если флаг будет включен после команды SBC, то выполняется переход по адресу 6611H. Машинные коды для этой строки -659ВН...65А6Н.
Проверка на новый рекорд.
659BH
26011 XOR A
26012 LD HL,(5B03H) 26015 LD DE,(5D00H) 26019 SBC HL,DE 25021 JR C,+6AH
СТРОКА 780. В этой строке устанавливается новое значение лучшего результата и это значение выводится на экран. В машинных кодах для выполнения этой операции достаточно переписать значения из ячеек 5В0З/4 в ячейки 5B00/1. Для вывода на экран используем процедуры STACK VALUE IN ВС и PRINT TOP VALUE ON CALCULATOR STACK, предварительно установив параметры PRINT AT. Машинные коды 65A7H...66C2H.
Коррекция рекорда.
65A7H |
|
26023 |
LD HL,(5B03H) |
25026 |
LD (5B00H),HL |
26029 |
PUSH HL |
26030 |
POP BC |
26031 |
CALL 2D2BH |
26034 |
LD A,02 |
26036 |
CALL 1601H |
25039 |
LD A,16H |
26041 |
RST 10H |
26042 |
LD A,15H |
26044 |
RST 10H |
26045 |
LD A,1BH |
25047 |
RST 10H |
26046 |
CALL 2DE3H |
26051 |
JR +4C |
СТРОКИ 790 и 800. В этих строках печатаются сообщения. Коды символов находятся в 65С5Н...6610H, а сама процедура печати - 6611H...6619K
Печать сообщений.
65C5H
DEFB |
12 |
01 |
11 |
07 |
16 |
0C |
00 |
20 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
DEFB |
20 |
20 |
47 |
41 |
4D |
45 |
20 |
20 |
DEFB |
4F |
56 |
45 |
52 |
20 |
20 |
20 |
20 |
DEFB |
20 |
20 |
20 |
20 |
20 |
20 |
20 |
16 |
DEFB |
02 |
00 |
12 |
00 |
20 |
20 |
41 |
6E |
DEFB |
6F |
74 |
68 |
65 |
72 |
20 |
67 |
61 |
DEFB |
6D |
65 |
20 |
3F |
20 |
28 |
79 |
29 |
DEFB |
65 |
73 |
20 |
20 |
28 |
6E |
29 |
6F |
DEFB |
20 |
20 |
20 |
20 |
|
|
|
|
6611H
26129 LD DE,65C5H 26132 LD BC,004CH 26135 CALL 203CH
СТРОКИ 840...850. В машинных кодах, соответствующих этим строкам, для проверки нажатой клавиши используется системная переменная LAST KEY, а после проверки осуществляется соответствующий переход. Если ни клавиша "y", ни клавиша "n" не будут нажаты, то осуществляется возврат к циклу ожидания нажатия клавиш.
Проверка нажатой клавиши.
661AH |
|
26138 |
HALT |
26139 |
BIT 5,(IY+01) |
26143 |
JR Z,-07 |
36145 |
RES 5,(IY+01) |
26149 |
LD A,(5TOBH) |
26152 |
CP 6EH |
26154 |
JR NZ,+03 |
26156 |
CALL 0000 |
26159 |
CP 79H |
26161 |
JR NZ,-19 |
СТРОКА 860. Перед тем, как выполнится переход к началу главного цикла по команде JP 60C9H, переписывается значение лучшего результата (переменная hi) с помощью команд LD A,n : RST 10H.
Печать нового рекорда.
661AH |
|
26163 |
LD A,02 |
26165 |
CALL 1601H |
26168 |
LD A,11H |
26170 |
RST 10H |
26171 |
LD A,05 |
26173 |
RST 10H |
26174 |
LD A,16H |
26176 |
RST 10H |
26177 |
LD A,15H |
26179 |
RST 10H |
26180 |
LD A,07 |
26182 |
RST 10H |
26183 |
LD A,20H |
26185 |
RST 10H |
26186 |
LD A,20H |
26188 |
RST 10H |
26189 |
LD A,20H |
26191 |
RST 10H |
26192 |
LD A,20H |
26194 |
RST 10H |
26195 |
JP 60C9H |
ПРОЦЕДУРА HOME
СТРОКА 890. Для вывода на экран здесь также используется процедура для печати символьной строки, но первоначально в данных этой строки переписываются значения x1 ,y1 ,x2 и y2. Коды символов сообщения при этом записаны в 669АН...66А5Н, перенос значений переменных x1 ,y1 ,x2 и y2 - в 66A6H..66В1 Н, а процедура печати - В 66В2Н... ...66BFH.
Печать "героя".
669AH
DEFB 11 08 10 08 08 16 02 04
DEFB 15 00 04 96
66A6H |
|
|
26278 |
LD |
HL,(5B06H) |
26281 |
LD |
(669F),HL |
26284 |
LD |
HL,(5B03H) |
26287 |
LD |
(66A3H),HL |
26290 |
LD |
A,02 |
26292 |
CALL 1601H |
26295 |
LD |
DE,669AH |
26298 |
LD |
BC,000C |
26301 CALL 203CH
СТРОКА 900. Эта строка в программе в машинных кодах не нужна, т.к. расположенные здесь данные для музыки будут загружены непосредственно в память при загрузке машинного кода.
СТРОКИ 910...920. Здесь через CALL 566AH вызывается процедура для проигрыша торжественной мелодии. Сама мелодия расположена в адресах 6656Н...6669Н, процедура -в 666AH...6699^ а вызов выполняется из точки 66С0Н.
Музыка.
66Ш
26304 CALL 666AH 6656H
DEFB 00 00 00 00 00 00 ED 0B
DEFB ED 0B F0 10 EC 0B EC 10
DEFB EC 0B EC 10
666AH
26218 LD B,07
26220 LD HL,665CH
26223 LD A,(HL)
26224 LD(6678H),A 26227 INC HL 26226 PUSH BC
26229 PUSH HL
26230 RST 28H ;Калькулятор. DEFB 34 EC 4C CC CC CC 38
26238 POP HL
26239 LD A,(HL)
26240 PUSH HL
26241 CALL 2D28H 26244 CALL 03F8H
26247 POP HL
26248 POP BC
26249 INC HL
26250 DJNZ -1DH 26252 LD A,01 26254 CALL 3D28H 26257 LD A,14H 26259 CALL 2D28H 26262 CALL 03F8H 26265 RET
СТРОКА 930. Изменение значения переменных home и score в машинных кодах см. 66С3H...66D7H, а вывод значения score на экран выполняется с использованием печати числа, находящегося на вершине стека калькулятора. Машинные коды 66D4Н...66Е9Н.
Коррекция переменных.
66C3H |
|
|
26307 |
LD |
A,(5B05H) |
26310 |
INC |
A |
26311 |
LD |
(5B05H),A |
26314 |
LD |
HL,(5B03H) |
26317 |
LD |
DE,0032H |
26320 |
ADD |
HL,DE |
26321 |
LD |
(5B03H),HL |
66D4H
26324 PUSH HL 25325 LD A,02
25327 |
CALL 1601H |
26330 |
LD A,16H |
26332 |
RST 10H |
26333 |
LD A,15H |
26335 |
RST 10H |
26336 |
LD A,07 |
26338 |
RST 10H |
26339 |
POP BC |
26340 |
CALL 2D2BH |
26343 |
CALL 2DE3H |
СТРОКА 950. В этой строке выполняется проверка: все ли 4 дома уже заняты. Если нет, то осуществляется переход к главному циклу. Программа в машинных кодах, выполняющая эту операцию, проще, чем строка BASIC-программы. Для этого достаточно записать в регистр A значение из ячейки 5В05Н и с помощью команды AND 4 маскировать все биты, кроме второго. Если в результате операции флаг нуля (ZERO) не будет установлен, то выполняется переход к главному циклу с помощью команды JP 641E.
Проверка 4-х домов.
66EAH
26346 LD A,(5B05H) 26349 AND 04 26351 JP NZ,641EH
СТРОКИ 960...980. Эти строки позволяют увеличить скорость игры, когда количество занятых домов достигает 4,8 или 12. Это достигается путем исключения команд RET из процедуры ROLL.
СТРОКА 985. В этой строке проверяется, выше ли число занятых домов, чем 36. Если это так, то пропускается процедура для добавления еще одного паука и осуществляется переход к главному циклу. Для реализации этого в машинных кодах достаточно вычесть от значения переменной "home" число 37. Если при этом флаг переноса (CARRY) не будет включен, то значит число занятых домов >= 37, и выполняется переход по команде JP NC 6129. Машинный код 6714Н...6718Н.
Изменение скорости игры.
66F2H |
|
26354 |
XOR A |
26355 |
LD A,(5B05H) |
26358 |
CP 04 |
26360 |
JR NZ,+06 |
26362 |
XOR A |
26363 |
LD(7EA9H),A |
26366 |
JR +19 |
26368 |
CP 08 |
26370 |
JR NZ,+06 |
26372 |
XOR A |
26373 |
LD (7EC2H),A |
26376 |
JR +0F |
26378 |
CP 0С |
26380 |
JR NZ,+06 |
26382 |
XOR A |
26383 |
LD (7ED5H),A |
26386 |
JR +5 |
26368 |
SUB 25H |
26390 |
JP NC,6129Н |
СТРОКА 990. Работу со случайными числами мы уже обсуждали в четвертой главе, поэтому объяснять порядок преобразования этой строки БЕЙСИК-программы в машинные коды мы здесь не будем. Необходимо только отметить, что для получения случайного числа в этой программе вначале извлекается значение системной переменной SEED, а затем оно
изменяется по следующей программе:
LD A,C AND 1F SUB 2
Все операции выполняются с использованием кодов калькулятора. Машинные коды -6719Н...6740Н.
Генерация случайных чисел.
6718H
26393 LD BC,(5C76H) 26397 CALL 2D2BH 26400 RST 28; калькулятор. DEFB A1 0F 34 37 16 04 34 80 DEFB 41 00 00 80 33 02 A1 03 DEFB 31 38 26419 CALL 2DA2H 26422 LD (5С76Р)^
26426 LD A,C
26427 AND 1F 26429 SUB 02 26431 JR C,+05
СТРОКА 1000. Все, что необходимо сделать, это увеличить на 1 значение переменной "а". Машинный код - 6741Н.
СТРОКА 1005. В этой строке проверяется, не превышает ли значение переменной "а" величины 31. Если это так, то значение этой переменной обнуляется.
6741H
26433 INC A
26434 CP 20H 26436 JR NZ,+01 26438 XOR A
СТРОКА 1010. Для того, чтобы проверить свободна ли позиция экрана с координатами (10,а), используется процедура SCREEN$. Для этого первоначально в регистр B записывается значение переменной "а", а в регистр C - значение 0AH (10D), и вызываются процедуры STACK VALUE IN ВС и SCREEN$, a затем параметры со стека передаются в регистры A^^D^. Теперь выполняется проверка, SCREEN$(10,a) = 20Н. Если это так, то выполняется переход для проверки следующей позиции экрана по команде JR 6741. Машинные коды, соответствующие этой строке, 6747Н...675ЕН.
Поиск свободного знакоместа.
6747H |
|
26439 |
PUSH AF |
26440 |
LD B,A |
26441 |
LD C,0A |
26443 |
CALL 2538H |
26446 |
CALL 2BF1H |
26449 |
LD A,(DE) |
26450 |
PUSH AF |
26451 |
CALL 16BFH |
26454 |
POP AF |
26455 |
CP 20 |
26457 |
JR Z,+03 |
26459 |
POP AF |
26460 |
JR -1D |
26462 |
POP AF |
СТРОКА 1020. Эта строка повторяет предыдущую, за исключением того, что значение переменной "а" увеличивается на 1 перед вызовом процедуры SCREEN$. Обратите внимание, что значение переменной "а" сохраняется перед вызовом процедуры SCREEN$ (PUSH AF), чтобы его можно было использовать в следующей процедуре. Машинные коды 675FH...6776K
Поиск свободного знакоместа.
675FH |
|
26463 |
INC A |
26464 |
PUSH AF |
26465 |
LD B,A |
26466 |
LD C,0A |
26468 |
CALL 2538H |
26471 |
CALL 2BF1H |
26474 |
LD A,(DE) |
26475 |
PUSH AF |
26476 |
CALL 16BFH |
26479 |
POP AF |
26480 |
CP 20 |
26483 |
JR Z,+03 |
26484 |
POP AF |
26485 |
JR -36H |
СТРОКА 1030. Значение переменной "а" извлекается со стека и записывается в регистр A, а затем размещается в участке памяти с именем DATA для следующего вывода на экран процедурой PRINT DATA. Машинные коды 6777Н... 6792Н.
Печать добавочного паука.
6777H
26487 POP AF
26468 DEC A
26489 LD (6782H),A
26492 JR +07
DEFB 11 04 16 0A 19 9E 9F
26501 LD A,02
26503 CALL 1601H
26506 LD DE,677EH
26509 LD BC,0007
26512 CALL 203CH
СТРОКА 1039. Здесь повторно вызывается процедура, воспроизводящая фанфары по команде CALL 666А.
СТРОКА 1040. Это строка безусловного перехода в начало цикла. В машинных кодах это выполняется по команде JP 6129H.
Музыка и возврат.
6793H
26515 CALL 666AH
26518 JP 6129H
Как видите, выполнять перевод БЕЙСИК-программы в машинные коды не так уж сложно. Лучше использовать при написании программ в машинных кодах шестнадцатиричную систему счисления, т.к. она более наглядна, если выполняется запись чисел сразу же в регистровую пару.
Нам осталось только привести машинный код для скроллинга экрана вправо-влево. Это код процедуры ROLL.
Машинный код процедуры ROLL.
ORG 32244 |
|
|
32357 |
LD HL, 18496 |
RIGHT 32244 |
LD C, 8 |
|
32360 |
CALL RIGHT |
L1 32246 |
PUSH HL |
|
32363 |
LD HL, 18496 |
32247 |
LD DE,31 |
|
32366 |
CALL RIGHT |
32250 |
ADD HL, DE |
|
32369 |
JR L6 |
32251 |
LD A,(HL) |
L5 |
32371 |
LD HL,18527 |
32252 |
SBC HL,DE |
|
32374 |
CALL LEFT |
32254 |
RRA |
|
32377 |
LD HL,18527 |
32255 |
LD B, 32 |
|
32380 |
CALL LEFT |
L2 32257 |
LD A,(HL) |
|
32383 |
LD HL,18527 |
32258 |
RRA |
|
32386 |
CALL LEFT |
32259 |
LD (HL),A |
L6 |
32389 |
LD HL, 18560 |
32260 |
INC HL |
|
32392 |
CALL RIGHT |
32261 |
DJNZ L2 |
|
32395 |
LD HL, 18560 |
32263 |
POP HL |
|
32398 |
CALL RIGHT |
32264 |
INC H |
|
32401 |
LD HL, 18560 |
32265 |
DEC C |
|
32404 |
CALL RIGHT |
32266 |
JR NZ,L1 |
|
32407 |
LD HL,18624 |
32268 |
RET |
|
32410 |
CALL RIGHT |
32281 |
LD B, 32 |
|
32413 |
LD HL,20511 |
L4 32283 |
LD A,(HL) |
|
32415 |
CALL LEFT |
32284 |
RLA |
|
32419 |
LD HL, 20575 |
32285 |
LD (HL),A |
|
32422 |
CALL LEFT |
32286 |
DEC HL |
|
32425 |
RET |
32287 |
DJNZ L4 |
|
32426 |
LD HL, 18560 |
32289 |
POP HL |
|
32429 |
CALL RIGHT |
32290 |
INC H |
|
32432 |
LD HL,18624 |
32291 |
DEC C |
|
32435 |
CALL RIGHT |
32292 |
JR NZ,L3 |
|
32438 |
LD HL,20511 |
32294 |
RET |
|
32441 |
CALL LEFT |
32295 |
LD HL,16479 |
|
32444 |
LD HL, 20575 |
32298 |
CALL LEFT |
|
32447 |
CALL LEFT |
32301 |
LD HL,16512 |
|
32450 |
RET |
32304 |
CALL RIGHT |
|
32431 |
LD HL,16479 |
32307 |
LD HL,16512 |
|
32454 |
CALL LEFT |
32310 |
CALL RIGHT |
|
32457 |
LD HL, 16512 |
32313 |
LD HL,16607 |
|
32450 |
CALL RIGHT |
32316 |
CALL LEFT |
|
32463 |
LD HL, 18432 |
32319 |
LD HL,18432 |
|
32466 |
CALL RIGHT |
32322 |
CALL RIGHT |
|
32469 |
RET |
32325 |
LD HL,18432 |
|
32470 |
LD HL,16479 |
32328 |
CALL RIGHT |
|
32473 |
CALL LEFT |
32331 |
LD HL,18432 |
|
32475 |
LD HL, 16607 |
32334 |
CALL RIGHT |
|
32479 |
CALL LEFT |
32337 |
LD A,(23673) |
|
32482 |
LD HL, 18560 |
32340.. |
.32346 - NOP |
|
32485 |
CALL RIGHT |
32347 |
AND 02 |
|
32486 |
LD HL,18624 |
32349 |
JR Z, L5 |
|
32491 |
CALL RIGHT |
32351 |
LD HL,18496 |
|
32494 |
RET |
32354 |
CALL RIGHT |
|
|
|