ПРИЛОЖЕНИЕ G
□ Подпрограмма калькулятора
Чтобы помочь вам понять работу калькулятора, научится им
пользоваться и поэкспериментировать, я привожу следующие про-
граммы.
Первая программа - демонстрационная.
ЕХХ ; Вы должны всегда сохранять H'L' для ; правильного
возврата
PUSH HL
ЕХХ
CALL PRSTK ; напечатаем начало и конец стека
LD ВС,Х ; первое число
PUSH ВС ; сохраним его
CALL 2D2Bh ; поместим на стек X
POP ВС ; восстановим X
CALL 2D2Bh ; вновь поместим X на стек
CALL 2DE3h ; напечатаем X
LD 2,20h
RST 10h ; напечатаем пробел
LD HL,NUMBER ; базовый адрес числа в ASCII форме
CALL STKNUM ; поместим число на стек (это будет У)
RST 28h ; вызовем калькулятор
DEFB 31 h ; продублируем Y
DEFB 38h ; выйдем из режима калькулятора
CALL 2DE3h ; напечатаем Y
RST 28h ; войдем в режим калькулятора
Здесь вы можете разместить набор определенных байтов
(DEFB), чтобы поэкспериментировать с калькулятором.
DEFB 38h ; конец режима калькулятора
CALL 2DE3h ; печать результата
CALL PRSTK ; печать "STKBOT" и "STKEND" для
; проверки, находился ли стек в балансе
ЕХХ ; восстановим H'L1
POP HL
ЕХХ
RET
NUMBER DEFM "1234.567"
DEFB 13 ; здесь всегда должно быть DEFB 13, для
; сигнализации об окончании числа.
Нижеприведенная программа напечатает адреса начала и
конца стека калькулятора:
PRSTK LD ВС,(23651); это STKBOT
CALL 2D28h ; разместим ее на стек
LD А,МВ"
RST 10h
LD А," "
RST 10h
CALL 2DE3h ; напечатаем STKBOT
LD A,"
RST 10h
LD A/'T"
RST 10h
LD A," "
RST 10h
LD ВС,(23653); это STKEND
CALL 2D2Bh
CALL 2DE3h ; напечатаем STREND
LD A,0Dh
RST 10h
RET
А эта программа разместит на стеке число в ASCII форме. При ее
использовании в паре "HL" разместите начальный адрес числа, поме-
щаемого на стек.
STKNUM LD DE,(23645); это CHADD
PUSH DE ; сохраним
LD (23645),HL ; поместим в CH ADD начало числа
LD A,(HL); поместим первый символ в «А»
CALL 2C9Bh ; поместим число на стек
POP DE ; восстановим CH ADD
LD (23645),DE
RET
Драйвы интерфейсов "MOREX% и "KEMPSTON"
При входе в эту подпрограмму ASCII код, выводимый на линию
"CENTRONICS", должен содержаться в регистре «А». Расширенные
коды не выводятся; если это требуется см. «Расширение символов для
вывода» глава 2.
□ Программа вывода "CENTRONICS" интерфейса
"MOREX"
PUSH AF ; сохраним код символа
BUSY IN A,(OFBh); считаем линию занятости принтера
AND 1 ; проверим бит О
JR NZ,BUSY ; если не сброшен - принтер занят
POP AF ; восстановим алмвол
OUT (0FBh),A ; перешлем его
LD А,1 ; стробируем принтер
OUT (7Fh),A
XOR А
OUT (7Fh),A
RET ; конец программы
Программа вывода "CENTRONICS" интерфейса
"KEMPSTON"
PUSH ВС ; сохраним пару регистров "ВС", т.к. они
; используются для ввода/вывода
PUSH AF ; сохраним код символа
LD BC,0E2BFh ; порт занятости
BUSY IN А,(С); считываем линию занятости
RRA ; бит 0 для переноса
JR С,BUSY ; если не сброшен принтер занят
POP AF ; восстановим символ
DEC В ; изменим порт на 02BFh
DEC В
OUT (С),А ; перешлем символ
LD A,00Eh ; стробируем данные для пересылки
LD B,0E3h ; изменим порт на E3BFh, стробируем порт
OUT (С),А
INC А
OUT (С),А
POP ВС ; восстановим "ВС"
RET ; конец
Подпрограмма передвижения спрайта с помощью прерыва-
ний.
; Демонстрационная программа для спрайтов, см. главу 6
ORG 51455
ENT 51455
; 51455 содержит указатель прерываний
DEFW 51500
SETUP LD A,200
LD I,A
LD ВС,(COORD)
CALL PLOT
IM 2
RET
; это важная программа, делающая указатель таким, чтобы
; программа прерываний стартовала с нужного адреса (здесь
51500)
1
ORG 51500
; сохраним все используемые регистры
PUSH HL
PUSH ВС
PUSH DE
PUSH AF
; сохраним TV флаг, т.к. он может быть изменен
LD А,(23612)
PUSH AF
1
; сохраним CO ORDS, т.к. они будут изменены, перед воз-
вратом их
; нужно восстановить
1
LD HL,(23677)
PUSH HL
LD ВС,(COORD); координаты спрайта
PUSH ВС ; сохраним их
; вызываем программу вывода спрайта. По окончании каж-
дого вывода
; это сотрет предыдущую позицию
CALL PLOT
POF* ВС ; восстановим координаты спрайта
>
; "L" используется как флаговый регистр для определения
; направления движения спрайта
; бит 0 установлен - вверх, сброшен - вниз
; бит 1 установлен - влево, сброшен - вправо
LD HL(FLAG)
BIT 0,L
JR Z,UP
DOWN DEC 8 ; передвижение спрайта вниз на пиксель
JR NZ,LEFT ; если флаг 0 - дошли до низа экрана и
; направление меняется
RES 0,L
JR LEFT
UP INC В ; один пиксель вверх
LD А,В ; дошли ли до верха экрана?
CP 174
JR NZ,LEFT
SET 0,L ; изменили направление
LEFT BIT 1,L ; те же проверки для влево/вправо
JRZ,RIGHT
DEC С
JRNZ,CPLOT
RES 1,L
JRCPLOT
RIGHT INC С
LD А,С
CP 254
JR NZ,CPLOT
SET 1 ,L
; новые координаты для спрайта записаны
С PLOT LD (COORD),ВС ; теперь сохраним флаги
LD (FLAG),HL
i
CALL PLOT ; вывод новой позиции спрайта
/
1
; вывод закончен, восстановим начальные значения систем-
ных
; переменных
у
NRET POP HL
LD (23677),HL
POP AF
LD (23612),A
«
1
; восстановим регистры
POP AF
POP DE
POP ВС
POP HL
; сканируем клавиатуру, т.к. этого не делалось потому, что
; программа прерываний была перемещена в ОЗУ
RST #38
RETI
COORD DEFW О
FLAG DEFW О
; "D" используется как счетчик, т.к. «В» уже использован
PLOT LD D,4
i
; запомним координаты, т.к. они будут испорчены програм-
мами ПЗУ
1
PUSH ВС
LOOP LD A,D
PUSH DE ; сохраним счетчик
•
i
; вывод делается четырежды, каждый раз выдавая следую-
щий спрайт
CP 4
JR Z,LOOP4
СРЗ
JR NZ,LOOP1
INC С
LOOP1 CP 2
JR NZ,LOOP2
INC В
LOOP2 CP 1
JR NZ,LOOP4
DEC С
; проверим, какая ПЗУ подключена
LOOP4 LD А,(#14) ; запросим ячейку, отличающуюся в раз-
ных
; ПЗУ
; Устанавливаем вывод на основной экран
RES 0,(IY+2); IY+2 - TV FLAG
PUSH ВС ; сохраним "ВС" для перехода ПЗУ-ПЗУ
CP #D5
JR Z,ROM2 ; подключена ПЗУ 2, поэтому подпрограммы
; основной ПЗУ впрямую вызвать нельзя
; если мы здесь, значит подключена основная ПЗУ и возмо-
жен
; прямой вызов
1
CALL #D4D ; запросим цвета для вывода
SET 0(IY+87); установим "OVER 1" через "Р FLAG"
CALL 8933 ; программа из ПЗУ для вывода пикселя
JR CONT1 ; делаем непрямой переход к запросам 16К
; из 8К
; если мы здесь, то подключена ПЗУ интерфейса
ROM2 RST 16 ; не прямо вызывается 16К ПЗУ
DEFW #D4D
SET 0,(IY+87)
RST 16
CONT1 RES 0,(IY+87); сбросим "OVER 1"
POP ВС ; восстановим последнюю позицию печати
POP DE ; и счетчик
DEC D
JR NZ,LOOP
•
i
POP ВС ; восстановим начальную позицию вывода
LD А,В ; проверим, достигнут ли край
AND А
JR Z,PING ; если да, то выполняем необходимые
; действия
CP 174
JR Z,PING
LD А,С
AND A
JR Z,PING
CP 254
JR Z,PING
RET ; иначе - возврат
1
PING PUSH ВС ; сохраним координаты вывода, чтобы «В»
; можно было использовать как счетчик
LD В,0
PINGL LD А,В ; выдадим тон на динамик
1
OUT (#FE),A ; меняем состояние, чтобы воспроизвести
; тон
DJNZ PINGL
POP ВС
; теперь посмотрим, откуда пришел вызов
LD HL,NRET
LD A,L
POP HL
PUSH HL
XOR L
i
; мы в этой точке, только если возврат не был сделан и
следующая
; программа установит черный цвет бордюра
RET Z
; увеличим значение цвета бордюра, биты 0-2
LD A,(COL)
INC А
LD (COL),А
; зададим цвет бордюра
OUT (#FE),A
RET
COL DEFB 0
□ DEBASE
DEBASE состоит из нескольких отдельных подпрограмм, собран-
ных в грубую, но эффективную систему для работы с базами данных,
есть программы для записи и загрузки как с ленты, так и с МИКРО-
ДРАЙВа. Программа позволяет производить следующие операции:
вводить, печатать, находить, вычеркивать и изменять. Нет ограни-
чений на число отдельных записей и размер каждой записи, за иск-
лючением одного требования: запись должна помещаться на экране
без "Scroll". Может быть найдена любая часть любого текста, курсор
будет помещен в начало найденного набора символов. Запись может
быть изменена, дополнена или сокращена после первого ввода без
уничтожения или изменения любых других частей. После этого ос-
вободившаяся память может быть использована. Программа исполь-
зует 1 байт памяти на символ и 1 байт на запись для маркировки
конца записи; 32 ООО байт свободны для записи и есть место для
дополнительных функций.
; Эта программа печатает все, что начинается с байта с
; активизированным битом 7 до следующего байта с таким
битом 7.
; В ней есть три основные точки входа и два способа
; использования. Если регистр А содержит на входе 255,
регистр
; DE должен содержать адрес первого символа сообщения,
; предваренного байтом с активизированным битом 7. Для
всех
; других значений А напечатается сообщение из таблицы,
идущее в
; ней под заданным номером.
МС1 ORG 62500
PRESS PUSH AF ; эта точка входа устанавливает начало
; печати в левую верхнюю позицию экрана
PUSH DE
LD А,2
CALL #1601 ; подтверждаем, что основной экран
; текущий, иначе позиция печати
; установится в другой экран, а в
; основном экране не изменится
LD ВС,#1821
CALL 3545 ; используем ПЗУ, см. Главу 2
POPDE
POP AF
PRINAT PUSH AF ; эта точка входа сохраняет позицию
; печати и использует основной экран
PUSH DE
LD А.2
CALL #1601
LD A,255 ; задает SCROLL до сообщения "Scroll?"
LD (23692),A ; это системная переменная SCR ST.
LD A, 13 ; перевод каретки в конец строки
RST 16 ; рестарт печати
POP DE
POP AF
PRINT INC A ; этот вход использует текущий поток
DEC DE ; поместим в "DE" начало маркера
JR Z,PRINTP ; если в «А» #FF используем адрес из DE
DEC А
LD DE,MESS-1 ; DE установлен в начало таблицы
; сообщений
PRINTP CALL 3082 ; программа ПЗУ для печати
RET
MESS EQU 1
; Эта программа ищет в памяти строку, начало которой
находится в
; SCHAR. Завершается маркер-байтом, содержащим 255.
Если
; соответствие найдено, то находится начало записи путем
подъема
; вверх до байта с активизированным битом 7, который
печатается
; предыдущей программой.
; Если конец каждой записи промаркирован #8D, то содер-
жимое
; SCHAR будет #FF (ничего не нашли) вместо сообщений
ничего
; напечатано не будет, так как ничего не найдено.
; На выходе регистры ВС будут содержать либо адрес начала
; записи, содержащей строку, либо 0, если строка не была
найдена
МС2 ORG #F450
FINDIT LD HL,SCHAR ; основная точка входа
LD A,(HL)
CP #FF
JR NZ,SEARCH
INC HL
LD (HL),A
DEC HL
LD A,#8D
LD (HL),A
SEARCH PUSH HL
LD HL,30002
LD ВС,34000
POP DE
LOOKMO PUSH DE
LOOKON CPIR ; ищем первый символ, если строка не
; найдена
JR NZ,NOTFIND
DEC HL
LD (LOCFND),HL; сохраним ячейку, где нашли, и отсчитаем
; влево 80
LD (LOCCNT),BC
POP DE
PUSH DE
MAYBE INC HL ; теперь проверяем посимвольно
EX DE,HL
INC HL
LD A,(HL)
CP 255 ; когда найден конец строки - строка
; найдена
JRNZ, FOUND
•
EX DE,HL
CP (HL)
JRZ,MAYBE
LD HL,(LOCFND); если соответствия нет - снова ищем
; первый символ
INC HL
LD A,(SCHAR)
JR LOOKON
FOUND POP HL
LD HL,(LOCFND); сначала проверим, в разрешенной ли
; области делается поиск
BACK DEC HL
LD (MEMPOS),HL
INC HL
PUSH HL
LD DE,(LIMIT)
AND A
SBC HUDE
JR NC,NOTFND ; если нет - отменяем поиск
POP HL
BACKMO DEC HL ; ищем начало входа для печати
BIT 7,(HL)
JRZ,BACKMO
INC HL
PUSH HL
PUSH HL
CALL 5435 ; очистим весь экран
POP DE
LD A,#FF ; программа печати должна использовать
; адрес из DE
CALL PRESS
POP ВС
RET
NOTFND LD A,3 ;печать сообщения 3
CALL PRINAT
POP HL
LD BC,0
RET
•
CONTLK LD HL,SCHAR ; эта точка входа для поиска других
; таких же строк
PUSH HL
LD A,(HL)
LD BC,(LOCCNT)
LD HL,(LOCFND)
INC HL
JP LOOKON
SCHAR DEFS 33
LOCCNT DEFW 0 ; после поиска отсчет влево
LOCFND DEFW 30002 ; ячейка где нашли
MEMPOS DEFW 30001 ; ячейка предваряющая найденную
LIMIT DEFW 62400 ; количество доступной памяти
PMESS EQU #F424 ; программа печати сообщений см. выше
в
; этом же приложении
PRINAT EQU #F423
; При использовании вместе с предыдущей программой вы-
черкивает
;запись
; На выходе регистры ВС содержат количество освободив-
шейся
; памяти
1
МСЗ ORG #F4CB
XREC CALL FINDIT ; используется для поиска начала
; вычеркиваемой записи
XRECON LD А,В
OR С
RET Z ; если не нашли BC=0
PUSH HL
PUSH ВС
LD A,2 ; сообщение 2
CALL PRINAT
CHECKB LD A,127 ; это один из способов сканирования
; нажатия ключей, см. главу 2
IN A,(#FE)
RRA
JR NC,BREAK
LD A, 127
IN A,(#FE)
BIT 3,A
JRZ.NEXTR
LD A,254
IN A,(#FE)
BIT 2,A
JR NZ,CHECKB
POP ВС
POP HL
PUSH ВС
PUSH ВС ; ВС - начало записи
POP HL
LD BC,0
F END BIT 7,(HL)
INC HL
INC ВС ; конец записи должен быть найден
JR Z.F END
POP DE ; теперь все вплоть до LIMIT опускается
; и запись уничтожается
PUSH ВС
PUSH HL
POP ВС
PUSH HL
LD HL,(LIMIT)
AND A
SBC HL,BC
PUSH HL
POP ВС
POP HL
LDIR
POP ВС ; количество добавленной памяти
RET
BREAK POP HL ; очистим стек, скажем о ненахождении
POP ВС
LD ВС,О
RET
NEXTR POP HL ; восстановим старые детали и продолжим
; поиск
POP ВС
CALL CONTLK
JP XRECON
; Эта программа позволяет разместить символ с клавиатуры
в памяти
; и отобразить его на экран.
; Она выполняет перемещение курсора вперед и назад, де-
лает
; вставки и вычеркивание символов
; Есть так же "HELP" и меню.
; Здесь показано как ее использовать вместе с другими
; программами для работы с базами данных, но она приме-
нима и для
; других целей.
; Программа проверяет доступную память и по достижении
предела
; останавливает ввод.
; Я включил вторую программу ввода и внешние программ
для выбора
; функций, чтобы продемонстрировать разные способы вво-
да и некоторые
; проблемы, упомянутые в основном тексте книги.
; Это адрес вызова из БЕЙСИКа.
9
*
МС4 ORG #F51D
USR LD A,#A0 ; сначала проверяется свободная память
LD HL,(LIMIT)
LD DE,(CHPOS)
AND A
SBC HL,DE
JP NC,NOTFUL
LD A,9 ; сообщение 9
CALL PRINAT
JP PMESS4
NOTFUL PUSH HL ; вся память выше последней записи и
ниже
; "LIMIT" очищается и маркируется как
;свободная
POP ВС
PUSH DE
POP HL
INC DE
LD (HL),A
LDIR
INPUTA LD HL,(CHPOS); начало следующей записи
DEC HL
LD A,(HL)
CP #8D
JR Z,ATBEG
INC HL
ATBEG LD (HL),#8D
LD (CUPOS),HL ; маркируется и очищается начало
CALL 3435
CALL OPEN1
LD ВС,#1821 ; позиция печати в нижнем экране
; устанавливается влево - вверх
CALL 3545
LD А,7 ; сообщение 7
CALL PRINT
LD А, 1 ; фирменный знак программы
CALL PRESS
XOR А ; очищается флаг режима редактирования
LD (WFLAG),A
LD ВС,#1621 ; установим строку 2, колонку О
CALL 3545
LD А,""
RST 16
CALL CURSOR
INPUT CALL OPEN1
INP1 CALL #10A8 ; это программа ввода с клавиатуры
JR C,KEYPRE ; перенос активизируется при вводе ключа
RES 3,(IY+2); это TV флаг, см. «Ожидание ввода»
; глава 2
JR INP1
KEYPRE CP 198 ; теперь запрашиваем специальные клави-
ши
JRZ,BACK1
CP 9
JP Z,RIGHT1
CP 12 ; CAPS SHIFT и 0
CP Z,DELETE
CP 197 ; OR
RET Z
CP 205 ; STEP
JP Z,HELP
CP 198
J P Z,AND
CP 195 ; NOT
JP Z,LOOKM
CP 204 ; то
JP Z,LPRINT
LD HL,(CUPOS)
INC HL ; проверяем, достигнут ли конец записи,
; если ввод больше не разрешен
PUSH AF
LD A,(WFLAG)
AND A
JR Z,OKTHEN ; если не в режиме редактора, то это
; свободная память
LD A,(HL)
CP #8D
JP Z,ENDREC
OKTHEN POP AF
CP 226 ; стоп, оканчивающий ввод
JR Z,STOP
LD (HL),A ; код символа помещается в текущую
; ячейку памяти, в следующий раз она
; будет изменена
LD (CUPOS),HL
CP 13
JR NZ,KEYOUT ; при выводе перемещаем курсор
CALL OPEN2
CALL CURSOR
KEYOUT CALL OPEN2
RST 16 ; отображение символов на экран
CALL CURSOR ; перемещаем курсор
JR INPUT ; повторяем для ввода следующего кода
#
1
1
ВАСК1 LD HL,(CUPOS) ; переводит курсор в текущую пози-
ция в
; памяти назад
LDA,(HL)
BIT 7,А
JRNZ,INPUT
CP 13
DEC HL
LD (CUPOS),HL
JR NZ,B_ON
CALL BACK ; но возврат после ввода означает повтор
; печати и изменение режима
JR FINRET
B ON CALL OPEN2
CALL CURSOR
LD А,О
RST 16
CALL CURSOR
JP INPUT ; возврат за следующим символом
•
STOP PUSH HL; если нажали STOP при новом вводе, то
; необходимо маркировать конец записи
DEC HL
ENDIS LD A,(HL); мы всегда ищем начало свободной памяти
; и изменяем указатель
INC HL
CP #А0
JR NZ,ENDIS
DEC HL
LD (CHPOS),HL
POP HL
LD A,(WFLAG)
AND A
INC HL
JR NZ,STOPON
LD (CHPOS),HL
DEC HL
LD A,#8D
LD (HL),A
STOPON CALL 3435 ; очистим экран
XOR A ; очистим флаг режима
LD (WFLAG),A
LD A,4 ; выведем меню
CALL PRESS
MENUIN CALL OPEN1
CALL#15DE ; программа ожидания ввода, глава 2
CP 13
JP Z,USR
OR #20
CP "O"
JR Z,XINPUT
CP "F"
JR Z,FINPUT
CP "C"
JR Z, LOO KM
CP "S"
JR Z,SAVEL
JR MENUIN
XINPUT CALL FINPT ; начало программы вычеркивания
CALLXREC
LD HL,(CHPOS); свободная память увеличивается
; изменением указателя памяти на
; количество вычеркнутых байтов
AND А
SBC HL,BC
LD (CHPOS)tHL
JP PMESS4
FINPUT CALL FINPT ; поиск начала записи
CALL FINDIT
FINRET LD А,В ; не нашли - выходим в меню
OR С
JPZ,PMESS4
DEC ВС
LD (CUPOS)tHL ; иначе - режим редактора, курсор под
; началом найденного
LD HL,(MEMPOS)
AND А
SBC HL,BC
LD (CURSP),HL
LD A,1
LD (WFLAG),A
CALL OPEN1
LD ВС,#1821
CALL 3435
LD A,8
CALL PRINT
LD A,7
CALL PRINT
CALL OPEN2
LD BC,#1821
CALL 3545
LD A,13
RST 16
CALL CURSOR
LD BC,(CURSP)
R1M0RE LD А,В
OR С
JPZ,INPUT
PUSH ВС
CALL RIGHTS
POP ВС
DEC ВС
JR RIMORE
•
1
1
FINPT CALL 3435; похоже на предыдущую программу ввода,
; но не допускает вычеркиваний и
; ограничивает ввод, останавливаясь по
; достижении "INLIM"
LD А,5
CALL PRESS
LD A,62
RST 16
LD HL,SCHAR+32
LD (IN_LIM),HL
LD HL,SCHAR
i
INPUTF PUSH HL ; подпрограмма ввода
CALL OPEN1
CALL #15DE
POP HD
CP 13 ; прекращается нажатием ENTER
JR Z,SETFIN
CP 32
JRZ,INPUTF
LD (HL),A
INC HL
PUSH HL
CALL OPEN2
RST 16
POP HL
EX DE,HL
LD HL,(IN_LIM)
AND А
SBCHL.DE
EX DE,HL
JR NZ.INPUTF
SETFIN LD (HL),255
RET
1
LOOKM CALL CONTLK ; ищем, есть ли еще такие строки
JP FINRET
»
»
PMESS4 LD В,3 ; очистим нижние три строки экрана,
; смотри главу 2
CALL 3652
LD А,4 ; меню
CALL PR I NAT
JPMENUIN
•
»
; OVER1 и OVER2 воспроизводят команды БЕЙСИКа, печа-
тая
; управляющие символы
OVER1 PUSH AF
PUSH HL
LD A,21
RST 16
LD A,1
RST 16
POP HL
POP AF
RET
OVERO PUSH AF
PUSH HL
LD A,21
RST 16
LD A,0
RST 16
POP HL
POP AF
RET
CURSOR PUSH AF; печать курсора и передвижение позиции
; печати назад на 17 позиций
CALL OVER1
LD А,95
RST 16
LD А,8
RST 16
CALL OVERO
POP AF
RET
RIGHT1 CALL RIGHTS
JP INPUT
RIGHTS CALL OPEN2 ; передвижение позиции курсора на 1
; вправо изменяя указатель памяти для
; нового символа
LD HL,(CUPOS)
INC HL
LD A,(HL))
BIT 7,A
RET NZ
CP 127
RET Z
CP 13
JR Z.ONRITE
CP 32
RET С
ONRITE LD (CUPOS) ,HL
CALL CURSOR
CP 13
JR Z.RITEON
CALLOVER1
LD A, 32
RITEON RST 16
CALL CURSOR
RET
«
)
« *
)
ENOREC PUSH HL; при попытке ввода после окончания
; записи выдается предупреждающее
; мигающее сообщение, низ экрана
; очищается
LD В,3
CALL 3652
LD А,6
CALL PRESS
EI; если они были отключены
LD В,50 ; как всеща 1 секундная пауза
WAIT1 HALT
DJNZWAIT1
POP HL
POP AF
REENTR LD HL,LOCFND
DEC (HL)
DEC HL
INC (HL)
JP LOOKM
•
*
s
>
DELETE LD HL, (CUPOS) ; работает как вычеркивание записи,
но
; для одного символа
INC HL
LD A, (HL)
BIT 7,А
JP NZ,INPUT
PUSH HL
PUSH HL
LDHL, (LIMIT)
POP DE
AND A
SBC HL,DE
PUSH HL
POP ВС
POP DE
JP C,INPUT
JP Z,INPUT
PUSH DE
POP HL
INC HL
LDIR
LD HL, (CHPOS)
DEC HL
LD (CHPOS),HL
LD HL, (CUPOS)
INC HL
CALL BACK
JP FINRET
•
J
♦
)
AND LD HL, (CUPOS) ; то же самое, но наоборот
INC HL
PUSH HL
LD HL, (LIMIT)
POP DE
AND A
SBC HL,DE
PUSH HL
POP ВС
PUSH DE
LD DE, (LIMIT)
PUSH DE
POP HL
DEC HL
LDDR
LD HL, (CHPOS)
INC HL
LD (CHPOS) ,HL
POP HL
LD A,32
LD (HL),A
CALL BACK
JP FINRET
•
J
♦
)
LPRINT LD HL, (CUPOS) ; использует поток 3 как поток 2 для
; экрана, если подключен интерфейс
; воспринимающий LPRINT
INC HL
CALL BACK
PUSH ВС
LD А,3
CALL #1601
POP DE
PUSH DE
DEC DE
XOR A
CALL PRINTP
POP ВС
JP FINRET
♦
•HELP CALL 3435
LD A, 10 ; страница HELP
CALL PRESS
WAITE LD A,OOF
IN A, (OFE)
AND 1
JR NZ,WAITE
LD HL, (CUPOS)
LD (LOCFND),HL
INC HL
LD A, (HL)
LD HL,SCHAR
LD (HL),A
INC HL
LD (HL) ,0FF
JP REENTR
; начало программ записи и загрузки
; Сначала вычисляется длина записи, включая оглавление и мар-
кер
; окончания, затем байты длины для повторного ввода после
; загрузки
МС5 ORG 0F7F1
SAVEL LD HL, (CHPOS) ; сначала конец записей помещается в
; начальную область для записи или
; загрузки
LD (29998),HL
LD DE,29998
AND А
SBC HL,DE
INC HL
INC HL
PUSH HL
LD A,11
CALL PRESS
LD B,25 ; 25 прерываний за 1/2 секунды если они
; были отключены
EI
♦
♦
)
; Это некорректно делать, но продемонстрируем использование
HALT
; для хронометрирования
♦
)
HOLDIT HALT ; убедимся, что S получено не из
; основного меню, теперь сканируем
; клавиатуру
DJNZ HOLDIT
♦
»
*
SOLDEC LD A,#DF
IN A, (#FE)
AND 2
JP Z,LOAD
LD A,#FD
; IN A, (#FE)
AND 2
JR NZ,SOLDEC
; программа выбора: лента или м/драйв
ORG #F81C
SAVE POP ВС
CALL M_OR_T ; если нажато M, делается возврат с
; установленным переносом и заголовком
♦
JR С, MS AVE
)
; для записи заголовка и основного блока данных на ленту.
; Заголовок особый. См. команды "SAVE" и "LOAD", глава 2.
♦
»
TSAVE PUSH ВС ; ВС=длина основного блока IX всегда
; установлен в начало
LD DE,13 ; заголовок из 13 байтов
XOR А ; А - сигнальный заголовок
CALL 1222 ; программа ПЗУ, смотри главу 2 для
; записи заголовка
POP DE ; восстановим длину основного блока
LD IX,29998 ; IX указывает адрес, с которого начнем
; запись из сигнального основного блока
LD A,OFF
CALL 1222 ; используется программа ПЗУ, возврат с
; вновь отключенными прерываниями
EI
JP LORET
; ниже приведенная программа отключает 16К ПЗУ
;см. главу 3
ORG #FB38
RSWAP LD HL,ROMOUNT
LD (23789) ,HL ; программа ПЗУ использует обходной код
; 32, поэтому установите возврат к этой
; программе
ЕХХ
LD(HLSAV),HL
ЕХХ
LD (BCSAV) ,ВС
RST 8 ; используем обходной код
DEFB #32
ROMOUNT POP HL ; два адреса программы должны быть
; перемещены и возврат из этой программы
; это "ERR SP", см. главу 4
POP HL
POP DE
LD HL, (23613)
PUSH HL ; сохраним позицию возврата по ошибке на
; стеке для дальнейшей работы
LD HL,MSLRET
PUSH HL ; поместим на стек новый адрес возврата
; по ошибке, укажем в "ERR SP" для
; восстановления адреса возврата
LD (23613),SP
PUSH DE
RET
; программа записи на МИКРОДРАЙВ
♦ ♦
ORG #FB5A
MS AVE CALL RSWAP
CALL MHEAD ; зададим заголовок и системные
; переменные
CALL VARSET
SET 5, (IY+124) ; FLAGG 3 - запись
CALL #1E7F ; на самом деле вызов не нужен, т.к.
; возврат через ошибку 16К
MSLRET POP HL ; восстановим "ERR SP"
LD (23613) ,HL; "ERR SP"
EI
EXX
LD HL, (HLSAV) ; регистры HL
ЕХХ ; отметьте, что 16K ПЗУ подключена,
; потому что возврат через ошибку в
; БЕЙСИКе 16К ПЗУ
JP LORET
ORG #F877
VARSET LD HL,23769 ; подробно описано в главе 3
LD (HL) ,"М"
LD HL,10
LD (23770),HL
LD HL,SCHAR+1
LD (23772),HL
LD HL, 1
LD (23766),HL
RET
; Программа загрузки с МИКРОДРАЙВа, детально изложена в
Главе 3
♦
♦
MLOAD LD BC,0 ; детали заголовка нужно использовать,
; т.к. они неизвестны
CALL RSWAP
CALL MHEAD
CALL VARSET
SET 4, (IY+124) ; сигнализирует о загрузке
CALL #BAF ; вызов программы загрузки
JP MSLRET ; реально это нежелательно
; зададим микродрайверный заголовок, см. Главу 3
MHEAD LD HL,23782
LD (HL),3
INC HL
LD DE,(BCSAV)
LD (HL),E
INC HL
LD (HL),D
INC HL
LD DE,29998
LD (HL),E
INC HL
LD (HL),D
INC HL
LD (HL) ,#80
RET
; определяем куда производить загрузку - на ленту или МИКРО-
ДРАЙВ
; загрузка с ленты смотри Главу 2
LOAD POP ВС
CALL M_OR_T
JR С,MLOAD
TLOAD XOR A ; заголовок
SCF ; загрузка
LD DE,13
INC D
EXAF,A'F'
DEC D
DI
LD IX,SCHAR+15
CALL #562
EI
CALL 8020
RET NC ; нажат BREAK
TESTHE LD IX,SCHAR ; проверка имени заголовка
LD HL,SCHAR+15
LD В, 11
TESTLP LD A, (HL)
CP (1Х-Ю0)
JR NZ,TLOAD ; несоответствие - заголовок неверен
INC IX ; соответствие - выполняем загрузку
INC HL
DJNZ TESTLP
LD IX,29998
LD E,(HL)
INC HL
LD D,(HL)
SCF ; загрузка
LD A,#FF ; основной блок данных
INC D
EX AF,A'F'
DEC D
DI
CALL #562
EI
CALL 8020
RET NC ; нажат BREAK
JP LORET ; загружено, повторный ввод
•
>
>
; программа запрашивает имя файла и что используется - лента
или
; МИКРОДРАЙВ
«
>
M_OR_T CALL SAVET
PUSH ВС
PUSH IX
LD A,12
CALL PRINAT
MIORTA LD A,#7F
IN A,(#FE)
AND 4
SCF
JR Z,MOTFIN
LD A,#FB
IN A,(#FE)
AND 16
JR NZ,MIORTA
MOTFIN POP IX
POP ВС
RET
; берет параметры длины из начала загруженной памяти или то,
что
; туда было помещено при записи
LORET LD HL, (29998)
LD (CHPOS),HL
JP USR
; программа генерирует заголовок в области памяти SCHAR
SAVET LD HL,SCHAR
PUSH ВС
PUSH HL
PUSH HL
LD (HL),3
PUSH ВС
LD В ДО
LD A,32
SETHED INC HL
LD (HL),A
DJNZ SETHED
PUSH HL
LD (IN_LIM),HL
POP HL
POP ВС
INC HL
LD (HL),C
INC HL
LD (HL),B
CALL 3435
LD A, 13
CALL PRESS
POP HL
INC HL
CALL INPUTF
LD (HL),32
POP IX
POP ВС
RET
•
>
BCSAV DEFW 0
CUPOS DEFW 0
CHPOS DEFW 30001
HLSAV DEFW 0
IN_LIM DEFW 0
LIMIT DEFW 62000
LOCCNT DEFW 0
LOCFND DEFW 0
WFLAG DEFB 0
MEMPOS DEFW 30001
CURSP DEFW #1821
SCHAR DEFS 33
MESSM1 DEFB #80
MESS DEFB #80
MESS1 DEFM "DEBASE COPYRIGHTE SGK 1984"
DEFB #8D
MESS2 DEFW #110
DEFM "PRESS SPACE TO ABORT"
DEFB 13
DEFM "X ТО ERASE OR N.TO NEXT RECORD"
DEFW #10
DEFB #8D
MESS3 DEFW #210
DEFM "NOT FOUND"
DEFW #10
DEFB #8D
MESS4 DEFW #110
DEFM " MENU"
DEFW #0D0D
DEFM "PRESS"
DEFW #0D0D
DEFM "F TO FIND"
DEFW #0D0D
DEFM "E TO ERASE"
DEFW #0D0D
DEFM "C TO CONTINUE SEARCH" DEFW #0D0D
DEFM "ENTER TO MAKE ANOTHER ENTRY"
DEFW #0D0D
DEFM "S TO SAVE OR LOAD"
DEFW #10
DEFB #8D
MESS5 DEFM "ENTER DETAILS TO FIND"
DEFB #8 D
MESS6 DEFW #210
DEFB 13
DEFM "END OF RECORD, NO MORE INPUT"
DEFB 13
DEFM "POSSIBLE"
DEFB #8D
MESS7 DEFW #110
DEFM "PRESS"
DEFW #210
DEFM "STOP"
DEFW #110
DEFM "FOR MENU"
DEFW #210
DEFB 2
DEFM "TO"
DEFW #110
DEFM "ТО PRINTOR"
DEFW #210
DEFM "STEP"
DEFW #110
DEFM "FOR HELP"
DEFB #A0
MESS8 DEFW #310
DEFM "YOU ARE IN EDIT MODE"
MC9 DEFB #8D
MESS9 DEFW #210
DEFM "YOU JUST RUN OUT OF MEMORY"
DEFB 13
DEFM "SAVE THE RECORDS OR SOMETHING"
DEFW #10
DEFB #8D
MESS10 DEFM "WHEN YOU ARE IN EDIT MODE"
DEFB 13
DEFM "PRESSING"
DEFW #210
DEFM "NOT"
DEFW #010
DEFM "WILL FIND THE NEXT OCCURENCE OF THE LAST"
DEFM " STRING THAT WAS SOUGHT"
DEFW #0D0D
DEFW #210
DEFM "AND"
DEFW #010
DEFM "WILL INSERT A CHARACTER"
DEFB 13
DEFM "AT THE CURRENT CURSOR POSITION"
DEFB #0D0D
DEFM "DELETE WILL REMOVE THE CHARACTER"
DEFB 13
DEFM "AT THE CURRENT CURSOR POSITION"
DEFB #0D0D
DEFM "IF THERE IS NO SPACE IN A RECORD"
DEFB 13
DEFM "YOU ARE ALTERING USE THE INSERT"
DEFB 13
DEFM "FUNCTION TO MAKE SOME SPACE."
DEFW #0D0D
DEFM "THE CURSOR KEYS ALLOW YOU TO"
DEFB 13
DEFM "MOVE THROUGH THE TEXT BUT YOU"
DEFB 13
DEFM "CANNOT GO BACK PAST AN ENTER"
DEFW #0D0D
DEFW #410
DEFM "PRESS ENTER TO RETURN TO TEXT"
DEFW #10
DEFB #8D
MESS 11 DEFM "PRESS S TO SAVE L TO LOAD"
DEFB #8D
MESS 12 DEFM "PRESS M FOR M/DRIVE"
DEFB 13
DEFM "OR T TO TAPE"
DEFB #8D
MESS 13 DEFM "INPUT FILE NAME"
DEFB #8D
ZEND DEFB #8D