╔───────────────────────────────────────╗ │ ─── ИСПОЛЬЗОВАНИЕ ПОДПРОГРАММ ПЗУ ─── │ ╚───────────────────────────────────────╝ по книге 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. Вы затащились ? ──────────────────────