Дж. Хардман, Э. Хьюзон
40 ЛУЧШИХ ПРОЦЕДУР
Мы продолжаем печать книгу Дж. Хардмана и Э. Хьюзона. Сегодня вашему вниманию предлагается подробный разбор еще 15 полезных процедур для самообразования. Начало см. "ZX-РЕВЮ" N1-2, стр. 17-28.
5.8 Сдвиг вниз на один символ.
Длина: 73
Количество переменных: 0 Контрольная сумма: 7987
Назначение: Эта программа сдвигает содержимое дисплейного файла вниз на 8 пикселей.
Вызов подпрограммы:
RANDOMIZE USR адрес
Контроль ошибок: Нет Комментарий: Нет
ЛИСТИНГ МАШИННЫХ КОДОВ
ЧИСЛА ДЛЯ ВВОДА
LD HL,22527 LD DE,22495 PUSH HL PUSH DE LD C,23 LD B, 32 LD A,(DE) LD (HL),A LD A,C AND 7 CP 1
JR NZ,NEXT_B SUB A LD (DE),A DEC HL DEC DE DJNZ COPY_B DEC C JR Z,REST LD A,C AND 7 CP 0
JR Z,N_BLOCK CP 7
JR NZ,NEXT_L PUSH DE LD DE,1792 AND A SBC HL,DE POP DE JR NEXT_L POP DE POP HL DEC D DEC H LD A,H CP 79
33 255 87 17 223 87
229 213
14 23 6 32 26 119 121
230 7 254 1 32 2 151
RET Z |
200 |
|
JR SAVE |
24 |
201 |
PUSH HL |
229 |
|
LD HL,1792 |
33 |
0 |
EX DE,HL |
235 |
|
AND A |
167 |
|
SBC HL,DE |
237 |
82 |
EX DE,HL |
235 |
|
POP HL |
225 |
|
JR NEXT L |
24 |
193 |
Как она работает:
В пару регистров HL загружается адрес последнего байта дисплейного файла, а в DE загружается адрес байта, соответствующего изображению, отстоящему на восемь линий вверх. HL и DE сохраняются на стеке. В C-регистр загружается число, на 1 меньшее, чем число строк на экране. Затем в B-регистр загружается количество байтов на одной линии дисплея - он используется, как счетчик. В аккумулятор загружается байт с адресом DE и это значение пересылается в ячейку по адресу HL. В аккумулятор загружается (для проверки) содержимое регистра C и, если оно равно 1, 9 или 17, то в ячейку по адресу DE помещается 0. HL и DE уменьшаются на единицу, указывая на следующий байт дисплея. Счетчик байтов в регистре B уменьшается и, если и он не равен 0, происходит переход к COPY_В.
Далее уменьшается счетчик строк в регистре C. Если он равен 0,происходит переход к процедуре 'REST'. Если C содержит 8 или 16, то происходит переход к процедуре 'N_BLOCK'. Если C не содержит 7 или 15, подпрограмма переходит к 'NEXT_L'. Затем из HL вычитается 1792 - теперь HL указывает на следующую треть экрана и подпрограмма переходит к 'NEXT_L'.
В процедуре REST значения DE и HL берутся из стека и из них вычитается число 256. В итоге DE и HL указывают на строку, позиция которой выше, чем та, что была в предыдущем цикле. Если HL содержит 20479, подпрограмма возвращается в BASIC, иначе происходит переход к процедуре SAVE.
В процедуре N_BLOCK, 1792 вычитается из DE - т.е. после этого DE указывает на следующий блок экрана. Подпрограмма затем переходит к NEXT_L.
5.9 Сдвиг влево на один пиксел.
Длина: 17
Количество переменных: 0
Контрольная сумма: 1828
Назначение: Сдвиг содержимого дисплейного файла на один пиксел влево.
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: Нет
Комментарии: Эта программа осуществляет более плавное перемещение, чем сдвиг влево на один символ, но требуется вызывать ее восемь раз, чтобы переместить дисплей на один полный символ.
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА |
АССЕМБЛЕР |
ЧИСЛА ДЛЯ |
|
LD HL,22527 |
33 |
255 |
|
LD C,192 |
14 |
192 |
NEXT_L |
LD B, 32 |
6 |
32 |
|
OR A |
183 |
|
NЕХТ_В |
RL (HL) |
203 |
22 |
|
DEC HL |
43 |
|
|
DJNZ NEXT B |
16 |
251 |
|
DEC C |
13 |
|
|
JR NZ,NEXT L |
32 |
245 |
Как она работает:
В пару регистров HL загружается адрес последнего байта дисплейного файла, а в регистр C загружается количество линий в дисплейном файле (он используется, как счетчик линии). В регистр "В" загружается количество байтов на одной линии (он используется, как счетчик байтов). Флаг переноса устанавливается в 0.
Байт, адресованный HL, сдвигается на один бит влево, бит переноса копируется в крайний правый бит, а крайний левый бит копируется во флаг переноса. Пара регистров HL уменьшается для указания на следующий байт, и счетчик (B-регистр) уменьшается. Если и он не равен 0, подпрограмма осуществляет переход к NEXT_B, иначе уменьшается количество обрабатываемых линий, и, если оно не равно 0, подпрограмма возвращается к процедуре NEXT_L.
По окончании работы программа возвращается в BASIC.
5.10 Сдвиг вправо на один пиксел.
Длина: 17
Количество переменных: 0
Контрольная сумма: 1550
Назначение: Сдвиг содержимого дисплейного файла на один пиксел вправо.
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: Нет
Комментарий: Эта программа осуществляет более плавное перемещение, чем сдвиг вправо на один символ, но требуется восемь раз вызывать эту программу, чтобы переместить дисплей на один полный символ.
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА |
АССЕМБЛЕР |
ЧИСЛА ДЛЯ |
|
LD HL,16384 |
33 |
0 |
|
LD C,192 |
14 |
192 |
NEXT_L |
LD B, 32 |
6 |
32 |
|
OR A |
183 |
|
NEXT_B |
RR (HL) |
203 |
30 |
|
INC HL |
35 |
|
|
DJNZ NEXT B |
16 |
251 |
|
DEC C |
13 |
|
|
JR NZ,NEXT L |
32 |
245 |
|
RET |
201 |
|
64
Как она работает:
В пару регистров HL загружается адрес дисплейного файла, а в C-регистр загружается количество линий на экране (он используется, как счетчик линий). В регистр "B" загружается количество байтов на одной линии (он используется, как счетчик байтов). Флаг переноса устанавливается, в 0. Байт по адресу HL сдвигается на один бит вправо, бит переноса копируется в крайний левый бит, а крайний правый бит копируется во флаг переноса. Пара регистров HL увеличивается, указывая на следующий байт, и счетчик (B-регистр) уменьшается.
Если он не равен 0, подпрограмма осуществляет переход к NEXT_B, иначе уменьшается количество обрабатываемых линий, и, если оно не равно 0, подпрограмма возвращается к NEXT_L.
Закончив работу, процедура возвращается в BASIC.
5.11 Сдвиг вверх на один пиксел.
Длина: 91
Количество переменных: 0 Контрольная сумма: 9228
Назначение: Сдвиг содержимого дисплейного файла вверх на один пиксел. Вызов программы: RANDOMIZE USR адрес Контроль ошибок: Нет Комментарий: Нет
ЛИСТИНГ МАШИННЫХ КОДОВ
АССЕМБЛЕР |
ЧИСЛА ДЛЯ |
LD HL,16384 |
33 |
0 |
LD DE,16640 |
17 |
0 |
LD C,192 |
14 |
192 |
LD B,32 |
6 |
32 |
LD A,(DE) |
26 |
|
LD (HL),A |
119 |
|
LD A,C |
121 |
|
CP 2 |
254 |
2 |
JR NZ,NEXT B |
32 |
2 |
SUB A |
151 |
|
LD (DE),A |
18 |
|
INC DE |
19 |
|
INC HL |
35 |
|
DJNZ COPY B |
16 |
243 |
PUSH DE |
213 |
|
LD DE,224 |
17 |
224 |
ADD HL,DE |
25 |
|
EX (SP),HL |
227 |
|
ADD HL,DE |
25 |
|
EX DE,HL |
235 |
|
POP HL |
225 |
|
DEC C |
13 |
|
LD A,C |
121 |
|
AND 7 |
230 |
7 |
CP 0 |
254 |
0 |
JR NZ,SUBTR |
32 |
10 |
PUSH DE |
213 |
|
LD DE,2016 |
17 |
224 |
AND A |
167 |
|
SBC HL,DE |
237 |
82 |
POP DE |
209 |
|
JR N BLOCK |
24 |
14 |
CP 1 |
254 |
1 |
JR NZ,N BLOCK |
32 |
10 |
PUSH HL |
229 |
|
EX DE,HL |
235 |
|
LD DE,2016 |
17 |
224 |
AND A |
167 |
|
SBC HL,DE |
237 |
82 |
EX DE,HL |
235 |
|
POP HL |
225 |
|
LD A,C |
121 |
|
AND 63 |
230 |
63 |
CP 0 |
254 |
0 |
JR NZ,ADD |
32 |
6 |
LD A,7 |
62 |
7 |
ADD A,H |
132 |
|
LD H,A |
103 |
|
JR NEXT L |
24 |
187 |
CP 1 |
254 |
1 |
JR NZ,NEXT L |
32 |
183 |
LD A,7 |
62 |
7 |
64
65
7
ADD A,7 LD D,A LD A,C CP 1
Как она работает:
В пару регистров HL загружается адрес дисплейного файла, а в DE - адрес первого байта второй строки дисплея. В регистр "C" загружается число линий на экране. В регистр "В" загружается количество байтов на одной строке он используется как счетчик.
В аккумулятор загружается байт с адресом в DE и это значение передается в ячейку по адресу НL. В аккумулятор заносится содержимое регистра "С". Если оно равно 2, то DE указывает на нижнюю строку экрана и по этому адресу записывается 0. HL и DE увеличиваются, чтобы указать на следующий байт. Счетчик в регистре "В" уменьшается и, если он не равен 0, происходит переход к COPY_B.
224 добавляется к регистровым парам HL и DE, чтобы они указывали на следующую строку экрана. Затем уменьшается регистр C, счётчик линий. Если содержимое регистра C не кратно 8, происходит переход к SUBTR иначе 2016 вычитается из HL и происходит переход к N_BLOCK. Теперь HL указывает на следующие 8 линий.
В процедуре SUBTR, если значение (С-1) не кратно 8, происходит переход к N_BLOCK, иначе 2016 вычитается из DE, т.е. теперь DE указывает на следующие 8 линий. В процедуре N_BLOCK, если значение C-регистра кратно 64, 1792 добавляется к HL и делается переход NEXT_LINE - теперь HL указывает на следующий блок из 64 линий. В процедуре ADD, если значение (С-1) не кратно 64,1792 добавляется к DE, чтобы пара DE указывала на следующий блок 64 линий. Если C-регистр не содержит 1, то программа возвращается к N_LINE иначе -возврат в BASIC.
5.12 Сдвиг вниз на один пиксел.
Длина: 90
Количество переменных: 0 Контрольная сумма: 9862
Назначение: Сдвиг содержимого дисплейного файла вниз на один пиксел. Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: Нет Комментарий: Нет
ЛИСТИНГ МАШИННЫХ КОДОВ
ЧИСЛА ДЛЯ ВВОДА
LD HL,22527 LD DE,22271 LD C,192
33 255 87 17 255 86 14 192 6 32 26 119 121
254 2 32 2 151
NEXT_L LD В, 32 COPY_B LD A, (DE)
LD (HL),A
LD A,C CP 2
JR NZ,NEXT_B SUB A LD (DE),A
DEC HL DJNZ COPY_B PUSH DE LD DE,224 AND A
SBC HL,DE |
237 |
82 |
EX (SP),HL |
227 |
|
AND A |
1 |
67 |
SBC HL,DE |
237 |
82 |
EX DE,HL |
235 |
|
POP HL |
225 |
|
DEC C |
13 |
|
LD A,C |
121 |
|
AND 7 |
230 |
7 |
CP 0 |
254 |
0 |
JR NZ,ADD |
32 |
8 |
PUSH DE |
213 |
|
LD DE,2016 |
17 |
224 |
POP DE |
209 |
|
JR N BLOCK |
24 |
11 |
ADD CP 1 |
254 |
4 |
JR NZ,N BLOCK |
32 |
7 |
PUSH HL |
229 |
|
LD HL,2016 |
33 |
224 |
ADD HL,DE |
25 |
|
EX DE,HL |
235 |
|
POP HL |
225 |
|
LD A,C |
121 |
|
CP 0 |
254 |
0 |
JR NZ,SUBTR |
32 |
6 |
LD A,H |
124 |
|
SUB 7 |
214 |
7 |
LD H,A |
103 |
|
JR NEXT L |
24 |
188 |
CP 1 |
254 |
1 |
JR NZ,NEXT L |
32 |
184 |
LD A,D |
122 |
|
SUB 7 |
214 |
7 |
LD D,A |
87 |
|
LD A,C |
121 |
|
CP 1 |
254 |
1 |
JR NZ,NEXT L |
32 |
175 |
RET |
201 |
|
7
7
Как она работает:
В пару регистров HL загружается адрес последнего байта дисплейного файла, а в пару регистров DE загружается адрес байта линии, которая находится непосредственно над этим байтом. В регистр "С" загружается число линий экрана. В регистр "В" загружается количество байтов на одной строке дисплея - он используется, как счетчик.
В аккумулятор загружается байт из ячейки с адресом в DE, и это значение загружается в ячейку по адресу в HL. В аккумулятор загружается содержимое регистра "С" -если оно равно 2, то DE указывает на верхнюю строку экрана, в адрес которой заносится 0. HL и DE уменьшаются, чтобы указать на следующие байты. Счетчик (B-регистр) уменьшается и, если он не равен 0, происходит переход к COPY_B.
224 вычитается из регистровых пар HL и DE - теперь они указывают на следующую строку экрана. Регистр C (счетчик строк) уменьшается. Если содержимое регистра C кратно 8, т.е. выполнено 8 циклов для одной строки, происходит переход к процедуре ADD, иначе 2016 добавляется к HL и происходит переход к N_BLOCK - HL теперь указывает на следующие 8 линий.
В процедуре ADD, если значение (C-1) не делится без остатка на 8, происходит переход к N_BLOCK, в противном случае 2016 добавляется к DE, чтобы пара регистров DE указывала на следующие 8 линий. В процедуре N_BLOCK, если значение C - регистра делится без остатка на 64, из HL вычитается 1792 - HL теперь указывает на следующий блок из 64 линий, и происходит переход к NEXT_L. В процедуре SUBTR, если значение (С-1) не кратно 64, из DE вычитается 1792 - в итоге DE указывает на следующий блок из 64 линий.
Если C-регистр не содержит 1, то подпрограмма возвращается к NEXT_LINE, иначе - в BASIC.