┌──────────────────────────────┐ │ │ │ РЕТРО │ │ │ └──────────────────────────────┘ Дж.Хардман, Э.Хьюзон. 40 ЛУЧШИХ ПРОЦЕДУР. (Продолжение. Начало см. ZX РЕВЮ 97/1-2) РАЗДЕЛ B 4. ВВЕДЕНИЕ В разделе B представлены прог- раммы в машинном коде. Для прос- тоты и удобства использования они даны в стандартном формате. Во введении описывается этот формат и дается программа на BASIC'е, которая может быть ис- пользована для загрузки прог- рамм в память. Длина: Это длина программы в байтах. Количество Выполнение некоторых переменных: программ может по- требовать изменения значения одной или более переменных, передаваемых в прог- рамму через буфер принтера. Контрольная Каждая программа да- сумма: на в виде последова- тельности целых по- ложительных чисел, помещаемых в после- довательные ячейки памяти. Контрольная сумма (т.е. сумма всех чисел вводимой подпрограммы) дается для того, чтобы Вы были уверены в пра- вильности загрузки. Функция: Дается краткое опи- сание задачи, выпол- няемой с помощью программы. Переменные: Определяется имя, длина и адрес в бу- фере принтера каж- дой переменной. Пе- ременная длиной в один байт (целое по- ложительное число в пределах от 0 до 255) передается в программу из BASIC'а или с клавиатуры че- рез POKE. ┌──────────────────────────────┐ │ POKE ячейка, значение │ │ Двухбайтовая переменная │ │ передается с помощью 2-х │ │ команд: │ │ POKE ячейка, значение-256* │ │ INT(значение/256): │ │ POKE ячейка+1, │ │ INT(значение/256) │ │ Используемые ячейки являются │ │ ячейками памяти буфера │ │ принтера. │ └──────────────────────────────┘ Вызов Программы вызыва- подпрограммы: ются с использова- нием функции USR, которая должна быть включена в команду. Если про- грамма в машин- ном коде не пере- дает какое-то зна- чение обратно в BASIC по заверше- нии, то использу- ется команда: RANDOMIZE USR адрес ┌──────────────────────────────┐ │ Если Вам надо, чтобы │ │ результат был возвращен в ре-│ │ гистровой паре BC, то вызов │ │ делается так: │ │ LET A = USR адрес │ │ или │ │ PRINT USR адрес │ │ в зависимости от того, │ │ должны ли возвращаемые данные│ │ сохраняться в переменной │ │ BASIC'а или выводиться │ │ на экран. │ └──────────────────────────────┘ Контроль Объясняются провер- ошибок: ки, выполняемые про- граммой для нелогич- ных или противоречи- вых значений пере- менных, параметров и т.п. Комментарии: Объясняются возмож- ные варианты в прог- раммах. Листинг в Программы представ- машинном лены на языке ассем- коде: блера. Для загрузки в память использует- ся третья колонка - "Числа для ввода". Все числа здесь даны в десятичной систе- ме. Как она Объяснение принципа работает: работы программы. ЗАГРУЗЧИК МАШИННОГО КОДА Почти все программы из этой книги перемещаемые, т.е. они бу- дут работать корректно независи- мо от того, в каком месте RAM мы их поместим. Если программа не перемещаемая, то в комментариях объясняется, как она должна быть изменена, если ее нужно сохра- нить в другой области памяти. В разделе A (часть 2) мы видели, что ZX-SPECTRUM использует раз- личные части RAM для различных фукнций и что область между ячейками, указанными системными переменными RAMTOP и UDG, пред- назначена для хранения подпрог- рамм в машинном коде. Программа BP может быть ис- пользована для загрузки, измене- ния и перемещения программы в машинном коде. С ее помощью пользователь может переустано- вить указатель RAMTOP, что даст больше свободного пространства для машинных кодов; ввести прог- рамму с клавиатуры; перейти впе- ред или назад для корректировки ошибки; вставить или удалить часть программы. Программа BP. Загрузчик машинного кода (MC LOADER) 100 GO SUB 8100 200 REM ***** Вычисление доступной памяти 210 LET min = 1+PEEK 23730+256*PEEK 23731 220 LET p = PEEK 23732+256*PEEK 23733 230 LET t = p - min + 1 400 REM ***** Определение стартового адреса 410 PRINT "Lowest possible start = ";min..."Maximum space avalible = ";t 420 INPUT "Do you wish to change the lowest start address (Y or N) ?";z$ 430 IF z$="Y" OR z$="y" THEN GO TO 7000 440 INPUT "Enter address at which to start loading machine code";a 450 IF a<min OR a>p THEN BEEP .2,24: GO TO 440 500 GO SUB 8100 510 LET t=t-a+min 520 PRINT "You can use up to ";t" bytes"... 530 LET u=PEEK 23675+256*PEEK 23676 540 IF a<u AND u<p THEN PRINT "If you use more than ";u-a; "bytes, you will overwrite the user defined graphics area." 550 IF a>=U THEN PRINT "You will overwrite the user defined graphics area." 560 INPUT "Is that OK (Y or N) ? ";z$ 570 IF z$="N" OR z$="n" THEN GO TO 7000 580 IF z$<>"Y" AND z$<>"y" THEN BEEP .2,24: GO TO 560 700 REM *** GO AHEAD AND LOAD 710 LET l=a 750 GOSUB 8200 760 INPUT "Enter number, b, f, i, d or t ";z$ 770 IF z$="" THEN BEEP .2,24: GO TO 760 780 LET a$=CHR$ (CODE z$(1) - 32*(z$(1)>"@")) 790 GO TO 800+200*(a$="B")+300*(a$="F")+400*(a$="I")+500*(a$= "D")+600*(a$="T") 800 LET x=VAL z$ 810 IF l>p THEN BEEP .2,24: GO TO 750 820 IF x<0 OR x>256 OR x<>INT x THEN BEEP .2,24: GO TO 760 830 POKE l,x 840 LET l=l+1 850 GO TO 740 1000 REM *** Перемещение вперед 1010 LET l=l-1 1020 IF LEN z$>1 THEN LET l=l+1-VAL z$(2 TO) 1030 IF l<a THEN LET l=a 1040 GO TO 740 1100 REM *** Перемещение назад 1110 LET l=l+1 1120 IF LEN z$>1 THEN LET l=l-1+VAL z$(2 TO) 1130 IF l>p THEN LET l=p 1140 GO TO 740 1200 REM *** Вставка 1210 IF LEN z$=1 THEN LET n=1: GO TO 1225 1220 LET n=VAL z$(2 TO): IF n<1 OR n>p-1 OR n<> INT n THEN BEEP .2,24: GO TO 740 1225 CLS: GOSUB 8100: PRINT TAB 6;"Inserting in progress" 1230 FOR j=p TO l+n STEP -1 1240 POKE j, PEEK (j-n) 1250 NEXT j 1260 FOR j=l TO l+n-1 1270 POKE j,0 1280 NEXT j 1290 GO TO 740 1300 REM *** Удаление 1310 IF LEN z$=1 THEN LET n=1: GO TO 1330 1320 LET n=VAL z$(2 TO): IF n<1 OR n>p-l OR n<> INT n THEN BEEP .2,24: GO TO 740 1330 IF n<0 OR n>p-l THEN BEEP .2,24: GO TO 1320 1340 CLS : GOSUB 8100 : PRINT TAB 6;"DELETING IN PROGRESS" 1350 FOR j=l TO p-n 1360 POKE j, PEEK (j+n) 1370 NEXT j 1380 GO TO 740 1400 STOP 1401 PRINT AT 21,7;"PROGRAM TERMINATED" 1410 STOP 7000 REM *** Изменение RAMTOP 7010 INPUT "ENTER NEW START ADDRESS ";a 7020 IF a<27000 OR a>p THEN BEEP .2,24: GO TO 710 7030 CLEAR a-1 7040 RUN 7999 STOP 8100 CLS 8110 PRINT TAB 6;"MACHINE CODE LOADER"... 8120 RETURN 8200 REM *** Вывод содержимого памяти 8210 GOSUB 8100 8220 PRINT "ADDRESS DECIMAL CHECK SUM" 8230 LET c=0 8240 LET s=l-8 : IF s<a THEN LET s=a : GO TO 8280 8250 FOR j=a TO s-1 8260 LET c=c+PEEK j 8270 NEXT j 8280 LET f=s+17 : IF f>p THEN LET f=p 8290 FOR j=s TO f 8300 LET c=c+PEEK j 8310 PRINT AT j-s+3,1;j; TAB 12;PEEK j; TAB 22;c 8320 NEXT j 8400 LET pos=1-s+3 8410 PRINT AT pos,12; FLASH 1; PEEK l 8420 RETURN Когда программа BP запускает- ся, она печатает младший адрес, с которого программа в машинных кодах может быть введена и сох- ранена, т.е. на единицу больший, чем RAMTOP. В машине с 48К памяти младший адрес 65368, если пользователь на обновлял системную перемен- ную RAMTOP. В конце ОЗУ обычно резерви- руются 168 байтов для UDG, но программа позволяет пользовате- лю использовать и эту область, если он пожелает. Он может так- же выбрать новый возможный млад- ший адрес, который программа за- тем помещает в системную пере- менную RAMTOP, используя коман- ду CLEAR. Данные не могут быть введены по адресу, меньшему, чем 27000, т.к. иначе нарушаются границы области, требующейся для самой программы BP. Программа BP запрашивает адрес, с которого должна стартовать программа в машинных кодах. Таким образом, пользователь может резервировать область для нескольких процедур и затем загружать их каждую от- дельно. Рисунок BP1 показывает формат дисплея после того, как с ячей- ки 32000 была загружена програм- ма "Screen Invert". Первая ко- лонка - адрес, вторая - содержи- мое ячейки памяти с этим адре- сом, третья - контрольная сумма. Программа "Screen Invert" имеет 18 байтов в длину и ее кон- трольная сумма 1613. Следова- тельно, она занимает ячейки с 32000 до 32017 и контрольная сумма дана для ячейки 32017, т.е. сумма содержимого ячеек (32000...32017) равна 1613. ┌──────────────────────────────┐ │ MACHINE CODE LOADER │ ├──────────────────────────────┤ │ ADDRESS DECIMAL CHECK SUM │ │ 32000 33 33 │ │ 32001 0 33 │ │ 32002 64 97 │ │ 32003 1 98 │ │ 32004 0 98 │ │ 32005 24 122 │ ..... ... ... │ 32012 11 836 │ │ 32013 120 956 │ │ 32014 177 1133 │ │ 32015 32 1165 │ │ 32016 247 1412 │ │ 32017 201 1613 │ │ │ │ Рис. BP1. Представлен экран │ │ во время работы загрузчика │ │ машинного кода. Программа │ │ "Screen Invert" загружена с │ │ адреса 32000. │ └──────────────────────────────┘ На основном экране внимание пользователя привлекается к од- ной ячейке - содержимое этой ячейки мерцает. Эта ячейка яв- ляется текущей и первоначально это выбранный стартовый адрес программы. Пользователь вводит целое число между 0 и 255 вклю- чительно, которое программа MC LOADER помещает в текущую ячей- ку. Затем следующий адрес стано- вится текущей ячейкой. Пользова- тель может не вводить число, а вместо этого выбрать для коррек- тировки вариант, описанный в таблице BT1. ┌──────────┬───────────────────┐ │ Код │ Вариант │ ├──────────┼───────────────────┤ │B │Перейти на один │ │ │адрес назад │ │B n(число)│Перейти на n │ │ │адресов назад │ │F │Перейти на один │ │ │адрес вперед │ │F n(число)│Перейти на n │ │ │адресов вперед │ │I n(число)│Вставить n байтов, │ │ │каждый из которых │ │ │содержит 0 │ │D n(число)│Удалить n байтов в │ │ │текущей области │ │T │Закончить программу│ ├──────────┴───────────────────┤ │ Таблица BT1. │ │ Возможные варианты │ │редактирования машинного кода.│ └──────────────────────────────┘ 5. ПОДПРОГРАММЫ СДВИГА. 5.1. Сдвиг атрибутов влево. Длина: 23 Количество переменных: 1 Контрольная сумма: 1574 Назначение: Эта программа сдвигает атрибуты всех символов экрана влево на одно знакоместо. Переменные: Имя: new attr Длина: 1 Ячейка: 23296 Комментарий: это атрибут, вво- димый в крайнюю правую колонку. Вызов программы: RANDOMIZE USR адрес Контроль ошибок: нет. Комментарий: Эта программа по- лезна для выделения области тек- ста или графики. Для прокручива- ния только 22 верхних строк 24* должно быть изменено на 22. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,22528 33 0 88 LD A,(23296) 58 0 91 LD C,24 14 24* NEXT_L LD B,31 6 31 NEXT_C INC HL 35 LD E,(HL) 94 DEC HL 43 LD (HL),E 115 INC HL 35 DJNZ NEXT_C 16 249 LD (HL),A 119 INC HL 35 DEC C 13 JR NZ,NEXT_L 32 242 2 Как она работает: В пару регистров HL загружает- ся адрес области атрибутов. Ак- кумулятор загружается значением атрибута, вводимым в правую ко- лонку. В регистр C загружается количество строк для сдвига - он теперь может быть использован как счетчик строк. В регистр B заносится число на 1 меньшее, чем число символов в строке, чтобы он использовался как счет- чик. HL увеличивается, чтобы указать на следующий атрибут, который загружается в E-регистр. HL уменьшается, и по адресу HL помещается значение из E-регис- тра. HL увеличивается вновь, чтобы указать на следующий атри- бут. Регистр B уменьшается, и если он не равен 0, то происхо- дит переход к NEXT_C. HL теперь указывает на правую колонку, и по адресу HL помещается значение из аккумулятора. HL увеличивает- ся, чтобы указать на следующую строку - NEXT_L. Счетчик строк (регистр C) уменьшается. Если значение результата не равно 0, подпрограмма возвращается назад к NEXT_L. По окончании работы программа возвращается в BASIC. 5.2. Сдвиг атрибутов вправо. Длина: 23 Количество переменных: 1 Контрольная сумма: 1847 Назначение: Эта программа сдвигает атрибуты всех символов экрана вправо на одно знакоместо. Переменные: Имя: new attr Длина: 1 Ячейка: 23296 Комментарий: это атрибут, вво- димый в крайнюю левую колонку. Вызов программы: RANDOMIZE USR адрес Контроль ошибок: нет. Комментарий: Эта программа по- лезна для выделения области тек- ста или графики. Для прокручива- ния только 22 верхних строк 24* должно быть изменено на 22. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,23295 33 255 88 LD A,(23296) 58 0 91 LD C,24 14 24* NEXT_L LD B,31 6 31 NEXT_C DEC HL 43 LD E,(HL) 94 INC HL 35 LD (HL),E 115 DEC HL 43 DJNZ NEXT_C 16 249 LD (HL),A 119 DEC HL 43 DEC C 13 JR NZ,NEXT_L 32 242 RET 201 2 Как она работает: В пару регистров HL загружает- ся адрес последнего байта облас- ти атрибутов. Аккумулятор загру- жается значением атрибута для ввода в левую кололнку. В ре- гистр C загружается количество строк для сдвига - он использу- ется как счетчик строк. В ре- гистр B заносится число на 1 меньшее, чем число символов в строке, для использования его в качестве счетчика. HL увеличивается, чтобы ука- зать следующий атрибут. Значе- ние этого атрибута загружается в E-регистр. HL увеличивается, и по адресу HL помещается значение из E-регистра. HL уменьшается снова для указания адреса следу- ющего атрибута. Счетчик в регис- тре B уменьшается, и если он не равен 0, то - возврат назад к NEXT_C. HL теперь указывает на крайнюю левую колонку, и в ячей- ку с адресом HL помещается зна- чение из аккумулятора. HL уменьшается для указания право- го конца следующей строки. Счет- чик строк уменьшается, и если он не равен 0 - возврат назад к NEXT_L. Программа возвращается в BASIC. 5.3. Сдвиг атрибутов вверх. Длина: 21 Количество переменных: 1 Контрольная сумма: 1591 Назначение: Эта программа сдвигает атрибуты всех символов экрана вверх на одно знакоместо. Переменные: Имя: new attr Длина: 1 Ячейка: 23296 Комментарий: Это атрибут, вво- димый в нижнюю строку. Вызов программы: RANDOMIZE USR адрес Контроль ошибок: нет. Комментарий: Эта программа по- лезна для выделения области тек- ста или графики. Для прокручива- ния только 22 верхних строк 224* должно быть изменено на 160. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,22560 33 32 88 LD DE,22528 17 0 88 LD BC,736 1 224* 2 LDIR 237 176 LD A,(23296) 58 0 91 LD B,32 6 32 NEXT_C LD (DE),A 18 INC DE 19 DJNZ NEXT_C 16 252 RET 201 2 Как она работает: В пару регистров HL загружает- ся адрес второй строки атрибу- тов, в DE загружается адрес пер- вой строки и BC загружается чис- лом байтов для перемещения. Количество байтов, определен- ное в регистровой паре BC, копи- руется в ячейки памяти с адре- сом, находящимся в DE из ячеек, начинающихся с адреса в HL, ис- пользуя инструкцию LDIR. Эти ре- зультаты в DE указывают на ниж- нюю строку атрибутов. Аккумуля- тор загружается кодом атрибута для ввода в нижнюю строку. B-ре- гистр загружается числом симво- лов на одной строке - он ис- пользуется как счетчик. По адресу DE помещается значе- ние из аккумулятора, а затем DE увеличивается для указания на следующий байт. Счетчик уменьша- ется, и если он не равен 0, под- программа возвращается в NEXT_C. Затем программа возвращается в BASIC. 5.4. Сдвиг атрибутов вниз. Длина: 21 Количество переменных: 1 Контрольная сумма: 2057 Назначение: Эта программа сдвигает атрибуты всех символов экрана вниз на одно знакоместо. Переменные: Имя: new attr Длина: 1 Ячейка: 23296 Комментарий: Это атрибут, вво- димый в верхнюю строку. Вызов программы: RANDOMIZE USR адрес Контроль ошибок: нет. Комментарий: Эта программа по- лезна для выделения области тек- ста или графики. Для прокручива- ния только 22 верхних строк дол- жны быть изменены: 223* на 159, 255* на 191, 224* на 160. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,23263 33 223* 90 LD DE,23295 17 255* 90 LD BC,736 1 224* 2 LDDR 237 184 LD A,(23296) 58 0 91 LD B,32 6 32 NEXT_C LD (DE),A 18 DEC DE 27 DJNZ NEXT_C 16 252 RET 201 2 Как она работает: В HL загружается адрес послед- него атрибута 23-й строки. В DE загружается адрес последнего ат- рибута 24-й строки. В BC загру- жается число байтов для переме- щения. Затем команда LDDR пере- мещает байты (их количество ука- зано в регистровой паре BC) из адреса в HL по адресу в DE. Эти результаты в DE хранят адрес последнего атрибута первой стро- ки. В аккумулятор загружается зна- чение атрибута для ввода в вер- хнюю строку. В B-регистр загру- жается число байтов в верхней строке - он используется как счетчик. В ячейку с адресом DE помещается значение из аккумуля- тора, и DE уменьшается для ука- зания на следующий байт. Счет- чик уменьшается, и если он не равен 0, подпрограмма возвраща- ется к NEXT_C. Программа затем возвращается в BASIC. 5.5 Сдвиг влево на один символ. Длина: 21 Количество переменных: 0 Контрольная сумма: 1745 Назначение: Эта программа про- кручивает графику экрана на один символ влево. Вызов подпрограммы: RANDOMIZE USR адрес Контроль ошибок: Нет. Комментарий: Эта программа по- лезна при организации экрана в качестве "окна", показывающего в данный момент меньшую часть большой дисплейной области. Это "окно" перемещается, используя подпрограммы сдвига. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,16384 33 0 64 LD D,L 85 LD A,192 62 192 NEXT_L LD B,31 6 31 NEXT_B INC HL 35 LD E,(HL) 94 DEC HL 43 LD (HL),E 115 INC HL 35 DJNZ NEXT_B 16 249 LD (HL),D 114 INC HL 35 DEC A 61 JR NZ,NEXT_L 32 242 RET 201 2 Как она работает: В пару регистров HL загружает- ся адрес дисплейного файла, а D-регистр устанавливается в 0. В аккумулятор загружается число строк на экране. В B-регистр загружается значение на 1 меньшее, чем число символов в строке - оно является числом байтов для копирования. HL увеличивается для указания на следующий адрес, и содержимое из этой ячейки загружается в E-регистр. HL уменьшается, и в ячейку с адресом HL загружается значение из E-регистра. HL уве- личивается для адресации следую- щего байта, и счетчик в B-регис- тре уменьшается. Если он не ра- вен 0, подпрограмма возвращает- ся к NEXT_B. Если регистр B равен 0, это означает, что последний байт строки скопирован и HL указы- вает на правый крайний байт. По этому адресу в регистровой паре HL помещается 0, и HL увеличи- вается, указывая на следующую строку. Счетчик строк - аккуму- лятор - уменьшается, и если он не равен нулю, происходит пере- ход к NEXT_L. Программа возвращается в BASIC. 5.6.Сдвиг вправо на один символ. Длина: 22 Количество переменных: 0 Контрольная сумма: 1976 Назначение: Эта программа прокручивает содержимое дисплей- ного файла на один символ впра- во. Вызов подпрограммы: RANDOMIZE USR адрес Контроль ошибок: Нет. Комментарий: Эта программа по- лезна при организации экрана в качестве "окна", показывающего в данный момент меньшую часть большой дисплейной области. Это "окно" перемещается, используя подпрограммы сдвига. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,22527 33 255 87 LD D,0 22 0 LD A,192 62 192 NEXT_L LD B,31 6 31 NEXT_B DEC HL 43 LD E,(HL) 94 INC HL 35 LD (HL),E 115 DEC HL 43 DJNZ NEXT_B 16 249 LD (HL),D 114 DEC HL 35 DEC A 61 JR NZ,NEXT_L 32 242 RET 201 2 Как она работает: В пару регистров HL загружает- ся адрес последнего байта дис- плейного файла, а D-регистр ус- танавливается в 0. В аккумуля- тор загружается число строк на экране. В B-регистр загружается значение на 1 меньшее, чем чис- ло символов в строке - он ис- пользуется как счетчик. HL уменьшается, указывая на следующий байт, и его значение загружается в E-регистр. HL за- тем увеличивается, и в ячейку с адресом HL загружается значение E-регистра. HL уменьшается, ука- зывая на следующий байт, и счет- чик (B-регистр) уменьшается. Если он не равен 0, подпрограм- ма возвращается в NEXT_B. Если регистр B равен 0, это означает, что HL указывает на крайний левый байт строки. За- тем по адресу в регистровой паре HL помещается 0, и HL уменьшает- ся, указывая на следующую стро- ку. Счетчик строк (аккумулятор) уменьшается и, если он не равен 0, происходит переход к NEXT_L. Программа возвращается в BASIC. 5.7. Сдвиг вверх на один символ. Длина: 68 Количество переменных: 0 Контрольная сумма: 6328 Назначение: Программа сдвигает содержимое дисплейного файла вверх на восемь пикселей. Вызов программы: RANDOMIZE USR адрес Контроль ошибок: нет. Комментарий: нет. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,16384 33 0 64 LD DE,16416 17 32 64 SAVE PUSH HL 229 PUSH DE 213 LD C,23 14 23 NEXT_L LD B,32 6 32 COPY_B LD A,(DE) 26 LD (HL),A 119 LD A,C 121 AND 7 230 7 CP 1 254 1 JR NZ,NEXT_B 32 2 SUB A 151 LD (DE),A 18 NEXT_B INC HL 35 INC DE 19 DJNZ COPY_B 16 241 DEC C 13 JR Z,REST 40 19 LD A,C 121 AND 7 230 7 CP 0 254 0 JR Z,N_BLOCK 40 22 CP 7 254 7 JR NZ,NEXT_L 32 225 PUSH DE 213 LD DE,1792 17 0 7 ADD HL,DE 25 POP DE 209 JR NEXT_L 24 217 REST POP DE 209 POP HL 225 INC D 20 INC H 36 LD A,H 124 CP 72 254 72 JR NZ,SAVE 32 204 RET 201 N_BLOCK PUSH HL 229 LD HL,1792 33 0 ADD HL,DE 25 EX DE,HL 235 POP HL 225 JR NEXT_L 24 198 2 Как она работает: В пару регистров HL загружает- ся адрес начала дисплейного фай- ла, а в DE загружается адрес байта через восемь линий вниз. HL и DE сохраняются в стеке. В C-регистр загружается число на 1 меньшее, чем число строк на эк- ране. В B-регистр загружается количество байтов на одной ли- нии дисплея - он используется как счетчик. В аккумулятор загружается байт, адресованный DE, и это значение загружается в ячейку по адресу HL. В аккумулятор загру- жается содержимое C-регистра и, если оно равно 1, 9 или 17, то в ячейку по адресу DE помещается 0. HL и DE увеличиваются, указы- вая на следующий байт. Счетчик в B-регистре уменьшается, и если он не равен 0, происходит пере- ход к 'COPY_B'. Счетчик строк в регистре C за- тем уменьшается. Если он равен 0, происходит переход к 'RESTORE'. Если C содержит 8 или 16, то происходит переход к 'N_BLOCK'. Если C не содержит 7 или 15, подпрограмма переходит к 'NEXT_L'. Затем 1792 прибавляет- ся к HL - теперь HL указывает на следующий блок экрана. Подпрог- рамма переходит к 'NEXT_L'. В процедуре 'REST' DE и HL бе- рутся из стека и 256 прибавляет- ся к каждому их них. Т.о., DE и HL указывают на строку, позиция которой ниже, чем та, что была в предыдущем цикле. Если HL содер- жит значение 18432, подпрограм- ма возвращается в BASIC, иначе происходит переход к процедуре 'SAVE'. В процедуре 'N_BLOCK' 1972 прибавляется к DE - таким образом DE указывает на следую- щий блок экрана. Подпрограмма затем возвращается к 'NEXT_L'. По окончании работы происходит возврат в BASIC. 5.8. Сдвиг вниз на один символ. Длина: 73 Количество переменных: 0 Контрольная сумма: 7987 Назначение: эта программа сдвигает содержимое дисплейного файла вниз на восемь пикселей. Вызов программы: RANDOMIZE USR адрес Контроль ошибок: нет. Комментарий: нет. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,22527 33 255 87 LD DE,22495 17 223 87 SAVE PUSH HL 229 PUSH DE 213 LD C,23 14 23 NEXT_L LD B,32 6 32 CORY_B LD A,(DE) 26 LD (HL),A 119 LD A,C 121 AND 7 230 7 CP 1 254 1 JR NZ,NEXT_B 32 2 SUB A 151 LD (DE),A 18 NEXT_B DEC HL 43 DEC DE 27 DJNZ COPY_B 16 241 DEC C 13 JR Z,REST 40 21 LD A,C 121 AND 7 230 7 CP 0 254 0 JR Z,N_BLOCK 40 24 CP 7 254 7 JR NZ,NEXT_L 32 225 PUSH DE 213 LD DE,1792 17 0 7 AND A 167 SBC HL,DE 237 82 POP DE 209 JR NEXT_L 24 215 REST POP DE 209 POP HL 225 DEC D 21 DEC H 37 LD A,H 124 CP 79 254 79 RET Z 200 JR SAVE 24 201 N_BLOCK PUSH HL 229 LD HL,1792 33 0 7 EX DE,HL 235 AND A 167 SBC HL,DE 237 82 EX DE,HL 235 POP HL 225 JR NEXT_L 24 193 2 Как она работает: В пару регистров HL загружает- ся адрес последнего байта дис- плейного файла, а в DE загру- жается адрес байта, соответ- ствующего изображению, отстояще- му на восемь линий вверх. HL и DE сохраняются на стеке. В C-ре- гистр загружается число на 1 меньшее, чем число строк на эк- ране. Затем в B-регистр загру- жается количество байтов на од- ной линии дисплея - он ис- пользуется как счетчик. В аккумулятор загружается байт с адресом DE, и это значение пе- ресылается в ячейку по адресу HL. В аккумулятор загружается (для проверки) содержимое регистра C и, если оно равно 1, 9 или 17, то в ячейку по адресу DE поме- щается 0. HL и DE уменьшается на единицу, указывая на следующий байт дисплея. Счетчик байтов в регистре B уменьшается и, если он не равен 0, происходит пере- ход к 'COPY_B'. Далее уменьшается счетчик строк в регистре 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' 1972 вы- читается из DE, т.е. после этого DE указывает на следующий блок экрана. Подпрограмма затем пере- ходит к 'NEXT_L'. 5.9. Сдвиг влево на один пиксел. Длина: 17 Количество переменных: 0 Контрольная сумма: 1828 Назначение: сдвиг содержимого дисплейного файла на один пиксел влево. Вызов программы: RANDOMIZE USR адрес Контроль ошибок: нет. Комментарий: эта программа осуществляет более плавное пере- мещение, чем сдвиг влево на один символ, но требуется вызывать ее восемь раз, чтобы переместить дисплей на один полный символ. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,22527 33 255 87 LD C,192 14 192 NEXT_L LD B,32 6 32 OR A 183 NEXT_B RL (HL) 203 22 DEC HL 43 DJNZ NEXT_B 16 251 DEC C 13 JR NZ,NEXT_L 32 245 RET 201 2 Как она работает: В пару регистров HL загружает- ся адрес последнего байта дис- плейного файла, а в регистр C загружается количество линий в дисплейном файле (он использует- ся как счетчик линий). В ре- гистр B загружается количество байтов на одной линии (он ис- пользуется как счетчик байтов). Флаг переноса устанавливается в 0. Байт, адресованный HL, сдви- гается на один бит влево, бит переноса копируется в крайний правый бит, а крайний левый бит копируется во флаг переноса. Па- ра регистров HL уменьшается для указания на следующий байт и счетчик (B-регистр) уменьшается. Если он не равен 0, подпрограм- ма осуществляет переход к NEXT_B, иначе уменьшается коли- чество обрабатываемых линий и, если оно не равно 0, подпрограм- ма возвращается к процедуре NEXT_L. По окончании работы программа возвращается в BASIC. 5.10. Сдвиг вправо на один пик- сел. Длина: 17 Количество переменных: 0 Контрольная сумма: 1550 Назначение: сдвиг содержимого дисплейного файла на один пиксел вправо. Вызов подпрограммы: RANDOMIZE USR адрес Контроль ошибок: нет. Комментарий: эта программа осуществляет более плавное пере- мещение, чем сдвиг вправо на один символ, но требуется восемь раз вызывать эту программу, что- бы переместить дисплей на один полный символ. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,16384 33 0 64 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 2 Как она работает: В пару регистров HL загружает- ся адрес дисплейного файла, а в C-регистр загружается количес- тво линий на экране (он ис- пользуется как счетчик линий). В регистр B загружается количес- тво байтов на одной линии (он используется как счетчик байтов). Флаг переноса устанав- ливается в 0. Байт по адресу HL сдвигается на один бит вправо, бит переноса копируется в край- ний левый бит, а крайний правый бит копируется во флаг переноса. Пара регистров HL увеличивается, указывая на следующий байт и счетчик (B-регистр) уменьшается. Если он не равен 0, подпрограм- ма осуществляет переход к NEXT_B, иначе уменьшается коли- чество обрабатываемых линий и, если оно не равно 0, подпрограм- ма возвращается к NEXT_L. Закончив работу, процедура возвращается в BASIC. 5.11.Сдвиг вверх на один пиксел. Длина: 91 Количество переменных: 0 Контрольная сумма: 9228 Назначение: сдвиг содержимого дисплейного файла вверх на один пиксел. Вызов программы: RANDOMIZE USR адрес Контроль ошибок: нет. Комментарий: нет. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,16384 33 0 64 LD DE,16640 17 0 65 LD C,192 14 192 NEXT_L LD B,32 6 32 CORY_B 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 NEXT_B INC DE 19 INC HL 35 DJNZ COPY_B 16 243 PUSH DE 213 LD DE,224 17 224 0 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 7 AND A 167 SBC HL,DE 237 82 POP DE 209 JR N_BLOCK 24 14 SUBTR CP 1 254 1 JR NZ,N_BLOCK 32 10 PUSH HL 229 EX DE,HL 235 LD DE,2016 17 224 7 AND A 167 SBC HL,DE 237 82 EX DE,HL 235 POP HL 225 N_BLOCK 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 ADD CP 1 254 1 JR NZ,NEXT_L 32 183 LD A,7 62 7 ADD A,7 130 LD D,A 87 LD A,C 121 CP 1 254 1 JR NZ,NEXT_L 32 174 RET 201 2 Как она работает: В пару регистров HL загружает- ся адрес дисплейного файла, а в DE адрес первого байта второй строки дисплея. В регистр C заг- ружается число линий на экране. В регистр B загружается количес- тво байтов на одной строке - он используется как счетчик. В аккумулятор загружается байт с адресом в DE, и это значение передается в ячейку по адресу HL. В аккумулятор заносится со- держимое регистра C. Если оно равно 2, то DE указывает на ниж- нюю строку экрана и по этому ад- ресу записывается 0. HL и DE увеличиваются, чтобы указать на следующий байт. Счетчик в регис- тре B уменьшается и, если он не равен 0, происходит переход к COPY_B. 224 добавляется к регистровым парам HL и DE, чтобы они указы- вали на следующую строку экрана. Затем уменьшается регистр C, счетчик линий. Если содержимое регистра C не кратно 8, происхо- дит переход к SUBTR, иначе 2016 вычитается из HL и происходит переход к N_BLOCK. Теперь HL указывает на следующие 8 линий. В процедуре SUBTR, если значе- ние (C-1) не кратно 8, происхо- дит переход к N_BLOCK, иначе 2016 вычитается из DE, т.е. те- перь DE указывает на следующие 8 линий. В процедуре N_BLOCK, ес- ли значение C-регистра кратно 64, 1792 добавляется к HL и де- лается переход к NEXT_LINE - те- перь HL указывает на следующий блок из 64 линий. В процедуре ADD, если значение (C-1) не кратно 64, 1792 добавляется к DE, чтобы пара DE указывала на следующий блок 64 линий. Если C-регистр не содержит 1, то программа возвращается к N_LINE, иначе возврат в BASIC. 5.12. Сдвиг вниз на один пиксел. Длина: 90 Количество переменных: 0 Контрольная сумма: 9862 Назначение: сдвиг содержимого дисплейного файла вниз на один пиксел. Вызов программы: RANDOMIZE USR адрес Контроль ошибок: нет. Комментарий: нет. ЛИСТИНГ МАШИННЫХ КОДОВ МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА 147. LD HL,22527 33 255 87 LD DE,22271 17 255 86 LD C,192 14 192 NEXT_L LD B,32 6 32 CORY_B 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 NEXT_B DEC DE 27 DEC HL 43 DJNZ COPY_B 16 243 PUSH DE 213 LD DE,224 17 224 0 ADD A 167 SBC HL,DE 237 82 EX (SP),HL 227 AND A 167 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 7 ADD HL,DE 25 POP DE 209 JR N_BLOCK 24 11 ADD CP 1 254 1 JR NZ,N_BLOCK 32 7 PUSH HL 229 LD HL,2016 33 224 7 ADD HL,DE 25 EX DE,HL 235 POP HL 225 N_BLOCK LD A,C 121 AND 63 230 63 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 SUBTR 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 2 Как она работает: В пару регистров HL загружает- ся адрес последнего байта дис- плейного файла, а в пару регис- тров DE загружается адрес байта линии, которая находится непос- редственно над этим байтом. В регистр C загружается число ли- ний экрана. В регистр B загру- жается количество байтов на од- ной строке дисплея - он ис- пользуется как счетчик. В аккумулятор загружается байт из ячейки с адресом в DE, и это значение загружается в ячейку по адресу HL. В аккумулятор загру- жается содержимое регистра C. Если оно равно 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, если значение (C-1) не кратно 64, из DE вычитается 1792 - в итоге DE указывает на следующий блок из 64 линий. Если C-регистр не содержит 1, то подпрограмма возвращается к NEXT_LINE, иначе в BASIC.