ПРИЛОЖЕНИЕ 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 2D2BhCALL 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,ALD ВС,(COORD)
CALL PLOT
IM 2
RET; это важная программа, делающая указатель таким, чтобы
; программа прерываний стартовала с нужного адреса (здесь
51500)1
ORG 51500
; сохраним все используемые регистры
PUSH HL
PUSH ВС
PUSH DE
PUSH AF; сохраним TV флаг, т.к. он может быть изменен
LD А,(23612)
PUSH AF1
; сохраним CO ORDS, т.к. они будут изменены, перед воз-
вратом их; нужно восстановить
1
LD HL,(23677)
PUSH HLLD ВС,(COORD); координаты спрайта
PUSH ВС ; сохраним их
; вызываем программу вывода спрайта. По окончании каж-
дого вывода; это сотрет предыдущую позицию
CALL PLOTPOF* ВС ; восстановим координаты спрайта
>
; "L" используется как флаговый регистр для определения
; направления движения спрайта
; бит 0 установлен - вверх, сброшен - вниз
; бит 1 установлен - влево, сброшен - вправоLD HL(FLAG)
BIT 0,L
JR Z,UPDOWN DEC 8 ; передвижение спрайта вниз на пиксель
JR NZ,LEFT ; если флаг 0 - дошли до низа экрана и
; направление меняется
RES 0,L
JR LEFTUP INC В ; один пиксель вверх
LD А,В ; дошли ли до верха экрана?
CP 174
JR NZ,LEFTSET 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 AFLD (23612),A
«1
; восстановим регистры
POP AF
POP DE
POP ВС
POP HL
; сканируем клавиатуру, т.к. этого не делалось потому, что
; программа прерываний была перемещена в ОЗУRST #38
RETICOORD DEFW О
FLAG DEFW О; "D" используется как счетчик, т.к. «В» уже использован
PLOT LD D,4
i
; запомним координаты, т.к. они будут испорчены програм-
мами ПЗУ1
PUSH ВС
LOOP LD A,DPUSH 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 #D5JR 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 16CONT1 RES 0,(IY+87); сбросим "OVER 1"
POP ВС ; восстановим последнюю позицию печати
POP DE ; и счетчик
DEC DJR 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 В,0PINGL 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
RETCOL DEFB 0
□ DEBASE
DEBASE состоит из нескольких отдельных подпрограмм, собран-
ных в грубую, но эффективную систему для работы с базами данных,
есть программы для записи и загрузки как с ленты, так и с МИКРО-
ДРАЙВа. Программа позволяет производить следующие операции:
вводить, печатать, находить, вычеркивать и изменять. Нет ограни-
чений на число отдельных записей и размер каждой записи, за иск-
лючением одного требования: запись должна помещаться на экране
без "Scroll". Может быть найдена любая часть любого текста, курсор
будет помещен в начало найденного набора символов. Запись может
быть изменена, дополнена или сокращена после первого ввода без
уничтожения или изменения любых других частей. После этого ос-
вободившаяся память может быть использована. Программа исполь-
зует 1 байт памяти на символ и 1 байт на запись для маркировки
конца записи; 32 ООО байт свободны для записи и есть место для
дополнительных функций.; Эта программа печатает все, что начинается с байта с
; активизированным битом 7 до следующего байта с таким
битом 7.
; В ней есть три основные точки входа и два способа
; использования. Если регистр А содержит на входе 255,
регистр
; DE должен содержать адрес первого символа сообщения,
; предваренного байтом с активизированным битом 7. Для
всех
; других значений А напечатается сообщение из таблицы,
идущее в; ней под заданным номером.
МС1 ORG 62500PRESS PUSH AF ; эта точка входа устанавливает начало
; печати в левую верхнюю позицию экрана
PUSH DE
LD А,2CALL #1601 ; подтверждаем, что основной экран
; текущий, иначе позиция печати
; установится в другой экран, а в
; основном экране не изменится
LD ВС,#1821CALL 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 AFPRINT INC A ; этот вход использует текущий поток
DEC DE ; поместим в "DE" начало маркера
JR Z,PRINTP ; если в «А» #FF используем адрес из DE
DEC АLD DE,MESS-1 ; DE установлен в начало таблицы
; сообщенийPRINTP CALL 3082 ; программа ПЗУ для печати
RETMESS EQU 1
; Эта программа ищет в памяти строку, начало которой
находится в; SCHAR. Завершается маркер-байтом, содержащим 255.
Если; соответствие найдено, то находится начало записи путем
подъема; вверх до байта с активизированным битом 7, который
печатается; предыдущей программой.
; Если конец каждой записи промаркирован #8D, то содер-
жимое; SCHAR будет #FF (ничего не нашли) вместо сообщений
ничего; напечатано не будет, так как ничего не найдено.
; На выходе регистры ВС будут содержать либо адрес начала
; записи, содержащей строку, либо 0, если строка не была
найденаМС2 ORG #F450
FINDIT LD HL,SCHAR ; основная точка входа
LD A,(HL)
CP #FFJR NZ,SEARCH
INC HL
LD (HL),A
DEC HL
LD A,#8D
LD (HL),ASEARCH PUSH HL
LD HL,30002
LD ВС,34000
POP DELOOKMO PUSH DE
LOOKON CPIR ; ищем первый символ, если строка не
; найдена
JR NZ,NOTFIND
DEC HLLD (LOCFND),HL; сохраним ячейку, где нашли, и отсчитаем
; влево 80
LD (LOCCNT),BCPOP DE
PUSH DEMAYBE INC HL ; теперь проверяем посимвольно
EX DE,HL
INC HL
LD A,(HL)CP 255 ; когда найден конец строки - строка
; найденаJRNZ, FOUND
•EX DE,HL
CP (HL)
JRZ,MAYBELD 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 HLBACKMO DEC HL ; ищем начало входа для печати
BIT 7,(HL)
JRZ,BACKMO
INC HL
PUSH HL
PUSH HL
CALL 5435 ; очистим весь экран
POP DELD A,#FF ; программа печати должна использовать
; адрес из DE
CALL PRESS
POP ВС
RETNOTFND LD A,3 ;печать сообщения 3
CALL PRINAT
POP HL
LD BC,0RET
•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 PRINATCHECKB LD A,127 ; это один из способов сканирования
; нажатия ключей, см. главу 2
IN A,(#FE)
RRAJR NC,BREAK
LD A, 127
IN A,(#FE)
BIT 3,A
JRZ.NEXTR
LD A,254
IN A,(#FE)
BIT 2,AJR NZ,CHECKB
POP ВС
POP HL
PUSH ВСPUSH ВС ; ВС - начало записи
POP HL
LD BC,0F END BIT 7,(HL)
INC HLINC ВС ; конец записи должен быть найден
JR Z.F ENDPOP DE ; теперь все вплоть до LIMIT опускается
; и запись уничтожается
PUSH ВС
PUSH HL
POP ВС
PUSH HL
LD HL,(LIMIT)
AND A
SBC HL,BC
PUSH HL
POP ВС
POP HL
LDIRPOP ВС ; количество добавленной памяти
RETBREAK POP HL ; очистим стек, скажем о ненахождении
POP ВС
LD ВС,О
RETNEXTR 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 OPEN1LD ВС,#1821 ; позиция печати в нижнем экране
; устанавливается влево - вверх
CALL 3545LD А,7 ; сообщение 7
CALL PRINTLD А, 1 ; фирменный знак программы
CALL PRESSXOR А ; очищается флаг режима редактирования
LD (WFLAG),ALD ВС,#1621 ; установим строку 2, колонку О
CALL 3545
LD А,""
RST 16CALL CURSOR
INPUT CALL OPEN1INP1 CALL #10A8 ; это программа ввода с клавиатуры
JR C,KEYPRE ; перенос активизируется при вводе ключа
RES 3,(IY+2); это TV флаг, см. «Ожидание ввода»
; глава 2
JR INP1KEYPRE CP 198 ; теперь запрашиваем специальные клави-
шиJRZ,BACK1
CP 9JP 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 #8DJP Z,ENDREC
OKTHEN POP AFCP 226 ; стоп, оканчивающий ввод
JR Z,STOPLD (HL),A ; код символа помещается в текущую
; ячейку памяти, в следующий раз она
; будет изменена
LD (CUPOS),HL
CP 13JR 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_ONCALL BACK ; но возврат после ввода означает повтор
; печати и изменение режима
JR FINRET
B ON CALL OPEN2
CALL CURSOR
LD А,О
RST 16
CALL CURSOR
JP INPUT ; возврат за следующим символом
•STOP PUSH HL; если нажали STOP при новом вводе, то
; необходимо маркировать конец записи
DEC HLENDIS 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),ASTOPON 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 MENUINXINPUT CALL FINPT ; начало программы вычеркивания
CALLXRECLD HL,(CHPOS); свободная память увеличивается
; изменением указателя памяти на
; количество вычеркнутых байтов
AND А
SBC HL,BC
LD (CHPOS)tHL
JP PMESS4
FINPUT CALL FINPT ; поиск начала записи
CALL FINDITFINRET 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 16CALL CURSOR
LD BC,(CURSP)R1M0RE LD А,В
OR СJPZ,INPUT
PUSH ВС
CALL RIGHTS
POP ВС
DEC ВСJR RIMORE
•1
1FINPT CALL 3435; похоже на предыдущую программу ввода,
; но не допускает вычеркиваний и
; ограничивает ввод, останавливаясь по
; достижении "INLIM"
LD А,5
CALL PRESS
LD A,62
RST 16
LD HL,SCHAR+32
LD (IN_LIM),HL
LD HL,SCHARi
INPUTF PUSH HL ; подпрограмма ввода
CALL OPEN1
CALL #15DE
POP HDCP 13 ; прекращается нажатием ENTER
JR Z,SETFIN
CP 32JRZ,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
1LOOKM 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 AFRET
CURSOR PUSH AF; печать курсора и передвижение позиции
; печати назад на 17 позиций
CALL OVER1
LD А,95
RST 16
LD А,8
RST 16
CALL OVERO
POP AF
RET
RIGHT1 CALL RIGHTS
JP INPUTRIGHTS 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 13JR Z.RITEON
CALLOVER1
LD A, 32RITEON RST 16
CALL CURSORRET
«)
« *
)
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 HLLD (CHPOS),HL
LD HL, (CUPOS)
INC HL
CALL BACKJP 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 HLLD (CHPOS) ,HL
POP HL
LD A,32
LD (HL),A
CALL BACKJP 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 ACALL PRINTP
POP ВСJP FINRET
♦•HELP CALL 3435
LD A, 10 ; страница HELP
CALL PRESS
WAITE LD A,OOF
IN A, (OFE)
AND 1JR 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 PRESSLD 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 2JR 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,OFFCALL 1222 ; используется программа ПЗУ, возврат с
; вновь отключенными прерываниями
EIJP LORET
; ниже приведенная программа отключает 16К ПЗУ
;см. главу 3ORG #FB38
RSWAP LD HL,ROMOUNT
LD (23789) ,HL ; программа ПЗУ использует обходной код
; 32, поэтому установите возврат к этой
; программе
ЕХХLD(HLSAV),HL
ЕХХLD (BCSAV) ,ВС
RST 8 ; используем обходной код
DEFB #32ROMOUNT POP HL ; два адреса программы должны быть
; перемещены и возврат из этой программы
; это "ERR SP", см. главу 4
POP HL
POP DE
LD HL, (23613)
PUSH HL ; сохраним позицию возврата по ошибке на
; стеке для дальнейшей работы
LD HL,MSLRETPUSH HL ; поместим на стек новый адрес возврата
; по ошибке, укажем в "ERR SP" для
; восстановления адреса возврата
LD (23613),SP
PUSH DE
RET
; программа записи на МИКРОДРАЙВ
♦ ♦ORG #FB5A
MS AVE CALL RSWAPCALL MHEAD ; зададим заголовок и системные
; переменные
CALL VARSETSET 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 HLLD 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
DILD IX,SCHAR+15
CALL #562
EICALL 8020
RET NC ; нажат BREAK
TESTHE LD IX,SCHAR ; проверка имени заголовка
LD HL,SCHAR+15
LD В, 11TESTLP 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
EICALL 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
SCFJR Z,MOTFIN
LD A,#FB
IN A,(#FE)
AND 16JR 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,32SETHED INC HL
LD (HL),ADJNZ 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 #80MESS1 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 #0D0DDEFM "S TO SAVE OR LOAD"
DEFW #10
DEFB #8DMESS5 DEFM "ENTER DETAILS TO FIND"
DEFB #8 D
MESS6 DEFW #210
DEFB 13DEFM "END OF RECORD, NO MORE INPUT"
DEFB 13DEFM "POSSIBLE"
DEFB #8D
MESS7 DEFW #110
DEFM "PRESS"
DEFW #210
DEFM "STOP"
DEFW #110
DEFM "FOR MENU"
DEFW #210
DEFB 2
DEFM "TO"
DEFW #110DEFM "ТО 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 13DEFM "SAVE THE RECORDS OR SOMETHING"
DEFW #10
DEFB #8DMESS10 DEFM "WHEN YOU ARE IN EDIT MODE"
DEFB 13DEFM "PRESSING"
DEFW #210
DEFM "NOT"
DEFW #010DEFM "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 13DEFM "AT THE CURRENT CURSOR POSITION"
DEFB #0D0DDEFM "DELETE WILL REMOVE THE CHARACTER"
DEFB 13DEFM "AT THE CURRENT CURSOR POSITION"
DEFB #0D0DDEFM "IF THERE IS NO SPACE IN A RECORD"
DEFB 13DEFM "YOU ARE ALTERING USE THE INSERT"
DEFB 13DEFM "FUNCTION TO MAKE SOME SPACE."
DEFW #0D0D
DEFM "THE CURSOR KEYS ALLOW YOU TO"
DEFB 13DEFM "MOVE THROUGH THE TEXT BUT YOU"
DEFB 13DEFM "CANNOT GO BACK PAST AN ENTER"
DEFW #0D0D
DEFW #410DEFM "PRESS ENTER TO RETURN TO TEXT"
DEFW #10
DEFB #8DMESS 11 DEFM "PRESS S TO SAVE L TO LOAD"
DEFB #8DMESS 12 DEFM "PRESS M FOR M/DRIVE"
DEFB 13DEFM "OR T TO TAPE"
DEFB #8DMESS 13 DEFM "INPUT FILE NAME"
DEFB #8D
ZEND DEFB #8D