АВТОРСКАЯ РАЗРАБОТКА
Встроенный монитор «Хаккер-93»
© Владимир Корчагин, Кемеровская область, г. Тайга, 1994.
Краткое описание монитора.
Встроенный в ПЗУ монитор "Хаккер-93" является простым и достаточно удобным средством для работы с машинным кодом непосредственно в памяти компьютера ZX-Spectrum. Он рассчитан на тех, кто недавно приобрел компьютер и желает изучать программирование, взламывая готовые программы, но еще не имеет ни достаточных знаний для этого, ни программных и аппаратных средств. Монитор также может быть полезен и опытным программистам, как дополнение к имеющимся у них средствам.
К достоинствам "Хаккера-93" следует отнести возможность аппаратного вызова его кнопкой "NMI", полное восстановление состояния процессора после выхода из монитора, а также удобство ввода с клавиатуры программ в машинных кодах. Подпрограммы четко структурированы по сложности выполняемых функций и довольно универсальны, что позволяет пользователю применять их в своих процедурах. Недостатками программы являются ограниченный набор директив и несколько перегруженный стек. В состав программы входят следующие директивы:
Q - Вывод экрана на магнитофон в виде блока кодов без заголовка.
C - Директива копирования блоков.
P - Перенос (копирование) области стека.
E - Директива выхода из монитора.
M - Директива работы с магнитофоном: вывод, ввод и верификация блоков кодов без заголовка или заголовков.
N - Заполнение области памяти кодом.
I - Редактирование отдельных ячеек (POKES) с минимальной порчей экрана.
F - Поиск в памяти цепочки длиной до 3-х кодов.
V - Просмотр памяти в НЕХ-коде и символах; совмещен с редактированием.
Недостаточное количество директив частично компенсируется для пользователя тем, что он может составлять собственные директивы, вводить их в ОЗУ и запускать из директивы просмотра. При вызове директивы "Р" на экран выводится значение указателя стека - это позволяет в директиве "V" выше этого значения просмотреть (и изменить) записанное в стек состояние процессора, которое он имел при входе в монитор. Можно в директиве "F" задать область длиной 1 байт и поискать код, которого там нет (это очистит экран), а затем клавишей "Е" выйти в прерванную программу и посмотреть, как она формирует экран. Можно сразу после входа в монитор клавишей "Q" спасти (записать на магнитофон) картинку, а перед выходом - директивой "М" вернуть ее на место. Можно сделать полную копию памяти, можно легко снять защищенный загрузчик - одним словом, "Хаккер-93" дает широкие возможности для творчества.
Внесение изменений в схему компьютера.
Все изменения сводятся к установке в корпусе компьютера кнопки "NMI" любой конструкции, а также антидребезгового устройства (см. схему), собранного на двух логических элементах И-НЕ микросхемы серии К555 или К155. Возможно применение микросхем других серий.
Дамп изменений в ПЗУ "© 1982 Sinclair Research Ltd".
Подчеркиванием выделены неизменяемые ячейки ПЗУ.
002B 005F |
F5 29 |
E5 29 |
87 29 |
18 29 |
3D B5 |
C5 6F |
2A C9 |
61 00 |
31 F0 |
0067 |
F5 |
E5 |
3E |
FE |
DB |
FE |
21 |
00 |
77 |
006F |
00 |
39 |
C3 |
6E |
38 |
2A |
5D |
5C |
F4 |
1539 |
2A |
20 |
53 |
69 |
6E |
63 |
6C |
61 |
F2 |
1541 |
69 |
72 |
2D |
38 |
32 |
20 |
2A |
2A |
3C |
1549 |
20 |
58 |
61 |
6B |
6B |
65 |
70 |
2D |
0F |
1551 |
39 |
33 |
20 |
AA |
3E |
10 |
01 |
00 |
EB |
3868 |
01 |
05 |
02 |
A1 |
38 |
C9 |
1F |
ED |
56 |
3870 |
5F |
38 |
03 |
31 |
00 |
5B |
F5 |
ED |
B0 |
3878 |
57 |
F3 |
F5 |
E5 |
DD |
E5 |
FD |
E5 |
78 |
3880 |
C5 |
D5 |
08 |
F5 |
D9 |
C5 |
D5 |
E5 |
A7 |
3888 |
21 |
E0 |
A4 |
39 |
D4 |
F6 |
3C |
3C |
E0 |
3890 |
E 6 |
07 |
D3 |
FE |
5F |
01 |
20 |
00 |
06 |
3898 |
CD |
DA |
3C |
57 |
3C |
7B |
28 |
EF |
D8 |
38A0 |
7A |
FE |
25 |
20 |
0E |
DD |
21 |
00 |
A1 |
38A8 |
40 |
11 |
00 |
1B |
3E |
FF |
CD |
C6 |
1C |
38B0 |
04 |
18 |
DC |
FE |
0F |
20 |
1B |
0E |
36 |
38B8 |
03 |
CD |
9D |
3C |
D1 |
C1 |
E1 |
ED |
F9 |
38C0 |
52 |
19 |
38 |
04 |
ED |
B0 |
18 |
E9 |
3D |
38C8 |
0B |
EB |
09 |
EB |
09 |
03 |
ED |
B8 |
9B |
38D0 |
18 |
F4 |
FE |
22 |
20 |
11 |
21 |
00 |
86 |
38D8 |
00 |
39 |
E5 |
CD |
94 |
3C |
E1 |
D1 |
7D |
38E0 |
F9 |
EB |
01 |
28 |
00 |
18 |
DD |
FE |
18 |
38E8 |
15 |
20 |
20 |
E1 |
D1 |
C1 |
D9 |
F1 |
B2 |
38F0 |
08 |
D1 |
C1 |
FD |
E1 |
DD |
E1 |
E1 |
3F |
38F8 |
F1 |
ED |
47 |
F1 |
F9 |
E1 |
F3 |
E2 |
F5 |
3900 |
03 |
39 |
FB |
07 |
D6 |
1A |
0F |
ED |
63 |
3908 |
4 F |
F1 |
C9 |
FE |
10 |
20 |
23 |
CD |
68 |
3910 |
9B |
3C |
CD |
B5 |
3C |
C1 |
D1 |
DD |
4D |
3918 |
E1 |
CD |
5B |
3A |
FE |
1E |
20 |
03 |
D3 |
3920 |
79 |
18 |
8B |
FE |
07 |
28 |
05 |
FE |
A5 |
3928 |
19 |
20 |
EE |
37 |
79 |
CD |
EA |
3C |
2B |
3930 |
18 |
9E |
FE |
08 |
20 |
10 |
CD |
9B |
BD |
3938 |
3C |
CD |
B5 |
3C |
D1 |
C1 |
E1 |
73 |
51 |
3940 |
54 |
5D |
13 |
0B |
18 |
9F |
FE |
12 |
0F |
3948 |
20 |
11 |
CD |
94 |
3C |
CD |
83 |
3B |
DA |
3950 |
E1 |
46 |
E5 |
CD |
B5 |
3C |
C1 |
E1 |
F5 |
3958 |
71 |
18 |
D5 |
FE |
0E |
20 |
5E |
CD |
46 |
3960 |
9B |
3C |
0E |
04 |
CD |
B7 |
3C |
E1 |
23 |
3968 |
D1 |
06 |
03 |
3E |
FF |
BD |
28 |
05 |
A2 |
3970 |
05 |
BC |
28 |
01 |
05 |
7A |
D9 |
C1 |
AC |
3978 |
E1 |
F5 |
CD |
2C |
3C |
F1 |
ED |
B1 |
4B |
3980 |
20 |
D7 |
08 |
D9 |
48 |
0D |
7B |
D9 |
3A |
3988 |
28 |
0E |
BE |
20 |
2A |
D9 |
0D |
7C |
61 |
3990 |
D9 |
28 |
05 |
23 |
BE |
2B |
20 |
1F |
1A |
3998 |
2B |
CD |
B5 |
3A |
23 |
CD |
17 |
3B |
FA |
39A0 |
FE |
17 |
20 |
0E |
7B |
E6 |
1F |
FE |
9A |
3 9A8 |
1A |
28 |
AE |
C6 |
05 |
5F |
16 |
40 |
51 |
39B0 |
18 |
05 |
E5 |
CD |
92 |
3B |
E1 |
08 |
6E |
39B8 |
EA |
7E |
39 |
18 |
9C |
FE |
07 |
20 |
6B |
39C0 |
FA |
0E |
01 |
CD |
9D |
3C |
E1 |
CD |
56 |
39C8 |
2C |
3C |
1E |
07 |
79 |
E6 |
80 |
4F |
BC |
39D0 |
CD |
E7 |
3B |
28 |
E6 |
FE |
21 |
CC |
F1 |
39D8 |
C9 |
3B |
28 |
F4 |
FE |
1E |
20 |
04 |
71 |
39E0 |
CB |
F9 |
10 |
E3 |
FE |
01 |
20 |
04 |
F3 |
39E8 |
CB |
B9 |
18 |
DB |
D5 |
CD |
44 |
3B |
B9 |
39F0 |
FE |
0D |
20 |
03 |
19 |
18 |
06 |
FE |
8C |
39F8 |
0A |
20 |
12 |
ED |
52 |
D1 |
08 |
CD |
52 |
3 A00 |
59 |
3B |
C5 |
CD |
D7 |
3C |
C1 |
3C |
70 |
3 A08 |
20 |
C6 |
08 |
18 |
DF |
11 |
C0 |
00 |
F8 |
3 A1 0 |
CB |
79 |
28 |
03 |
11 |
80 |
01 |
FE |
49 |
3 A1 8 |
22 |
20 |
03 |
19 |
18 |
06 |
FE |
1A |
E 6 |
3 A2 0 |
20 |
02 |
ED |
52 |
D1 |
FE |
06 |
20 |
B0 |
3 A2 8 |
01 |
E9 |
FE |
09 |
20 |
0A |
C5 |
7E |
C0 |
3 A3 0 |
ED |
A1 |
28 |
FC |
2B |
C1 |
18 |
98 |
B8 |
3 A3 8 |
CD |
5C |
3C |
30 |
93 |
46 |
CD |
4A |
F7 |
3 A4 0 |
3C |
70 |
18 |
8C |
0E |
04 |
AF |
06 |
91 |
3 A4 8 |
20 |
10 |
FE |
2F |
F6 |
EF |
D3 |
FE |
95 |
3 A50 |
0D |
20 |
F4 |
0E |
C0 |
10 |
FE |
0D |
94 |
3 A58 |
20 |
FB |
C9 |
E5 |
D5 |
C5 |
CD |
8E |
50 |
3 A60 |
02 |
20 |
FB |
7B |
FE |
27 |
28 |
F6 |
75 |
3 A68 |
3E |
FE |
DB |
FE |
CB |
47 |
7B |
F5 |
39 |
3 A7 0 |
3C |
C4 |
44 |
3A |
F1 |
18 |
20 |
E5 |
36 |
3 A7 8 |
D5 |
FE |
20 |
38 |
04 |
FE |
80 |
38 |
97 |
3 A8 0 |
02 |
3E |
2E |
11 |
00 |
3C |
63 |
6F |
47 |
3 A8 8 |
29 |
29 |
29 |
19 |
D1 |
D5 |
C5 |
06 |
C7 |
3 A90 |
08 |
7E |
12 |
23 |
14 |
10 |
FA |
18 |
BB |
3 A98 |
6C |
C5 |
0E |
02 |
78 |
07 |
07 |
07 |
A0 |
3AA0 |
07 |
47 |
E6 |
0F |
FE |
0A |
38 |
02 |
5F |
3AA8 |
C6 |
07 |
C6 |
30 |
CD |
77 |
3A |
1C |
3F |
3AB0 |
0D |
20 |
E9 |
C1 |
C9 |
D5 |
C5 |
44 |
68 |
3AB8 |
CD |
99 |
3A |
45 |
CD |
99 |
3A |
C1 |
38 |
3AC0 |
D1 |
C9 |
CD |
CD |
3A |
13 |
13 |
CD |
5B |
3AC8 |
CD |
3A |
1B |
1B |
C9 |
C5 |
CB |
B9 |
51 |
3AD0 |
CD |
D5 |
3A |
C1 |
C9 |
E5 |
D5 |
F5 |
1F |
3AD8 |
7A |
0F |
0F |
0F |
E6 |
03 |
57 |
21 |
1A |
3AE0 |
00 |
58 |
19 |
F1 |
CB |
79 |
20 |
02 |
E2 |
3AE8 |
77 |
23 |
77 |
18 |
27 |
E5 |
D5 |
C5 |
F1 |
3AF0 |
CD |
B5 |
3A |
3E |
07 |
B3 |
5F |
CB |
08 |
3AF8 |
79 |
28 |
0C |
06 |
10 |
7E |
CD |
77 |
B7 |
3B00 |
3A |
23 |
1C |
10 |
F8 |
18 |
0C |
06 |
E 6 |
3B08 |
08 |
C5 |
46 |
CD |
99 |
3A |
23 |
1C |
35 |
3B10 |
C1 |
10 |
F6 |
C1 |
D1 |
E1 |
C9 |
C5 |
13 |
3B18 |
7A |
E6 |
18 |
47 |
7B |
E6 |
E0 |
07 |
5A |
3B20 |
07 |
07 |
B0 |
C1 |
C9 |
CD |
17 |
3B |
C2 |
3B28 |
A7 |
28 |
0B |
3D |
18 |
08 |
CD |
17 |
7E |
3B30 |
3B |
FE |
17 |
28 |
01 |
3C |
5F |
E6 |
65 |
3B38 |
18 |
C6 |
40 |
57 |
7B |
E6 |
07 |
0F |
5F |
3B40 |
0F |
0F |
5F |
C9 |
11 |
08 |
00 |
CB |
A5 |
3B48 |
79 |
C8 |
1E |
10 |
C9 |
E5 |
D5 |
21 |
96 |
3B50 |
05 |
02 |
16 |
00 |
5F |
19 |
7E |
18 |
B6 |
3B58 |
BB |
E5 |
D5 |
C5 |
CD |
17 |
3B |
87 |
73 |
3B60 |
87 |
87 |
CB |
79 |
28 |
04 |
87 |
30 |
D0 |
3B68 |
01 |
25 |
C5 |
CB |
B9 |
81 |
C1 |
16 |
6A |
3B70 |
00 |
5F |
ED |
52 |
11 |
01 |
40 |
06 |
A1 |
3B78 |
18 |
CD |
ED |
3A |
CD |
92 |
3B |
10 |
69 |
3B80 |
F8 |
18 |
90 |
C5 |
D5 |
B7 |
CD |
44 |
BD |
3B88 |
3B |
ED |
52 |
D1 |
43 |
CD |
25 |
3B |
7E |
3B90 |
18 |
0B |
C5 |
D5 |
CD |
44 |
3B |
19 |
ED |
3B98 |
D1 |
43 |
CD |
2E |
3B |
78 |
E6 |
1F |
9A |
3BA0 |
B3 |
5F |
AF |
C1 |
C9 |
2B |
79 |
E6 |
B0 |
3BA8 |
7 F |
28 |
0A |
0D |
1D |
CB |
79 |
20 |
22 |
3BB0 |
02 |
1D |
1D |
AF |
C9 |
CD |
25 |
3B |
CC |
3BB8 |
CB |
79 |
28 |
06 |
0E |
8F |
F6 |
16 |
0E |
3BC0 |
18 |
04 |
0E |
07 |
F6 |
1C |
5F |
AF |
4C |
3BC8 |
C9 |
23 |
79 |
FE |
8F |
28 |
0D |
FE |
28 |
3BD0 |
07 |
28 |
09 |
17 |
38 |
02 |
1C |
1C |
CC |
3BD8 |
1C |
0C |
AF |
C9 |
E6 |
80 |
4F |
CD |
35 |
3BE0 |
2E |
3B |
F6 |
07 |
5F |
AF |
C9 |
3E |
96 |
3BE8 |
28 |
CD |
D5 |
3A |
CD |
59 |
3B |
CB |
53 |
3BF0 |
79 |
28 |
09 |
D5 |
11 |
7B |
48 |
46 |
C4 |
3BF8 |
CD |
99 |
3A |
D1 |
CD |
5B |
3A |
F5 |
FB |
3C00 |
3C |
20 |
03 |
F1 |
18 |
E6 |
3E |
38 |
00 |
3C08 |
CD |
D5 |
3A |
F1 |
C0 |
FE |
03 |
CC |
9E |
3C10 |
92 |
3B |
28 |
D3 |
FE |
04 |
CC |
A5 |
87 |
3C18 |
3B |
28 |
F7 |
FE |
0B |
CC |
83 |
3B |
41 |
3C20 |
28 |
F7 |
FE |
13 |
CC |
C9 |
3B |
28 |
84 |
3C28 |
F7 |
FE |
20 |
C9 |
3E |
38 |
E5 |
C5 |
62 |
3C30 |
11 |
FE |
5A |
01 |
FF |
02 |
62 |
69 |
A2 |
3C38 |
77 |
ED |
B8 |
AF |
2B |
1B |
01 |
FF |
85 |
3C40 |
17 |
77 |
ED |
B8 |
11 |
01 |
40 |
C1 |
C2 |
3C48 |
E1 |
C9 |
CB |
20 |
CB |
20 |
CB |
20 |
EF |
3C50 |
CB |
20 |
B0 |
47 |
C9 |
CD |
5B |
3A |
99 |
3C58 |
FE |
FF |
28 |
F9 |
CD |
4D |
3B |
FE |
05 |
3C60 |
30 |
38 |
0B |
FE |
47 |
D0 |
FE |
40 |
62 |
3C68 |
38 |
02 |
D6 |
07 |
D6 |
30 |
3F |
C9 |
C9 |
3C70 |
3E |
28 |
CD |
C2 |
3A |
CD |
B5 |
3A |
97 |
3C78 |
CD |
55 |
3C |
D0 |
CD |
5F |
00 |
18 |
26 |
3C80 |
EF |
3E |
28 |
CD |
CD |
3A |
CD |
99 |
4B |
3C88 |
3A |
1D |
1D |
CD |
55 |
3C |
D0 |
CD |
33 |
3C90 |
4A |
3C |
18 |
ED |
0E |
01 |
11 |
01 |
78 |
3C98 |
40 |
18 |
05 |
0E |
02 |
CD |
2C |
3C |
76 |
3CA0 |
CD |
70 |
3C |
FE |
0D |
20 |
F9 |
E3 |
5C |
3CA8 |
E5 |
3E |
38 |
CD |
C2 |
3A |
CD |
92 |
67 |
3CB0 |
3B |
0D |
20 |
EC |
C9 |
0E |
01 |
CD |
E5 |
3CB8 |
81 |
3C |
FE |
0D |
20 |
F9 |
78 |
CB |
18 |
3CC0 |
41 |
D9 |
20 |
03 |
67 |
18 |
03 |
6F |
2A |
3CC8 |
E3 |
E5 |
D9 |
3E |
38 |
CD |
CD |
3A |
EF |
3CD0 |
CD |
92 |
3B |
0D |
20 |
E1 |
C9 |
01 |
7E |
3CD8 |
08 |
00 |
F5 |
F1 |
CD |
5B |
3A |
F5 |
59 |
3CE0 |
3C |
20 |
05 |
10 |
F6 |
0D |
20 |
F3 |
A3 |
3CE8 |
F1 |
C9 |
14 |
08 |
15 |
F3 |
3E |
05 |
45 |
3CF0 |
D3 |
FE |
CD |
62 |
05 |
D8 |
CD |
44 |
1A |
3CF8 |
3A |
CD |
D7 |
3C |
3C |
28 |
F7 |
C9 |
72 |
|
|
Текст программы на Ассемблере. |
|
|
|
Входной блок. |
|
ORG |
#002B |
Короткий вход из точки прерывания. |
|
PUSH |
AF |
|
|
PUSH |
HL |
|
|
ADD |
A, A |
Имитация нажатия CAPS SHIFT. |
|
JR |
L006D |
|
|
ORG |
#005F |
|
IN HL |
ADD |
HL, HL |
|
|
ADD |
HL, HL |
|
|
ADD |
HL, HL |
|
|
ADD |
HL, HL |
|
|
OR |
L |
|
|
LD |
L, A |
|
|
RET |
|
|
L0066 |
NOP |
;Инкремент |
рег.R (вход по "NMI" - #0066). |
L0067 |
PUSH |
AF |
|
|
PUSH |
HL |
|
|
LD |
A, #FE |
Если нажата CAPS SHIFT, то младший бит |
|
IN |
A, (#FE) |
аккумулятора будет обнулен. |
L006D |
LD |
HL,#0000 |
Фиксация |
|
ADD |
HL, SP |
значения SP. |
|
JP |
L386E |
|
|
ORG |
#1539 ; |
|
DEFM |
"* Sinclair- |
82 ** Xakkep-93 *" |
|
ORG |
#386E ; |
L386E |
RRA |
;Устан.знач.флага С по состоянию CAPS SHIFT |
|
LD |
A, R |
|
|
JR |
C,L3876 |
Переход, если CAPS SHIFT не нажата. |
|
LD |
SP,#5B00 |
Переключить SP на область атрибутов. |
L3876 |
PUSH |
AF |
Сохр. RF и сост. триггера прерываний. |
|
LD |
A, I |
|
|
DI |
|
Команда для случая входа из точки прерывания |
|
PUSH |
AF |
Сохранить IF. |
|
PUSH |
HL |
Сохранить SP. |
|
PUSH |
IX |
Сохранить остальные регистры. |
|
PUSH |
IY |
|
|
PUSH |
BC |
|
|
PUSH |
DE |
|
|
EX |
AF,AF' |
|
|
PUSH |
AF |
Сохранить альтернативные регистры. |
|
EXX |
|
|
|
PUSH |
BC |
|
|
PUSH |
DE |
|
|
PUSH |
HL |
|
|
LD |
HL,#A4E0 |
Загрузить число минус #5B20. |
|
ADD |
HL, SP |
|
|
CALL |
NC,EXIT |
Звук.сигнал, если SP указ. ниже, чем #5В20. |
OUT |
INC |
A |
Подготовить новый цвет бордюра. |
|
AND |
#07 |
Выключить остальные биты. |
|
OUT |
(#FE),A |
Установить цвет бордюра. |
|
LD |
E, A |
Сохранить значение цвета бордюра. |
|
LD |
BC,#0020 |
Задержка 2 сек. |
|
CALL |
T.SCAN |
Сканировать клавиатуру 2 сек. |
|
LD |
D, A |
Сохранить результат сканирования. |
|
INC |
A |
Установить флаг Z, если клавиша не нажата. |
|
LD |
A, E |
Восстановить цвет бордюра. |
|
JR |
Z, OUT |
Возврат, если клавиша не нажата. |
|
LD |
A, D |
Извлечь результат сканирования. |
|
|
|
Блок директив. |
|
CP |
#25 |
Нажата клавиша "Q"? |
|
JR |
NZ,L38B3 |
Переход вперед, если НЕТ. |
|
LD |
IX,#4000 |
Начальный адрес экрана. |
|
LD |
DE,#1B00 |
Длина экрана. |
|
LD |
A, #FF |
Флаговый байт. |
L38AE |
CALL |
#04C6 |
Запись экрана на магнитофон. |
L38B1 |
JR |
OUT |
Выход из директивы. |
L38B3 |
CP |
#0 F |
Нажата клавиша "С"? |
|
JR |
NZ,L38D2 |
Переход вперед, если НЕТ. |
|
LD |
C,#03 |
Ввести три числа. |
|
CALL |
MEN4-A |
Ввод 4-значных чисел (с очисткой экрана). |
|
POP |
DE |
Извлечь введенные числа. |
|
POP |
BC |
|
|
POP |
HL |
|
|
SBC |
HL, DE |
Установить флаг С и перейти |
|
ADD |
HL, DE |
вперед, если блок копируется |
|
JR |
C,L38C8 |
вверх по адресам. |
L38C4 |
LDIR |
|
Скопировать блок. |
L38C6 |
JR |
L38B1 |
Выход из директивы. |
L38C8 |
DEC |
BC |
Пересчет |
|
EX |
DE, HL |
регистров |
|
ADD |
HL, BC |
для |
|
EX |
DE, HL |
копирования |
|
ADD |
HL, BC |
блока кодов |
|
INC |
BC |
с "хвоста". |
|
LDDR |
|
Скопировать блок. |
L38D0 |
JR |
L38C6 |
Выход из директивы. |
L38D2 |
CP |
#22 |
Нажата клавиша "Р"? |
|
JR |
NZ,L38E7 |
Переход вперед, если НЕТ. |
|
LD |
HL,#0000 |
Занести |
|
ADD |
HL, SP |
SP в HL. |
|
PUSH |
HL |
Сохранить SP. |
|
CALL |
MEN4 |
Ввод 4-значного числа (без очистки экрана). |
|
POP |
HL |
Извлечь новое значение SP. |
|
POP |
DE |
Извлечь старое значение SP. |
|
LD |
SP, HL |
Загрузить в SP новое значение. |
|
EX |
DE, HL |
Подготовка к |
|
LD |
BC,#0028 |
копированию 4 0 байтов. |
L38E5 |
JR |
L38C4 |
Копирование LDIR и выход из директивы. |
L38E7 |
CP |
#15 |
Нажата клавиша "Е"? |
|
JR |
NZ,L390B |
Переход вперед, если НЕТ. |
|
POP |
HL |
Извлечь альтернативные регистры. |
|
POP |
DE |
|
|
POP |
BC |
|
|
EXX |
|
|
|
POP |
AF |
|
|
EX |
AF,AF' |
|
|
POP |
DE |
Извлечь основные регистры. |
|
POP |
BC |
|
|
POP |
IY |
|
|
POP |
IX |
|
|
POP |
HL |
Извлечь значение SP. |
|
POP |
AF |
Извлечь значение IF. |
|
LD |
I,A |
|
|
POP |
AF |
Извлечь значение RF (и триггера прерываний). |
|
LD |
SP, HL |
Восстановить значение SP. |
|
POP |
HL |
Извлечь значение HL. |
|
DI |
|
Восстановить |
|
JP |
PO,L3903 |
состояние триггера |
|
EI |
|
прерываний. |
L3903 |
RLCA |
|
Сохранить 7-й бит в нулевом разряде. |
|
SUB |
#1A |
Скомпенсировать значение регистра R. |
|
RRCA |
|
Извлечь 7-й бит из нулевого разряда. |
|
LD |
R, A |
|
|
POP |
AF |
Извлечь AF. |
|
RET |
|
Выход из монитора в вызывающую программу. |
L390B |
CP |
#10 |
Нажата клавиша "М"? |
|
JR |
NZ,L3 932 |
Переход вперед, если НЕТ. |
|
CALL |
MEN4-D |
Ввести два 4-значных числа (с очисткой экр.). |
|
CALL |
MEN2 |
Ввести 2-значное число. |
|
POP |
BC |
Поместить флаговый байт в регистр С. |
|
POP |
DE |
Извлечь длину блока. |
|
POP |
IX |
Извлечь начальный адрес ввода (вывода). |
L3919 |
CALL |
SCAN |
Сканировать клавиатуру. |
|
CP |
#1E |
Нажата клавиша "S"? |
|
JR |
NZ,L3923 |
Переход вперед, если НЕТ. |
|
LD |
A, C |
Поместить флаговый байт в аккумулятор. |
|
JR |
L3 8AE |
Запись блока на ленту и выход из директивы. |
L3923 |
CP |
#07 |
Нажата клавиша "V"? |
|
JR |
Z,L392C |
Переход вперед, если ДА (флаг С сброшен). |
|
CP |
#19 |
Нажата клавиша "L"? |
|
JR |
NZ,L3919 |
Возврат в сканирование, если НЕТ. |
|
SCF |
|
Установить флаг LOAD/VERIFY. |
L392C |
LD |
A, C |
Ввод флагового байта в аккумулятор. |
|
CALL |
LOAD |
Ввод блока с ленты или верификация. |
L3930 |
JR |
L38D0 |
Выход из директивы. |
L3932 |
CP |
#08 |
Нажата клавиша "N"? |
|
JR |
NZ ,L3 94 6 |
Переход вперед, если НЕТ. |
|
CALL |
MEN4-D |
Ввести два 4-значных числа (с очисткой экр. |
|
CALL |
MEN2 |
Ввести 2-значное число. |
|
POP |
DE |
Поместить в регистр Е код заполнения. |
|
POP |
BC |
Извлечь длину заполняемой области. |
|
POP |
HL |
Извлечь начальный адрес области. |
|
LD |
(HL),E |
Подготовка |
|
LD |
D, H |
к заполнению |
|
LD |
E,L |
с помощью |
|
INC |
DE |
команды |
|
DEC |
BC |
LDIR. |
|
JR |
L38E5 |
Переход на LDIR и выход из директивы. |
L3946 |
CP |
#12 |
Нажата клавиша "I"? |
|
JR |
NZ,L3 95B |
Переход вперед, если НЕТ. |
|
CALL |
MEN4 |
Ввести 4-значное число (без стирания экрана |
|
CALL |
UP |
Вернуть позицию печати назад. |
|
POP |
HL |
Извлечь введенный адрес. |
|
LD |
B, (HL) |
Извлечь байт из памяти. |
|
PUSH |
HL |
Сохранить адрес. |
|
CALL |
MEN2 |
Ввести новый байт. |
|
POP |
BC |
Поместить новый байт в регистр С. |
|
POP |
HL |
Извлечь адрес ячейки. |
|
LD |
(HL) ,C |
Загрузить новый байт в ячейку. |
L3959 |
JR |
L3930 |
Выход из директивы. |
L395B |
CP |
#0E |
Нажата клавиша "F"? |
|
JR |
NZ,L3 9BD |
Переход вперед, если НЕТ. |
|
CALL |
MEN4-D |
Ввести два 4-значных числа (с очисткой экр. |
|
LD |
C, #04 |
Ввести четыре |
|
CALL |
MEN2-A |
2-значных числа. |
|
POP |
HL |
Извлечь цепочку кодов |
|
POP |
DE |
в регистры D',E',H',L'. |
|
LD |
B,#03 |
Полагаем длину цепочки три кода. |
|
LD |
A, #FF |
Маркер конца цепочки. |
|
CP |
L |
Маркер в регистре L'? |
|
JR |
Z,L3975 |
Переход вперед, если ДА. |
|
DEC |
B |
Полагаем, что в цепочке два кода. |
|
CP |
H |
Маркер в регистре Н? |
|
JR |
Z,L3975 |
Переход вперед, если ДА. |
|
DEC |
B |
Будем искать только первый код. |
L3975 |
LD EXX |
A, D |
Извлечь первый код цепочки. |
|
POP |
BC |
Извлечь длину блока. |
|
POP |
HL |
Извлечь начальный адрес блока. |
|
PUSH |
AF |
Сохранить первый код цепочки. |
|
CALL |
CLS |
Очистка экрана (INK 0; PAPER 7). |
|
POP |
AF |
Извлечь первый код цепочки. |
L397E |
CPIR |
|
Поиск кода. |
|
JR |
NZ ,L3 95 9 |
Выход из директивы, если весь блок просмотрен |
|
EX |
AF, AF' |
Сохранить первый код и флаги. |
|
EXX |
|
|
|
LD |
C, B |
Поместить в регистр С' длину цепочки. |
|
DEC |
C |
Контроль конца цепочки (флаг Z). |
|
LD |
A, E |
Загрузить второй код цепочки. |
|
EXX |
|
|
|
JR |
Z,L3998 |
Переход на печать адреса, если конец цепочки |
|
CP |
(HL) |
Сверить второй код с содержимым ячейки. |
|
JR |
NZ,L3 9B7 |
Продолжить поиск в блоке, если не совпадает. |
|
EXX |
|
|
|
DEC |
C |
Контроль конца цепочки. |
|
LD |
A, H |
Загрузить третий код из цепочки. |
|
EXX |
|
|
|
JR |
Z,L3998 |
Переход на печать адреса, если конец цепочки |
|
INC |
HL |
Сверить третий код |
|
CP |
(HL) |
с содержимым |
|
DEC |
HL |
ячейки. |
|
JR |
NZ,L39B7 |
Продолжить поиск в блоке, если не совпадает. |
L3998 |
DEC |
HL |
Установить адрес первого кода цепочки. |
|
CALL |
PR.HL |
Распечатать адрес на экране. |
|
INC |
HL |
Восстановить HL. |
|
CALL |
AB.LIN |
Получить номер строки экрана, где была печать |
|
CP |
#17 |
Это последняя строка? |
|
JR |
NZ,L3 9B2 |
Переход вперед, если НЕТ. |
|
LD |
A, E |
Загрузить номера строки и колонки экрана. |
|
AND |
#1F |
Выделить номер колонки. |
|
CP |
#1A |
Это последняя колонка? |
|
JR |
Z,L3 95 9 |
Выход из директивы, если весь экран заполнен |
|
ADD |
A, #05 |
Задать адрес колонки следующего столбца. |
|
LD |
E, A |
Младший байт позиции печати. |
|
LD |
D, #40 |
Старший байт позиции печати. |
|
JR |
L39B7 |
Переход на продолжение поиска. |
L39B2 |
PUSH |
HL |
Перемещение позиции |
|
CALL |
DOWN |
печати на одну |
|
POP |
HL |
строку вниз. |
L39B7 |
EX |
AF,AF' |
Извлечь первый код цепочки и флаги. |
|
JP |
PE,L397E |
Продолжить поиск, если блок не кончился. |
L39BB |
JR |
L3959 |
Выход из директивы. |
L39BD |
CP |
#07 |
Нажата клавиша "V"? |
|
JR |
NZ,L3 9BB |
Возврат, если НЕТ. |
|
LD |
C, #01 |
Ввод одного |
|
CALL |
MEN4-A |
4-значного числа. |
|
POP |
HL |
Извлечь введенный адрес. |
L39C7 |
CALL |
CLS |
Осистить экран, печать с адреса #4001 (в DE) |
|
LD |
E, #07 |
Установить курсор в 7-ю колонку экрана. |
|
LD |
A, C |
Сохранить бит 7 (флаг БАЙТЫ/СИМВОЛЫ) |
|
AND |
#80 |
и обнулить остальные |
|
LD |
C, A |
(счетчик столбцов). |
L39D0 |
CALL |
WIND |
Печать экрана с курсором. |
|
JR |
Z,L39BB |
Выход из директивы, если нажата BREAK. |
|
CP |
#21 |
Нажата клавиша ENTER? |
|
CALL |
Z,RIGHT |
Сдвинуть курсор вправо, если ДА. |
|
JR |
Z,L39D0 |
Возврат в "окно", если был сдвиг курсора. |
|
CP |
#1E |
Нажата клавиша "S"? |
|
JR |
NZ,L39E4 |
Переход вперед, если НЕТ. |
|
SET |
7,C |
Установить значение флага СИМВОЛЬНОГО режима. |
|
DJNZ |
L39C7 |
Возврат в "окно" со стиранием экрана. |
L39E4 |
CP |
#01 |
Нажата клавиша "Н"? |
|
JR |
NZ,L3 9EC |
Переход вперед, если НЕТ. |
|
RES |
7,C |
Установить значение флага БАЙТОВОГО режима. |
|
JR |
L39C7 |
Возврат в "окно" со стиранием экрана. |
L39EC |
PUSH |
DE |
Сохранить позицию курсора. |
|
CALL |
STEP |
Занести в DE шаг по строке (8 или 16). |
|
CP |
#0D |
Нажата клавиша "R"? |
|
JR |
NZ,L39F7 |
Переход вперед, если НЕТ. |
|
ADD |
HL, DE |
Сместить распечатку экрана |
|
JR |
L39FD |
на 1 строку вверх. |
L39F7 |
CP |
#0A |
Нажата клавиша "U"? |
|
JR |
NZ,L3A0D |
Переход вперед, если НЕТ. |
|
SBC |
HL, DE |
Сместить распечатку экрана на 1 строку вниз. |
L39FD |
POP |
DE |
Восстановить позицию курсора. |
|
EX |
AF,AF' |
Сохранить номер нажатой клавиши. |
|
CALL |
PR.SCR |
Печать экрана. |
|
PUSH |
BC |
Сканирование |
|
CALL |
T.SC.5 |
клавиатуры |
|
POP |
BC |
в течение 0,5 сек. |
|
INC |
A |
Установить флаг Z, если клавиша не нажата. |
|
JR |
NZ,L3 9D0 |
Возврат в "окно", если нажата любая клавиша. |
|
EX |
AF,AF' |
Восстановить номер нажатой клавиши. |
|
JR |
L39EC |
Возврат на начало роллинга. |
L3A0D |
LD |
DE,#00C0 |
Занести в DE шаг по странице БАЙТОВ. |
|
BIT |
7,C |
Проверить флаг режима (БАЙТЫ/СИМВОЛЫ). |
|
JR |
Z,L3A17 |
Переход вперед, если БАЙТОВЫЙ режим. |
|
LD |
DE,#0180 |
Занести в DE шаг по странице СИМВОЛОВ. |
L3A17 |
CP |
#22 |
Нажата клавиша "Р"? |
|
JR |
NZ,L3A1E |
Переход вперед, если НЕТ. |
|
ADD |
HL, DE |
Увеличить адрес курсора на шаг по странице. |
|
JR |
L3A2 4 |
Переход вперед. |
L3A1E |
CP |
#1A |
Нажата клавиша "О"? |
|
JR |
NZ,L3A2 4 |
Переход вперед, если НЕТ. |
|
SBC |
HL, DE |
Уменьшить адрес курсора на шаг по странице. |
L3A2 4 |
POP |
DE |
Восстановить позицию курсора. |
|
CP |
#06 |
Нажата клавиша "G"? |
|
JR |
NZ,L3A2A |
Переход вперед, если НЕТ. |
|
JP |
(HL) |
Запустить программу с адреса, указ.курсором. |
L3A2A |
CP |
#09 |
Нажата клавиша "J"? |
|
JR |
NZ,L3A38 |
Переход вперед, если НЕТ. |
|
PUSH |
BC |
Поиск вверх по адресам |
|
LD |
A,(HL) |
первого байта, |
L3A30 |
CPI |
|
отличающегося от |
|
JR |
Z , L3 A3 0 |
указанного курсором. |
|
DEC |
HL ;Установка курсора на обнаруженный байт. |
|
POP |
BC ;Восстановление регистра С. |
|
JR |
L3 9D0 ;Возврат в "окно". |
L3A38 |
CALL |
F.CONT ;Перевод цифры в число с установкой флага С. |
|
JR |
NC,L39D0 ;Возврат в "окно", если нажата не цифра. |
|
LD |
B, (HL) ;Загрузить рег.В из ячейки, указ.курсором. |
|
CALL |
IN B ;Ввести в рег.В со сдвигом число из рег.А. |
|
LD |
(HL),B ;Вернуть в ячейку отредактированное число. |
|
JR |
L3 9D0 ;Возврат в "окно". |
|
|
|
Блок подпрограмм. |
TON |
LD |
C,#04 |
Динамик переключится 4 раза. |
|
XOR |
A |
По окончании работы динамик выключить. |
L3A47 |
LD |
B, #20 |
Задержка времени между фронтами. |
L3A4 9 |
DJNZ |
L3A4 9 |
Цикл задержки. |
|
CPL |
|
Инверсия бита 4. |
|
OR |
#EF |
Установка остальных битов. |
|
OUT |
(#FE),A |
Переключить динамик (бордюр белый). |
|
DEC |
C |
Контроль окончания цикла. |
|
JR |
NZ,L3A47 |
Возврат, если цикл не окончен. |
|
LD |
C, #C0 |
Задержка для подавления дребезга клавиши. |
L3A55 |
DJNZ |
L3A5 5 |
Цикл задержки. |
|
DEC |
C |
Контроль окончания работы. |
|
JR |
NZ,L3A55 |
Возврат, если работа не окончена. |
|
RET |
|
|
SCAN |
PUSH |
HL |
Сохранить регистры. |
|
PUSH |
DE |
|
|
PUSH |
BC |
|
L3A5E |
CALL |
#028E |
Сканирование клавиатуры вызовом KEY-SCAN. |
|
JR |
NZ,L3A5E |
Возврат, если нажаты 2 и более клавиши. |
|
LD |
A, E |
Извлечь номер нажатой клавиши. |
|
CP |
#27 |
Нажата только CAPS SHIFT? |
|
JR |
Z,L3A5E |
Возврат, если ДА. |
|
LD |
A, #FE |
Повторный |
|
IN |
A,(#FE) |
опрос клавиши |
|
BIT |
0,A |
CAPS SHIFT. |
|
LD |
A, E |
Восстановить номер нажатой клавиши. |
|
PUSH |
AF |
Сохранить номер клавиши и флаг Z. |
|
INC |
A |
Установить флаг Z, если клавиша не нажата. |
|
CALL |
NZ,TON |
Звуковой щелчок, если клавиша нажата. |
|
POP |
AF |
Восстановить номер клавиши и флаг Z. |
|
JR |
L3A97 |
Восстановление регистров и завершение п/п. |
P.SIM |
PUSH |
HL |
Сохранить регистры. |
|
PUSH |
DE |
|
|
CP |
#20 |
Нижняя граница отображаемого набора 9 6 литер |
|
JR |
C,L3A81 |
Переход вперед, если управляющий код. |
|
CP |
#80 |
Верхняя граница отображ. набора 96 литер. |
|
JR |
C,L3A83 |
Переход вперед, если печатный код. |
L3A81 |
LD |
A, #2E |
Загрузить код символа "точка". |
L3A83 |
LD |
DE,L3C00 |
Загрузить базовый адрес символьного набора. |
|
LD |
H, E |
Поместить в HL |
|
LD |
L, A |
код символа. |
|
ADD |
HL, HL |
Получение адреса |
|
ADD |
HL, HL |
первого байта |
|
ADD |
HL, HL |
шаблона символа |
|
ADD |
HL, DE |
в символьном наборе. |
|
POP |
DE |
Восстановить |
|
PUSH |
DE |
позицию печати. |
|
PUSH |
BC |
Сохранить ВС. |
|
LD |
B, #08 |
Цикл для перенесения 8 байтов. |
L3A91 |
LD |
A, (HL) |
Перенос байта шаблона символа |
|
LD |
(DE),A |
из символьного набора в дисплейный файл. |
|
INC |
HL |
Переход к следующему байту симв.набора. |
|
INC |
D |
Переход к следующей линии знакоместа. |
|
DJNZ |
L3A91 |
Цикл переноса 8 байтов. |
L3A97 |
JR |
L3B05 |
Восстановление регистров и выход из п/п. |
PR.B |
PUSH |
BC |
Сохранить ВС. |
|
LD |
C, #02 |
Цикл для печати двух символов. |
L3A9C |
LD |
A, B |
Перенести байт в аккумулятор. |
|
RLCA |
|
Поменять |
|
RLCA |
|
местами |
|
RLCA |
|
тетрады. |
|
RLCA |
|
|
|
LD |
B, A |
Сохранить результат. |
|
AND |
#0 F |
Выделить младшую тетраду. |
|
CP |
#0A |
Получить код символа, |
|
JR |
C,L3AAA |
соответствующий |
|
ADD |
A, #07 |
числу в |
L3AAA |
ADD |
A, #30 |
аккумуляторе. |
|
CALL |
P.SIM |
Печать символа на экране. |
|
INC |
E |
Адрес следующего знакоместа. |
|
DEC |
C |
Контроль окончания печати. |
|
JR |
NZ,L3A9C |
Возврат, если печать не окончена. |
|
POP |
BC |
|
|
RET |
|
|
PR.HL |
PUSH |
DE |
Сохранить |
|
PUSH |
BC |
регистры. |
|
LD |
B, H |
Печать содержимого |
|
CALL |
PR.B |
регистра Н. |
|
LD |
B, L |
Печать содержимого |
|
CALL |
PR.B |
регистра L. |
|
POP |
BC |
|
|
POP |
DE |
|
|
RET |
|
|
P.ATR4 |
CALL |
P.ATR2 |
Печать атрибутов (в А) в 2-х з/м по адр.в DE. |
|
INC |
DE |
Позиция печати для |
|
INC |
DE |
остальных знакомест. |
|
CALL |
P.ATR2 |
Печать атрибутов в двух знакоместах. |
|
DEC |
DE |
Восстановить |
|
DEC |
DE |
позицию печати. |
|
RET |
|
|
P.ATR2 |
PUSH |
BC |
|
|
RES |
7,C |
Установить флаг БАЙТОВОГО режима. |
|
CALL |
P.ATR |
Печать атрибутов в двух знакоместах. |
|
POP |
BC |
|
|
RET |
|
|
P.ATR |
PUSH |
HL |
Сохранить |
|
PUSH |
DE |
регистры. |
|
PUSH |
AF |
|
|
LD |
A, D |
Извлечь номер сегмента позиции печати. |
|
RRCA |
|
Сдвинуть номер |
|
RRCA |
|
сегмента в |
|
RRCA |
|
младшие биты. |
|
AND |
#03 |
Выделить номер сегмента. |
|
LD |
D, A |
Теперь в DE абсолютный номер з/м поз.печати. |
|
LD |
HL,#5800 |
Начальный адрес области атрибутов. |
|
ADD |
HL, DE |
Теперь в HL адрес атрибутов позиции печати. |
|
POP |
AF |
Извлечь значение атрибутов. |
|
BIT |
7,C |
Контроль режима (БАЙТЫ/СИМВОЛЫ). |
|
JR |
NZ,L3AEA |
Переход вперед, если СИМВОЛЫ. |
|
LD |
(HL),A |
Печать атрибутов. |
|
INC |
HL |
Адрес атрибутов следующего знакоместа. |
L3AEA |
LD |
(HL),A |
Печать атрибутов. |
|
JR |
L3B14 |
Восстановление регистров и выход из п/п. |
P.LIN |
PUSH |
HL |
Сохранить |
|
PUSH |
DE |
регистры. |
|
PUSH |
BC |
|
|
CALL |
PR.HL |
Печать адреса в начале строки. |
|
LD |
A, #07 |
Следующая позиция печати: 7-я колонка. |
|
OR |
E |
Соединить номер колонки с номером строки. |
|
LD |
E, A |
Установить позицию печати. |
|
BIT |
7,C |
Контроль режима. |
|
JR |
Z,L3B07 |
Переход вперед, если БАЙТОВЫЙ режим. |
|
LD |
B,#10 |
Будет напечатано 16 символов. |
L3AFD |
LD |
A, (HL) |
Извлечь код символа. |
|
CALL |
P.SIM |
Печать символа на экране. |
|
INC |
HL |
Адрес следующего символа. |
|
INC |
E |
Адрес следующего знакоместа. |
|
DJNZ |
L3AFD |
Цикл печати строки символов. |
L3B05 |
JR |
L3B13 |
Восстановление регистров и выход из п/п. |
L3B07 |
LD |
B, #08 |
Будет распечатано 8 байтов в HEX-коде. |
L3B09 |
PUSH |
BC |
Сохранить регистр В. |
|
LD |
B,(HL) |
Извлечь байт для печати. |
|
CALL |
PR.B |
Распечатка байта на экране. |
|
INC |
HL |
Адрес следующего отображаемого байта. |
|
INC |
E |
Пробел между столбцами. |
|
POP |
BC |
Извлечь регистр В. |
|
DJNZ |
L3B09 |
Цикл печати строки байтов в HEX-коде. |
L3B13 |
POP |
BC |
Восстановление |
L3B14 |
POP |
DE |
регистров |
|
POP |
HL |
и выход из |
|
RET |
|
подпрограммы. |
AB.LIN |
PUSH |
BC |
|
|
LD |
A, D |
Извлечь номер сегмента экрана. |
|
AND |
#18 |
Выделить номер сегмента. |
|
LD |
B, A |
Сохранить номер сегмента. |
|
LD |
A, E |
Извлечь номер строки (позиции печати). |
|
AND |
#E0 |
Выделить номер строки. |
|
RLCA |
|
Сдвинуть номер |
|
RLCA |
|
строки в |
|
RLCA |
|
младшие биты. |
|
OR |
B |
Получить абсолютный номер строки. |
POP BC ;
RET ;
Z.LIN CALL AB.LIN ;Номер строки, в которой находится курсор.
AND A ; Определить флаг Z (лишняя команда).
JR Z,L.DE ;Переход вперед, если строка нулевая.
DEC A ;Задать курсор на одну строку выше.
JR L.DE ;Переход вперед.
L.LIN CALL AB.LIN ;Номер строки, в которой находится курсор.
CP #17 "Это последняя строка?
JR Z,L.DE ;Переход вперед, если ДА.
INC A ;Курсор - строкой ниже.
L.DE LD E,A ;Сохранить абсолютный номер строки.
AND #18 ;Выделить номер сегмента экрана.
ADD A,#4 0 ;Получить в регистре D
LD D,A ;старший байт адреса строки.
LD A, E ;Извлечь абсолютный номер строки.
AND #07 ;Выделить относительный номер строки.
RRCA ; Получить в регистре Е
RRCA ; младший байт
RRCA ; адреса строки
LD E,A ;(нулевая колонка).
RET ;
STEP LD DE,#0008 ;Курсор переместится на 8 байтов.
BIT 7,C ;Контроль режима.
RET Z ;Выход, если БАЙТОВЫЙ режим.
LD E,#10 ;Курсор переместится на 16 символов.
RET ;
C.NUM PUSH HL ; Сохранить
PUSH DE ;регистры.
LD HL,#02 05 ;Базовый адрес таблицы клавиатуры.
LD D,#00 ,"Занести в DE номер
LD E,A "нажатой клавиши.
ADD HL,DE "Получить адрес кода в таблице.
LD A,(HL) "Извлечь код из таблицы.
JR L3B14 "Восстановление регистров и выход из п/п.
PR.SCR PUSH HL "Сохранить адрес ячейки, указываемой курсором.
PUSH DE "Сохранить позицию курсора на экране.
PUSH BC "Сохр.рег.С (флаг режима и N столбца курсора).
CALL AB.LIN "Строка экрана, в которой находится курсор.
ADD A, A "Умножить число полных
ADD A, A " строк (до курсора) на
ADD A, A "число байтов в строке.
BIT 7,C "Контроль режима.
JR Z,L3B6A "Переход вперед, если БАЙТОВЫЙ режим.
ADD A, A "Удвоить значение для СИМВОЛЬНОЙ строки.
JR NC,L3B6A "Переход вперед, если результат меньше 256.
DEC H "Вычесть 25 6 из адреса ячейки в курсоре.
L3B6A PUSH BC " Сохранить регистр С.
RES 7,C "Выделить N столбца, в к-ром находится курсор.
ADD A, C "Число яч.от начала экр.до курсора (MOD 25 6).
POP BC " Восстановить регистр С.
LD D,#00 "Занести в DE число распечатываемых ячеек
LD E,A "памяти от нач.экр. до курсора (MOD 256).
SBC HL,DE "Получить адрес начальной ячейки распечатки.
LD DE,#4001 "Начальная позиция печати.
LD B,#18 "Будет распечатано 24 строки.
L3B7 9 CALL P.LIN "Печать строки байтов или символов.
CALL DOWN "Переместить позицию печати вниз на 1 строку.
DJNZ L3B79 "Цикл печати 24 строк.
JR L3B13 "Восстановление регистров и выход из п/п.
UP PUSH BC " Сохранить
PUSH DE "регистры.
OR A "Сбр.флаг С (лишняя команда, т.к.уже сброшен).
CALL STEP "Ввести в DE шаг по строке.
SBC HL,DE "Уменьшить адрес ячейки в курсоре на 1 шаг.
POP DE "Восстановить позицию курсора.
LD B,E "Сохранить номер колонки.
CALL Z.LIN "Переместить курсор вверх, если не 0 строка.
JR L3B9D "Переход на восстановление номера колонки.
DOWN PUSH BC " Сохранить
PUSH DE "регистры.
CALL STEP "Ввести в DE шаг по строке.
ADD HL,DE "Увеличить адрес ячейки в курсоре на 1 шаг.
POP DE "Восстановить позицию курсора.
LD B,E "Сохранить номер колонки.
CALL L.LIN ,• Перемест. курсор вниз, если строка не послед.
L3B9D LD A, B "Извлечь номер колонки.
AND #1F "Выделить номер колонки.
OR E "Соединить с новым номером строки.
LD E,A "Установить новую позицию курсора.
XOR A "Установить флаг Z.
POP BC "
RET "
LEFT DEC HL "Уменьшить адрес ячейки, указываемой курсором.
LD A, C "Извлечь номер столбца распечатки.
AND #7F "Выделить номер столбца.
JR Z,L3BB5 "Переход вперед, если нулевой столбец.
DEC C "Уменьшить номер столбца.
DEC E "Сдвинуть курсор влево на 1 экранную колонку.
BIT 7,C "Контроль режима.
JR NZ,L3BB3 "Переход вперед, если СИМВОЛЬНЫЙ режим.
DEC E " Сдвинуть курсор еще 2 раза, т. к. в БАЙТОВОМ
DEC E "режиме столбец занимает 3 колонки.
L3BB3 XOR A "Установить флаг Z.
RET "
L3BB5 CALL Z.LIN "Переместить курсор вверх, если не 0 строка.
BIT 7,C "Контроль режима.
JR Z,L3BC2 "Переход вперед, если БАЙТОВЫЙ режим.
LD C,#8F "Уст.счетчик на СИМВОЛЬНЫЙ режим и столбец 15.
OR #16 "Установить номер колонки для курсора.
JR L3BC6 "Переход вперед.
L3BC2 LD C,#07 "Уст.БАЙТОВЫЙ режим и столбец 7 (последний).
OR # 1C "Установить номер колонки для курсора.
L3BC6 LD E,A "Установить позицию курсора.
XOR A "Установить флаг Z.
RET "
RIGHT INC HL "Увеличить адрес ячейки, указываемой курсором.
LD A, C "Извлечь номер столбца.
CP #8F "Последний столбец в СИМВОЛЬНОМ режиме?
JR Z,L3BDC "Переход вперед, если ДА.
CP #07 "Последний столбец в БАЙТОВОМ режиме?
JR Z,L3BDC "Переход вперед, если ДА.
RLA "Контроль режима.
JR C,L3BD8 "Переход вперед, если СИМВОЛЬНЫЙ режим.
INC E " Сдвинуть позицию
INC E " курсора на один
L3BD8 INC E "столбец вправо.
INC C "Увеличить значение счетчика столбцов.
XOR A "Установить флаг Z.
RET "
L3BDC AND #8 0 "Обнулить
LD C,A "счетчик столбцов.
CALL L.LIN "Сдвинуть курсор вниз, если не послед.строка.
OR #07 "Начальный номер колонки для нулевого столбца.
LD E,A "Установить курсор в начало строки.
XOR A "Установить флаг Z.
RET "
WIND LD A,#2 8 "Атрибуты голубого фона и черных чернил.
CALL P.ATR "Печать атрибутов (курсор).
L3BEC CALL PR.SCR "Печать экрана (24 строки).
BIT 7,C "Контроль режима.
JR Z,L3BFC "Переход вперед, если БАЙТОВЫЙ режим.
PUSH DE "Сохранить позицию курсора.
LD DE,#487B "Позиция байта, дублирующего символ в курсоре.
LD B, (HL) "Загрузить код символа, указанного курсором.
CALL PR.B "Распечатать код символа в HEX-коде.
POP DE "Восстановить позицию курсора.
L3BFC CALL SCAN "Сканировать клавиатуру.
PUSH AF "Сохранить результаты сканирования.
L3C00 INC A "Установить флаг Z, если клавиша не нажата.
JR NZ,L3C06 "Переход вперед, если клавиша не нажата.
POP AF "Компенсация стека.
JR L3BEC "Возврат на печать экрана.
L3C06 LD A,#38 "Атрибуты белого фона и черных чернил.
CALL P.ATR "Стереть курсор.
POP AF "Извлечь результаты сканирования.
RET NZ "Вых.из п/п, если клав. нажата без CAPS SHIFT.
CP #03 "Нажата клавиша "DOWN"?
CALL Z,DOWN "Переместить курсор вниз, если ДА.
L3C12 JR Z,WIND "Возврат к началу, если курсор перемещен.
CP #04 "Нажата клавиша "LEFT"?
CALL Z,LEFT "Переместить курсор влево, если ДА.
L3C19 JR Z,L3C12 "Возврат к началу, если курсор перемещен.
CP #0B "Нажата клавиша "UP"?
CALL Z,UP "Переместить курсор вверх, если ДА.
L3C2 0 JR Z,L3C19 "Возврат к началу, если курсор перемещен.
CP #13 "Нажата клавиша "RIGHT"?
CALL Z, RIGHT "Переместить курсор вправо, если ДА.
JR Z,L3C2 0 "Возврат к началу, если курсор перемещен.
CP #20 "Установить флаг Z, если нажата BREAK.
RET "
CLS LD A,#38 "Атрибуты для всего экрана: PAPER 7" INK 0.
|
PUSH |
HL |
Сохранить |
|
PUSH |
BC |
регистры. |
|
LD |
DE,#5AFE |
Подготовить регистры |
|
LD |
BC,#02FF |
к заполнению |
|
LD |
H, D |
области |
|
LD |
L, C |
атрибутов. |
|
LD |
(HL),A |
Занести байт в послед. ячейку обл. атрибутов. |
|
LDDR |
|
Заполнить область атрибутов. |
|
XOR |
A |
Код для заполнения дисплейного файла. |
|
DEC |
HL |
Подготовить регистры |
|
DEC |
DE |
к заполнению |
|
LD |
BC,#17FF |
дисплейного файла. |
|
LD |
(HL),A |
Занести байт в последнюю ячейку диспл.файла. |
|
LDDR |
|
Заполнить дисплейный файл. |
|
LD |
DE,#4001 |
Начальная позиция печати. |
|
POP |
BC |
|
|
POP |
HL |
|
|
RET |
|
|
IN B |
SLA |
B |
Сдвиг |
|
SLA |
B |
младшей |
|
SLA |
B |
тетрады |
|
SLA |
B |
в старшую. |
|
OR |
B |
Соединить знач. рег. В с тетрадой в рег. А. |
|
LD |
B, A |
Поместить чисто в регистр В. |
|
RET |
|
|
K.CONT |
CALL |
SCAN |
Сканирование клавиатуры. |
|
CP |
#FF |
Ни одна клавиша не нажата? |
|
JR |
Z,K.CONT |
Возврат на начало, если ДА. |
F.CONT |
CALL |
C.NUM |
Преобразовать номер клавиши в код символа. |
|
CP |
#30 |
Нижняя граница кодов цифр. |
|
JR |
C,L3C6E |
Переход вперед, если не цифра. |
|
CP |
#47 |
Верхняя граница кодов цифр. |
|
RET |
NC |
Выход из п/п, если не цифра. |
|
CP |
#40 |
Преобразование |
|
JR |
C,L3C6C |
кода цифры |
|
SUB |
#07 |
в соответствующее |
L3C6C |
SUB |
#30 |
число. |
L3C6E |
CCF |
|
Если код символа преобразован в число, |
|
RET |
|
то устанавливается флаг С. |
IN4 |
LD |
A,#28 |
Атрибуты голубого фона и черных чернил. |
|
CALL |
P.ATR4 |
Печать атрибутов в четырех знакоместах. |
|
CALL |
PR.HL |
Распечатка рег.HL на экр. (случайное число). |
|
CALL |
K.CONT |
Ожидание нажатия клавиши. |
|
RET |
NC |
Выход, если нажата не цифра (в HEX-коде). |
|
CALL |
IN_HL |
Ввести со сдвигом число в регистр HL. |
|
JR |
IN4 |
Возврат на начало п/п. |
IN2 |
LD |
A,#28 |
Атрибуты голубого фона и черных чернил. |
|
CALL |
P.ATR2 |
Печать атрибутов в двух знакоместах. |
|
CALL |
PR.B |
Распечатка регистра В на экране (в HEX-коде). |
|
DEC |
E |
Восстановить |
|
DEC |
E |
позицию печати. |
|
CALL |
K.CONT |
Ожидание нажатия клавиши. |
|
RET |
NC |
Выход, если нажата не HEX-цифра. |
|
CALL |
IN_B |
Ввести со сдвигом число в регистр В. |
|
JR |
IN2 |
Возврат на начало п/п. |
MEN4 |
LD |
C, #01 |
Будет введено одно 4-значное число. |
|
LD |
DE,#4001 |
Позиция печати. |
|
JR |
L3CA0 |
Переход вперед. |
MEN4-D |
LD |
C, #02 |
Будет введено два 4-значных числа. |
MEN4-A |
CALL |
CLS |
Очистить экран. |
L3CA0 |
CALL |
IN4 |
Ввести 4-значное число с клавиатуры в рег.HL. |
|
CP |
#0D |
Нажата клавиша ENTER? |
|
JR |
NZ,L3CA0 |
Возврат на ввод числа, если НЕТ. |
|
EX |
(SP),HL |
Поместить введенное число в стек. |
|
PUSH |
HL |
Вернуть в стек адрес возврата из п/п. |
|
LD |
A, #38 |
Атрибуты белого фона и черных чернил. |
|
CALL |
P.ATR4 |
Стереть голубой фон в поз. введенного числа. |
|
CALL |
DOWN |
Переместить позицию печати вниз. |
|
DEC |
C |
Контроль окончания ввода. |
|
JR |
NZ,L3CA0 |
Возврат, если ввод не окончен. |
|
RET |
|
|
MEN2 |
LD |
C, #01 |
Будет введено одно 2-значное число. |
MEN2-A |
CALL |
IN2 |
Ввести 2-значное число в регистр В. |
|
CP |
#0D |
Нажата клавиша ENTER? |
|
JR |
NZ,MEN2-A |
Возврат на ввод числа, если НЕТ. |
|
LD |
A, B |
Извлечь введенное число. |
|
BIT |
0, C |
Контроль четности номера вводимого числа. |
|
EXX |
|
|
|
JR |
NZ,L3CC7 |
Переход вперед, если номер числа нечетный. |
|
LD |
H, A |
Загрузить введенное число в регистр Н'. |
|
JR |
L3CCA |
Переход вперед. |
L3CC7 |
LD |
L, A |
Загрузить введенное число в регистр L'. |
|
EX |
(SP),HL |
Поместить введенное число (числа) в стек. |
|
PUSH |
HL |
Вернуть адрес возврата из п/п в стек. |
L3CCA |
EXX |
|
|
|
LD |
A, #38 |
Атрибуты белого фона и черных чернил. |
|
CALL |
P.ATR2 |
Стереть голубой фон в позиции печати. |
|
CALL |
DOWN |
Переместить позицию печати вниз. |
|
DEC |
C |
Контроль окончания ввода. |
|
JR |
NZ,MEN2-A |
Возврат, если не окончен. |
|
RET |
|
|
T.SC.5 |
LD |
BC,#0008 |
Установить задержку времени 0,5 сек. |
T.SCAN |
PUSH |
AF |
Компенсация стека в цикле. |
L3CDB |
POP |
AF |
|
|
CALL |
SCAN |
Сканирование клавиатуры. |
|
PUSH |
AF |
Сохранить результат сканирования. |
|
INC |
A |
Контроль нажатия клавиши. |
|
JR |
NZ,L3CE8 |
Переход вперед, если клавиша нажата. |
|
DJNZ |
L3CDB |
Цикл задержки времени со сканированием. |
|
DEC |
C |
Контроль истечения времени задержки. |
|
JR |
NZ,L3CDB |
Возврат, если время не истекло. |
L3CE8 |
POP |
AF |
Извлечь результат сканирования. |
|
RET |
|
|
LOAD |
INC |
D |
Сбросить флаг Z. |
|
EX |
AF,AF' |
Сохранить флаги и флаговый байт. |
|
DEC |
D |
Восстановить регистр D. |
|
DI |
|
Запретить прерывания. |
|
LD |
A, #05 |
Задать голубой цвет для бордюра. |
|
OUT |
(#FE),A |
"Установить цвет бордюра. |
|
CALL |
#0562 |
"LOAD/VERIFY без обработки ошибок и без EI |
|
RET |
C |
"Выход из п/п, если нет ошибки ввода. |
EXIT |
CALL |
TON |
"Звуковой щелчок. |
|
CALL |
T.SC.5 |
"Сканирование клавиатуры в течение 0,5 сек |
|
INC |
A |
"Контроль нажатия клавиши. |
|
JR |
Z,EXIT |
"Возврат, если клавиша не нажата. |
|
RET |
|
" |
Стандартная таблица клавиатуры (#0205).
№ |
HEX- |
Сим |
№ |
HEX- |
Сим |
№ |
HEX- |
Сим |
№ |
HEX- |
Сим |
клав. |
код |
вол |
клав. |
код |
вол |
клав. |
код |
вол |
клав. |
код |
вол |
#00 |
#42 |
B |
#0A |
#55 |
U |
#14 |
#33 |
3 |
#1E |
#53 |
S |
#01 |
#48 |
H |
#0B |
#37 |
7 |
#15 |
#45 |
E |
#1F |
#5A |
Z |
#02 |
#59 |
Y |
#0C |
#34 |
4 |
#16 |
#44 |
D |
#20 |
#20 |
SPC |
#03 |
#36 |
6 |
#0D |
#52 |
R |
#17 |
#58 |
X |
#21 |
#0D |
ENT |
#04 |
#35 |
5 |
#0E |
#46 |
F |
#18 |
#0E |
SS |
#22 |
#50 |
P |
#05 |
#54 |
T |
#0F |
#43 |
C |
#19 |
#4C |
L |
#23 |
#30 |
0 |
#06 |
#47 |
G |
#10 |
#4D |
M |
#1A |
#4F |
O |
#24 |
#31 |
1 |
#07 |
#56 |
V |
#11 |
#4B |
K |
#1B |
#39 |
9 |
#25 |
#51 |
Q |
#08 |
#4E |
N |
#12 |
#49 |
I |
#1C |
#32 |
2 |
#26 |
#41 |
A |
#09 |
#4A |
J |
#13 |
#38 |
8 |
#1D |
#57 |
W |
- |
- |
CS |
Примечание. Номеру клавиши #27 соответствует CAPS SHIFT, но в таблице #0205 для нее не отведено места (таблица состоит из 39 байтов).
Описание работы программы.
Любая взламывающая программа должна как можно меньше "наследить" в ОЗУ, чтобы скрыть факт взлома от защитных процедур исследуемой программы, а также чтобы не повредить ее, поскольку она может занимать все ОЗУ. "Хаккер-93" для служебной работы использует только стек и, соответственно, имеет средства обхода защит, использующих стек. Наиболее неприятным защитным приемом является помещение стека в область дисплейного файла - тогда стирание экрана уничтожит стек. Может быть применен прием жесткого ограничения размеров стека - тогда монитор, записывая в стек свои данные, неизбежно уничтожит часть программы.
В первом случае монитор сразу после входа просигнализирует звуковыми щелчками, что нужно директивой "Р" скопировать стек в более подходящее место, но до этого обязательно нужно вывести картинку на магнитофон (вместе с расположенным в ней стеком) клавишей "Q", а перед возвратом в программу ввести картинку директивой "М".
Во втором случае нужно нажимать кнопку "NMI" вместе с клавишей CAPS SHIFT. Тогда монитор запишет в стек только три числа, а остальное "сбросит" в область цветовых атрибутов и даст знать щелчками, что стек нужно куда-то убрать.
Кроме кнопки "NMI", монитор можно вызвать из точек прерывания командами CALL #0067 и CALL #002B. В первом случае выполняется опрос клавиши CAPS SHIFT и прочие действия, как по вызову "NMI", а во втором ("короткий вход") нажатие CAPS SHIFT имитируется без опроса.
Входной блок.
Сразу после входа монитор записывает в стек (где уже имеется адрес возврата) значения AF и HL, после чего анализирует состояние клавиши CAPS SHIFT, фиксирует значение SP и регистра R.
47
Одновременно второй бит регистра флагов (флаг четности) фиксирует состояние триггера прерываний (0 - запрет, 1 - разрешение). Затем, если нажата клавиша CAPS SHIFT, в SP заносится адрес #5B00 (конец области атрибутов), и продолжается загрузка в стек значений регистров.
Вот полный перечень загружаемых значений: адрес возврата, AF, HL, RF, IF, SP, IX, IY, BC, DE, AF', BC', DE', HL'. Следует помнить, что помещенное в стек значение SP указывает на ячейку со значением регистра L, а то значение, которое выводится на экран директивой "Р", указывает адрес ячейки со значением регистра L'. А еще надо помнить, что при копировании стека из области атрибутов (после действия клавиши CAPS SHIFT) стек "рвется" и выше значения RF расположится "мусор", захваченный из области буфера ZX-принтера. Прерывания, кстати, запрещаются.
После загрузки в стек состояния процессора, контролируется значение указателя стека и, если оно ниже, чем #5B20, то выдаются звуковые щелчки, которые означают, что стек если и не в экране, то "въедет" туда при вызове директивы. Нажав любую клавишу, мы прекратим щелчки и попадем в точку OUT (#388F). В этой знаменитой точке начинается процедура ожидания ввода директив, сюда передается управление после окончания их работы. Эту точку можно использовать для входа в монитор, если не нужны описанные выше формальности и выход по директиве "Е". Если прерывания разрешены, то прямой вход в эту точку покажет жизнь системных переменных (естественно, в директиве "V"), бег системных часов, зоны "микрофонного эффекта" в экранной области, когда коды в ячейках забиваются шаблонами их символов, а шаблоны воспринимаются как коды и забиваются новыми шаблонами. Можно наблюдать деловитое мельтешение чисел в стеке, с дрожью глядеть на хлещущие в ОЗУ молнии сбоев... При запрещенных прерываниях системные переменные мертвы, а числа в стеке чинно изменяются при перемещениях курсора.
Блок директив.
Режим ожидания ввода директив легко узнается по последовательному изменению цвета бордюра через каждые 2 секунды. Как можно заметить, входной блок монитора не портит картинки, исключая вход с нажатием клавиши CAPS SHIFT.
Директива "Q" автоматически выведет картинку на магнитофон в виде стандартного блока кодов без заголовка. Если в ней что-то спрятано, то можно потом ввести ее в ОЗУ и просмотреть.
Директива "Р" портит только четыре знакоместа в левом верхнем углу экрана, где на голубом фоне выведет значение указателя стека. Кстати, числа в мониторе представляются только в HEX-коде. Значение SP можно редактировать цифровыми клавишами, а после утверждения клавишей ENTER 40 байтов из области стека копируются по новому значению указателя. Во избежание неприятностей с программой, следует копировать стек в свободную область памяти или, в крайнем случае, в область, где хранятся экраны.
Директива "С" стирает экран и входит в меню ввода трех 4-значных чисел - это начальный адрес копируемого блока, его длина в байтах и начальный адрес копии. Надо сказать, что меню в мониторе очень жесткое, оно не допускает изменения уже утвержденного числа, не предусматривает отмены директивы. Просто в левом верхнем углу на голубом поле распечатывается число, которое можно редактировать. После утверждения клавишей ENTER голубое поле смещается ниже, и в нем возникает другое число и т. д.
После набора всех чисел происходит переход к исполнению директивы. Следует помнить, что нулевая длина блока воспринимается монитором как 65536 байтов, то есть все поле памяти. Текстовых подсказок нет, поэтому надо помнить, какое именно число и в какой директиве вводится в данный момент. Итак, все числа введены, и утверждение последнего из них клавишей ENTER одновременно явится командой на исполнение директивы.
Директива "С" копирует блоки корректно при любых введенных значениях. Это достигается за счет того, что вниз по адресам копирует команда LDIR, а вверх - команда LDDR с соответствующим перерасчетом регистров. Пользователь может представить себе действие этой директивы так, как если бы блок, указанный первыми двумя числами копировался за пределы компьютера, а затем вписывался с адреса, указанного третьим числом. Данная директива весьма удобна, когда надо раздвинуть или сдвинуть части машинного кода, чтобы вставить или выбросить какие-то команды.
Директива "Е" извлекает из стека и загружает в регистры те значения, которые были в них на момент вызова монитора. При этом значение SP, записанное в стеке, используется таким образом, что даже в случае полного или частичного копирования стека директивой "Р" происходит возврат в прежний стек. Семь младших битов регистра R инкрементируются при чтении каждого кода операции (КОП), то есть 1-2 раза на каждой команде. Следовательно, чтобы программа по значению регистра R не обнаружила вмешательства в свою работу, нужно его скомпенсировать, то есть вычесть " лишние" инкременты. В мониторе от каждой из трех точек входа (#002B, #0066 и #0067) до захвата значения регистра R находится одинаковое количество команд (команда NOP по адресу #0066 компенсирует команды CALL в точках прерывания, так как при входе по "NMI" регистр R не инкрементируется). Это позволяет скомпенсировать регистр R одним числом. Также по значению флага Р регистра флагов восстанавливается состояние триггера прерываний. Выход в вызывающую программу происходит по команде RET.
Директива "М" вводит в меню начальный адрес блока, его длину, а также флаговый байт (стандартное значение - #00 для заголовка и #FF для блока кодов). Блок может быть введен с ленты только с тем флаговым байтом, с которым он выводился. После утверждения флагового байта директива ожидает нажатия клавиши "S" (SAVE), "L" (LOAD) или "V" (VERIFY). В первом случае происходит немедленный вывод блока или заголовка, а в других - бордюр становится голубым и ожидается блок с ленты. Подпрограммы "SAVE" и "LOAD/VERIFY" запрещают прерывания (и уже не разрешают). Клавиша BREAK прерывает действие этих подпрограмм. В случае корректной загрузки или верификации происходит выход из директивы, а при ошибке - Вы услышите щелчки.
Директива "N" вводит в меню начальный адрес, длину блока и код, которым будет заполнен этот блок.
Директива "I" без порчи экрана выведет слева вверху на голубом поле четырехзначное число, которое можно редактировать. Это адрес ячейки памяти. После утверждения адреса клавишей ENTER на месте старшего байта адреса распечатывается значение этой ячейки. Его тоже можно редактировать. После нажатия ENTER число запишется в ячейку и последует выход из директивы. Эта директива должна особенно понравиться любителям POKES.
Директива "F" вводит в меню начальный адрес и длину блока, а затем четыре одиночных байта. В этих байтах вводится разыскиваемая цепочка длиной 1-3 байта, после которой ставится маркер - код #FF. Директива сначала предполагает длину цепочки 3 байта и проверяет наличие маркера на 4-м месте. Если его там нет, то предполагается, что в цепочке два кода, и маркер ищется на 3-м месте. Если его и там нет, то без дальнейших проверок будет отыскиваться только первый код. После утверждения 4-го байта клавишей ENTER экран стирается, и на нем распечатываются адреса начала цепочки в памяти. К примеру, если отыскивается цепочка из трех кодов #FF, а в памяти обнаружится цепочка из пяти кодов #FF, то на экране распечатаются три первые адреса этой цепочки. Выход из директивы - по окончании просмотра блока, либо по заполнении экрана. На просмотр всей памяти уходит порядка 1,5 секунды.
Директива "V" стирает экран и вводит в меню только адрес входа в память. После утверждения на экране распечатываются 24 строки по 8 байтов в строке, начиная с утвержденного адреса. Информация из отображаемой области извлекается несколько сот раз в секунду, поэтому все изменения в этой области немедленно отображаются на экране. В основном, это сбои, но может быть и стек, и другие случаи. Причем, информация между столбцами и в свободных знакоместах экрана не регистрируется (то есть остается статичной), поэтому, попавшие туда сбойные байты останутся до переключения режимов.
Левый верхний байт распечатки находится в голубом курсоре. Курсор управляется клавишами со стрелками и при попытке выхода за пределы экрана автоматически вызывает роллинг экрана на одну строку, так, что курсор может бегать по всей памяти, все время оставаясь в пределах экрана. Переход из строки в строку при горизонтальном перемещении курсора происходит также автоматически.
Байт, находящийся в курсоре, редактируется цифровыми клавишами без утверждения, что требует осторожности, так как случайное нажатие цифровой клавиши обязательно испортит байт в ОЗУ. По этой причине неприятности гарантируются тем, у кого 40-клавишная клавиатура с плохо работающей клавишей CAPS SHIFT.
Автоматический роллинг экрана (непрерывный) вызывается клавишей "R", обратный роллинг - клавишей "U". Отменяется роллинг нажатием любой клавиши. Перелистать память за несколько минут можно, удерживая клавишу "Р", обратное перелистывание - клавиша "О".
Нажатие клавиши "G" запустит из экрана программу с адреса, указанного курсором. Если эта программа вся умещается в экране, сохраняет регистры C, DE, HL, а числовые результаты своей работы помещает в ячейки, присутствующие на экране, то командой перехода в точку #39D0 она вернется в этот же экран, на котором отобразятся и результаты ее работы. Кстати, в регистре HL содержится адрес байта в курсоре. Манипулируя этим значением, можно организовать и роллинг, и прыжки в любую область памяти.
Когда курсор попадает в область, заполненную одинаковыми байтами, клавиша "J" поможет " перепрыгнуть" эту область. Курсор остановится на первом отличающемся байте.
Клавиша "S" включит символьный режим отображения 24 строк по 16 символов в строке. Распечатка производится с адреса, указанного курсором. Коды, не входящие в набор 96 символов, отображаются в виде точек. Сервис здесь тот же, что и в байтовом режиме. HEX-код символа, находящегося в курсоре, отображается правее распечатки в 12-й экранной строке, что облегчает редактирование (только цифровыми клавишами!).
Перейти в байтовый режим можно нажатием клавиши "Н". Выход из директивы - клавиша BREAK. Клавиша ENTER дублирует клавишу RIGHT.
Блок подпрограмм.
TON (Звуковой щелчок). Посредством циклов, четырежды переключает динамик, выдавая щелчок при нажатии клавиши, после чего переходит в циклы задержки времени для подавления дребезга контактов. Общее время работы - 0,3 сек.
SCAN (Сканирование клавиатуры). Сканирует клавиатуру посредством стандартной подпрограммы KEY-SCAN (#028E). При нажатии только CAPS CHIFT или двойных клавиш - возврат в сканирование. Извлекает номер нажатой клавиши. Если при этом нажата CAPS SHIFT, устанавливает флаг
Z. Состояние CAPS CHIFT определяется после выхода из KEY-SCAN (см. ZX-РЕВЮ-94, N2, стр.52) отдельным опросом клавиши. Если клавиша (кроме CAPS SHIFT) нажата, выдается щелчок.
P.SIM (Печать символа на экране). Печатает символ из стандартного набора 96 литер, либо точку. В регистре DE - адрес нулевой линии нужного знакоместа.
PR.B (Распечатка регистра В на экране в HEX-коде). Преобразует тетрады из регистра В в коды символов цифр и распечатывает их. Позиция печати переходит на следующее знакоместо.
PR.HL (Распечатка регистра HL на экране в HEX-коде). Загружает в регистр В последовательно регистр H и регистр L, вызывая подпрограмму PR.B. Позиция печати сохраняется (нулевая линия начального знакоместа в DE).
P.ATR (Печать атрибутов в одном или двух знакоместах). Преобразует в регистре DE позицию печати в адрес атрибутов данного знакоместа, а затем загружает их (атрибуты) из аккумулятора в одно или два знакоместа, в зависимости от режима. Режим определяется старшим битом регистра C (0 - байты; 1 - символы) для печати курсора.
P.ATR2 (Печать атрибутов горизонтально в двух знакоместах). Сбрасывает флаг режима и вызывает подпрограмму P.ATR.
P.ATR4 (Печать атрибутов горизонтально в четырех знакоместах). Дважды вызывает подпрограмму P.ATR2.
P.LIN (Печать строки символов или байтов). С первой колонки экрана (адрес в DE) печатает содержимое HL (адрес начального кода распечатки), а затем распечатывает 8 байтов в HEX-коде или 16 символов, в зависимости от режима (флаг в регистре С).
AB.LIN (Абсолютный номер экранной строки). По значению позиции курсора (в DE) получает в регистре А значение абсолютного номера экранной строки от 0 до 23.
L.DE (Получение адреса в DE по номеру экранной строки). Выполняет действия, обратные подпрограмме AB.LIN, то есть по абсолютному номеру строки устанавливает в DE адрес ее нулевой линии нулевой колонки.
Z.LIN* (Контроль нулевой строки экрана). Декрементирует абсолютный номер строки, если она не нулевая, затем переходит в подпрограмму L.DE.
L.LIN* (Контроль последней строки экрана). Инкрементирует абсолютный номер строки, если она не последняя, затем переходит в подпрограмму L.DE.
STEP (Получение шага по строке для перемещения курсора). Заносит в DE шаг по строке (8 или 16) для вертикального перемещения курсора.
C.NUM (Определение кода символа по номеру нажатой клавиши). Заменяет в регистре А номер клавиши на код символа по таблице #0205.
P.SCR (Печать на экране 24 строк байтов или символов). По позиции курсора (в DE) и адресу ячейки памяти в курсоре (в HL) рассчитывает начальный адрес распечатки и выводит на экран 24 строки.
UP (Вверх). Перемещает курсор вверх, изменяя значения регистров HL и DE.
DOWN (Вниз). Полностью обратна подпрограмме UP. Подпрограммы UP и DOWN не изменяют DE, если не достигнут край экрана.
LEFT; RIGHT (Влево; вправо). Перемещают курсор назад или вперед на 1 адрес, изменяя DE и декрементируя (инкрементируя) регистр HL. По значению счетчика столбцов (7 битов регистра С) -переход в другую строку.
WIND (Окно). Распечатывает экран с курсором; сканирует клавиатуру, выполняя перемещение курсора. По нажатию других клавиш - выход из подпрограммы. Флаг Z=1, если нажата клавиша BREAK.
CLS (Очистка экрана). Устанавливает атрибуты INK 0; PAPER 7 посредством команды LDDR (см. ZX-РЕВЮ-92, № 9-10, стр. 208) заполняет область атрибутов и очищает дисплей. Устанавливает в DE #4001.
IN_B (Ввод числа в регистр В со сдвигом). Младшую тетраду в регистре B переносит в старшую, а на ее место вводит тетраду из рег. А.
IN_HL (Ввод числа в регистр HL со сдвигом). Выполняет операцию, аналогичную подпрограмме IN_B, с регистром HL.
K.CONT* (Сканирование клавиатуры до нажатия любой клавиши). При нажатии клавиши переходит в подпрограмму F.CONT.
F.CONT (Контроль нажатия цифровой клавиши в HEX-коде). Переводит номер клавиши в код символа. Код HEX-цифры заменяет числом с установленным флагом С.
IN2; IN4 (Ввод с клавиатуры 2- или 4-значного числа). Печатает на голубом фоне содержимое регистров В или HL. Редактирование - цифровыми клавишами. Выход из подпрограммы, если нажата не цифра.
MEN2; MEN4 (Меню для ввода 2- или 4-значных чисел с клавиатуры). Посредством подпрограммы IN2 или IN4 вводит количество чисел, заданное в регистре С и помещает в стек. Ввод в стек - по нажатию ENTER.
MEN4-D - точка для ввода в стек двух чисел плюс стирание экрана.
T.SCAN (Задержка времени со сканированием). Сканирует клавиатуру в течение времени, задаваемого в регистре ВС, затем выход из подпрограммы. По нажатию клавиши - выход немедленно.
T.SC.5 (Сканирование клавиатуры в течение 0,5 сек). Задает в регистре ВС задержку 0,5 сек., затем переходит в подпрограмму T.SCAN.
LOAD1 (Ввод блока кодов с магнитофона). Вводит через подпрограмму LD-BYTES (#0562) блок кодов с ленты. При ошибке переходит в подпрограмму EXIT.
EXIT (Подача щелчков в нештатной ситуации). Каждые 0,8 сек. выдает щелчок. По нажатию клавиши - выход из подпрограммы.
IN4 - Вход: DE - позиция печати. Выход: HL - введенное число; А - код символа нажатой клавиши (не цифры).
MEN2 - Вход: DE - позиция печати. Выход: число в стеке. Портит HL, B, DE, HL'. Обнуляет регистры А, С.
MEN4 - Вход: нет. Выход: число в стеке. Портит HL, DE. Обнуляет регистры C, A. MEN4-A Вход: С - количество вводимых чисел (до 24). Выход: число в стеке. Портит HL, DE. Обнуляет регистры С, А. Стирает экран.
T.SCAN - Вход: ВС - задержка времени. Выход: А - номер нажатой клавиши. Портит ВС. LOAD - Вход: IX - начальный адрес загрузки; DE - длина блока; A - флаговый байт; флаг C -LOAD/VERIFY. Выход: нет. Портит A, ВС, DE, HL. EXIT - Вход: нет. Выход: нет. Портит A, ВС.
Точки входа в подпрограммы.
Адрес |
Обозначение |
Входной блок. |
#002B |
"Короткий вход" - |
|
имитация нажатия CS. |
#005F |
п/п IN_HL |
#0066 |
Вход по нажатию |
|
кнопки "NMI". |
#0067 |
Вход из точки |
|
прерывания. |
#388F |
п/п OUT - вход без сохранения регистров. |
Блок директив. |
#38A5 |
Вход в директиву "Q" |
#38B7 |
Вход в директиву "C" |
#38D6 |
Вход в директиву "P" |
#38EB |
Вход в директиву "E" |
#390F |
Вход в директиву "M" |
#3936 |
Вход в директиву "N" |
#394A |
Вход в директиву "I" |
#395F |
Вход в директиву "F" |
#39C1 |
Вход в директиву "V" |
#39D0 |
Вход непосредственно в экран. |
Блок подпрограмм. |
#3A44 |
подпрограмма TON |
#3A5B |
подпрограмма SCAN |
#3A77 |
подпрограмма P.SIM |
#3A99 |
подпрограмма PR.B |
#3AB5 |
подпрограмма PR.HL |
#3AC2 |
подпрограмма P.ATR4 |
#3ACD |
подпрограмма P.ATR2 |
#3AD5 |
подпрограмма P.ATR |
#3AED |
подпрограмма P.LIN |
#3B17 |
подпрограмма AB.LIN |
#3B25 |
подпрограмма Z.LIN |
#3B2E |
подпрограмма L.LIN |
#3B36 |
подпрограмма L.DE |
#3B44 |
подпрограмма STEP |
#3B4D |
подпрограмма C.NUM |
Адрес |
Обозначение |
#3B59 |
подпрограмма P.SCR |
#3B83 |
подпрограмма UP |
#3B92 |
подпрограмма DOWN |
#3BA5 |
подпрограмма LEFT |
#3BC9 |
подпрограмма RIGHT |
#3BE7 |
подпрограмма WIND |
#3C2C |
подпрограмма CLS |
#3C2E |
Очистка экрана с атрибутами, установкой в регистре A. |
#3C4A |
подпрограмма IN_B |
#3C55 |
подпрограмма K.CONT |
#3C5C |
подпрограмма F.CONT |
#3C70 |
подпрограмма IN4 |
#3C81 |
подпрограмма IN2 |
#3C94 |
подпрограмма MEN4 |
#3C9B |
подпрограмма MEN4-D |
#3C9D |
подпрограмма MEN4-A |
#3CB5 |
подпрограмма MEN2 |
#3CB7 |
подпрограмма MEN2-A |
#3CD7 |
подпрограмма T.SC.5 |
#3CDA |
подпрограмма T.SCAN |
#3CEA |
подпрограмма LOAD |
#3CF6 |
подпрограмма EXIT |