╔───────────────────────────────────────╗
│ ─── ИСПОЛЬЗОВАНИЕ ПОДПРОГРАММ ПЗУ ─── │
╚───────────────────────────────────────╝
по книге by Ian Logan & Dr Frank O'Hara
"The Complete Spectrum ROM DISASSEMBLER"
Когда-то очень давно, аж в 1991 году
в журнале "ZX-РЕВЮ" был опубликован цикл
статей с описанием точек входа в подпрог-
раммы ПЗУ. Однако, это благое начинание
не было доведено до конца, и напечатаны
описания подпрограмм только по адрес
#1727. Т.к. в редакции появилась эта кни-
га, то мы решили сделать небольшой ее об-
зор на предмет выявления подпрограмм,
которыми есть смысл пользоваться для эко-
номии памяти в своих программах. Чтобы не
повторяться с другими изданиями, я освещу
только ранее неуказанные точки входа.
В начале некоторых процедур стоит
контроль проверки синтаксиса. Поэтому
точки входа в эти процедуры даны со сме-
щением.
CLEAR-PRB #0EDF
Очищается буфер принтера, устанавливаются
его системные переменные.
INDEXER #16DC
Поиск элемента в таблице. Если найден -
устанавливается флаг переноса. Конец
таблицы - код #00.
вх: HL - адрес начала таблицы
C - искомый байт
вых: HL - адрес найденного байта
NUMBER #18B9
Увеличить HL на 5, загрузить A по HL
RANDOMIZE #1E4F
вх: BC - любое число
вых: BC - случайное число
FREE MEMORY #1F1A
вых: BC - количество свободной памяти
STK-FETCH #2BF1
Снимает 5 байт со стека калькулятора.
вых: A - первый байт
E
D ...
C
B - пятый байт
ALPHANUM #2C8D
Устанавливает флаг C если в A цифра или
заглавная буква.
LOG (2^A) #2DC1
вх: A - степень
вых: A - логарифм
A=10*A+C #2F8B
(портит только HL)
вых: A - результат
C - если результат больше #FF, то
старший байт, иначе = 0
HL=HL*DE #30A9
В этом кратком обзоре совершенно не
рассмотрены процедуры калькулятора. Если
эта тема представляет интерес, напишите в
редакцию. Если вы полностью разобрались с
работой с калькулятором и можете привести
конкретные примеры его практического ис-
пользования и готовы поделиться своим
опытом - пишите нам !
──────────────────────
А теперь несколько подпрограмм, ко-
торые могут пригодиться при разработке
ваших собственных программ.
Функция VAL x$ для десятичных чисел:
────────────────────────────────────
(перевод строки в число)
(вытащена из программы mon2)
LD DE,string-1; адрес строки-1
CALL val_dec ; переводим
; HL = VAL "12345"
....
string DEFM "12345"
val_dec
LD HL,0
L1 INC DE
JR NZ,L2
CALL 11547
CCF
RET NC
PUSH DE
LD D,H
LD E,L
ADD HL,HL
ADD HL,HL
ADD HL,DE
ADD HL,HL
LD D,0
SUB 48
LD E,A
ADD HL,DE
POP DE
JR L1
CP 97
JR C,L4
SUB 32
L4 CP 48
RET C
CP 71
RET NC
SUB 48
CP 10
JR C,L3
SUB 7
CP 10
RET C
L3 ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
OR A
LD L,A
JR L1
Функция VAL x$ для HEX-чисел:
─────────────────────────────
(придумал я)
LD DE,string ; адрес строки
CALL val_dec ; переводим
; HL = VAL "1A"
....
string DEFM "1A"
val_hex
PUSH AF ; *
PUSH HL ; *
LD A,2 ; *
LD B,A ; *
v_ch_h LD A,(HL) ; *
CP 48 ; *
JR C,ex_vh ; <0 *
CP 71 ; *
JR NC,ex_vh; >="G" *
CP 58 ; *
JR C,con_ ; <=9 *
CP 65 ; *
JR C,ex_vh ; <"A" *
con_ INC HL ; *
DJNZ v_ch_h ; *
POP HL ; *
POP AF ; *
CALL conv
OR A
RLA
RLA
RLA
RLA
PUSH AF
INC HL
CALL conv
OR A
POP HL
ADD A,H
RET
conv LD A,(HL)
SUB 48
CP 10
RET C
SUB 7
RET
ex_vh POP HL ; *
POP AF ; *
XOR A ; *
RET ; *
Строки, отмеченные "*" служат проверкой
шестнадцатиричное это число или нет и
их можно удалить при необходимости.
Печать байта в HEX-виде
───────────────────────
(вытащено из Monitor Turbo 90,
адрес #38C1)
вх: A - число
HEX_BYT PUSH AF
RRA
RRA
RRA
RRA
CALL OUT_H
POP AF
OUT_H AND 15
CP 10
JR C,O_H1
ADD A,7
O_H1 ADD A,48
RST 16
RET
А вы знаете, почему в большинстве
программ (особенно старых) ввод и вывод
осуществляется в HEX-виде ? Когда-то я
думал, что это делается для "понта". Все
оказалось гораздо проще : HEX-числа легче
обрабатывать. Сравните вышеуказанную про-
цедуру с подпрограммой печати десятичных
чисел (см. точки входа в ПЗУ #15EF или
#1A1B или #2DE3).
Без сомнения, у многих наших читате-
лей при написании собственных программ
бозникали проблемы с обработкой ошибок
TR-DOS. Некоторые пишут дисковые драйвера
с использованием прямого программирования
ВГ-шки, другие идут обходным путем. Пред-
лагаю вашему вниманию дисковый драйвер,
использующий точку входа #3D13 и обраба-
тывающий все ошибки самостоятельно. Идея
драйвера позаимствована из игры "LAST
BATTLE".
Oбращение к драйверу стандартное:
LD HL,куда
LD D,дорожка
LD E,сектор
LD B,количество секторов
LD C,код функции -
(5-load, 6-save)
CALL dos
А вот и сам драйвер (слегка изменен):
dos PUSH HL
XOR A
LD (23824),A ; Сброс кодов
LD (23822),A ; ошибки TR-DOS
DEC A ; в ERR_NR код
LD (23610),A ; "нет ошибки"
LD A,#C3 ; формируем по
LD (#5CC2),A ; адресу #5CC2
LD HL,obr_er ; JP obr_er
LD (#5CC3),HL ;
LD HL,oth_err ; ERR_SP тоже на
LD (#5C3D),HL ; нашу процедуру
POP HL
LD (dos_sp),SP; сохраняем стек
; для выхода по
; ошибке
CALL #3D13
RET
dos_sp DEFW 0
DEFW 0 ; стек для выхода
DEFW 0 ; по ошибке NO DISK
oth_err DEFW no_disk ; здесь адрес п/п
; no_disk
no_disk
LD SP,#FFFF ; или на любое сво-
; бодное место
; Сказать "НЕТ ДИСКА".
; Здесь ваши процедуры, которые этим
; занимаются, после чего...
JP abort
obr_er POP HL ; собственно процедура
PUSH AF ; обработки ошибок типа
; READ/WRITE
CALL #1F54 ; проверка нажатия
JR NC,break ; клавиши BREAK
LD A,H
CP 13
JR NZ,obr1
LD A,L
CP #6B
JR Z,error
obr1
LD A,H
CP #1F
JR NZ,obr2
LD A,L
CP #54
JR Z,okay
obr2 ; возникла ошибка
POP AF ; не READ/WRITE
PUSH HL ; обычно "NO DISK"
RET
okay
POP AF
SCF ; BREAK не нажата
RET
break
; Сказать "Нажата BREAK"
; Здесь ваши процедуры...
abort
LD SP,(dos_sp) ; выходим из
DEC SP ; драйвера
DEC SP
RET
error
POP HL
POP HL
POP HL
POP HL
POP HL ; если L=#D8 -"Read only"
; иначе просто "Disk error"
; Сказать "Retry, Abort, Ignore"
; Здесь ваши процедуры...
retry LD HL,16276
PUSH HL
ignore JP 15664
В процессе написания этой статьи ме-
ня посетила мысль : а почему бы в рамках
раздела "ОБМЕН ОПЫТОМ" не открыть рубри-
ку, подобную "ЭТЮДЫ" в "ZX-РЕВЮ" ? Мы
могли бы все вместе создать неплохой банк
подпрограмм, которые сберегли бы немало
времени и нервов как начинающему хакеру,
так и программисту со стажем. А в выигры-
ше будут все пользователи SPECCY.
Если вам понравилась моя мысль и вы
готовы поддержать это начинание - пишите
к нам в редакцию.
──────────────────────
А теперь - прикол. Наберите (не ини-
циализируя TR-DOS):
1 PRINT 1
30 PRINT 30
POKE 23756,90
100 PRINT 100
45 PRINT 45
Как вам картинка на экране ? Но это еще
не все. Дайте команды:
RUN, GOTO 45, GOTO 90, GOTO 30.
Вы затащились ?
──────────────────────