ZX Review
#1-2
31 декабря 1996 |
|
Возвращаясь к напечатанному - последний файл диззасемблера TR-DOS.
ВОЗВРАЩАЯСЬ К НАПЕЧАТАННОМУ В недавно выпущенной нами книге П.Федина "Полное описание и полный дизассемблер TR DOS 5.04 (5.03)" из-за технологической ошибки не был напечатан последний файл полного дизассемблера. Приносим автору и читателям свои извинения и исправляем допущенную оплошность. Итак: Адрес 15361. То же, что и 15665. 15361 JR 15366 ──────────────────────────────────────────────────────────────── Адрес 15364. То же, что и 15642 15364 JR 15369 ──────────────────────────────────────────────────────────────── Адрес 15366. То же, что и 15665. 15366 JP 15616 ──────────────────────────────────────────────────────────────── Адрес 15369. То же, что и 15642. 15369 JP 15619 ──────────────────────────────────────────────────────────────── Адрес 15610. То же, что и 8433. 15610 JP 8433 ──────────────────────────────────────────────────────────────── Адрес 15613. То же, что и 15635, но не переключает ПЗУ. 15613 JP 10300 ──────────────────────────────────────────────────────────────── Адрес 15616. Вход в TR-DOS. Переключает ПЗУ. 15616 NOP JR 15665 ──────────────────────────────────────────────────────────────── Адрес 15619. Выполнение команд TR-DOS из бейсика. Установите CH_ADD на префикс :REM: перед командой. Возвращает в BC код ошибки. Переключает ПЗУ. 15619 NOP JR 15642 ──────────────────────────────────────────────────────────────── Адрес 15622. Подпрограмма ввода из файла данных. Переключает ПЗУ. При вызове из редактора вводит всю строку и производит выход из редактора, иначе возвращает в A символ из файла. 15622 NOP JP 9711 ──────────────────────────────────────────────────────────────── Адрес 15626. То же, что и 15629, но не переключает ПЗУ. 15626 JP 9290 ──────────────────────────────────────────────────────────────── Адрес 15629. Подпрограмма вывода в файл данных. Символ поместите в аккумулятор. Используется также с адреса 15630. Обе точки входа переключают ПЗУ. 15629 NOP 15630 JR 15626 ──────────────────────────────────────────────────────────────── Адрес 15632. То же, что и 8433. Переключает ПЗУ. 15632 NOP JR 15610 ──────────────────────────────────────────────────────────────── Адрес 15635. Переход на подпрограмму вызова подпрограмм TR-DOS из машинного кода. Адрес является переключателем. 15635 NOP JR 15613 ──────────────────────────────────────────────────────────────── Адрес 15638. Переход на подпрограмму обработки ошибок. Адрес является переключателем. 15638 NOP JP 12137 ──────────────────────────────────────────────────────────────── Адрес 15642. То же, что и 15619, но не переключает ПЗУ. 15642 CALL 15649;создание системных переменных TR-DOS PUSH HL ;помещение на стек адреса переключателя ПЗУ на бейсик JP 364 ;выполнение команды ──────────────────────────────────────────────────────────────── Адрес 15649. Создание области системных переменных TR-DOS, если ее нет. В HL помещается 23746. 15649 CALL 12787 ;проверка наличия области системных переменных NOP NOP CALL C,15692;если ее нет, то создание ее LD HL,23746 ;загрузка в HL адреса переключателя ПЗУ на бейсик RET ;возврат ──────────────────────────────────────────────────────────────── Адрес 15663. Переключение пзу на TR-DOS и переход на любой адрес. Адрес поместите на стек. 15663 NOP RET ──────────────────────────────────────────────────────────────── Адрес 15665. Вход в TR-DOS. 15665 CALL 15649;создание области системных переменных PUSH HL ;помещение на стек адреса переключателя ПЗУ на бейсик JP 569 ;вход в TR-DOS ──────────────────────────────────────────────────────────────── Адрес 15672. Проверка наличия интерфейса-1. В случае его обнаружения происходит создание его системных переменных и в 23793 помещается 1. Для работы подпрограмма должна быть перемещена в любое место ОЗУ. 15672 XOR A ;интерфейс-1 есть ? OUT (247),A IN A,(247) CP 30 JR Z,15684 ;если да, то создание его системных переменных CP 31 RET NZ ;если нет, то возврат 15684 RST 8 ;создание системных переменных интерфейса-1 DEFB #31 LD A,1 ;по команде SAVE записывать 1 копию LD (23791),A RET ;возврат ──────────────────────────────────────────────────────────────── Адрес 15692. Создание системных переменных TR-DOS. При наличии интерфейса-1 перед созданием переменных TR-DOS создаются его переменные и в 23791 помещается 1. В переменные TR-DOS помещаются: в 23802 - 23804, 23752 - 23754, 23610, 23830 и 23820 - 255; в 23831, 23833, 23832, 23823 и 23839 - 0; в 23746 - 201. Также в системный регистр помещается 255, а на ВГ93 выдается команда прерывания. Подпрограмма портит ячейки памяти калькулятора. 15692 XOR A ;выбор дисковода A: и сброс ВГ93 OUT (255),A IN A,(246) ;это ничего не дает LD HL,15672;адрес подпрограммы проверки наличия интерфейса-1 LD DE,23698; любой свободный адрес, ОЗУ LD BC,20 ;длина подпрограммы LDIR ;перенос подпрограммы в ОЗУ LD HL,15719;адрес возврата из подпрограммы PUSH HL ;помещение его на стек LD HL,15663;адрес переключателя ПЗУ на TR-DOS PUSH HL ;помещение его на стек JP 23698 ;запуск подпрограммы ──────────────────────────────────────────────────────────────── Адрес 15719. Создание системных переменных TR-DOS. В переменные помещаются: в 23802 - 23805, 23752 - 23755, 23610, 23830 и 23820 - 255; в 23831, 23833, 23832, 23823 и 23839 - 0; в 23746 - 201. Также в системный регистр помещается 255, а на ВГ93 выдается команда прерывания. 15719 LD HL,12176 ;адрес возврата из пзу бейсика PUSH HL ;помещение его на стек LD HL,15663 ;адрес переключателя ПЗУ на TR-DOS PUSH HL ;помещение его на стек LD HL,5717 ;адрес подпрограммы MAKE_ROOM из ПЗУ бейсика PUSH HL ;помещение его на стек LD HL,23551 ;адрес переключателя ПЗУ на бейсик PUSH HL ;помещение его на стек LD (HL),201 ;помещение в озу команды RET LD HL,23773 ;начальный адрес области системных переменных LD BC,112 ;длина ее RET ;запуск подпрограммы MAKE_ROOM ──────────────────────────────────────────────────────────────── Адрес 15744. Перевод строки. Используется также с адреса 15746 (печать символа из аккумулятора). Также эта подпрограмма ошибочно используется с адреса 15755 подпрограммой 1270. 15744 LD A,13 ;символ ENTER 15746 PUSH HL ;сохранение регистров PUSH BC PUSH DE PUSH AF ;сохранение символа CALL 8433 ;изменение памяти POP AF ;восстановление символа 15754 CALL 15764;печать символа CALL 8433 ;восстановление памяти POP DE ;восстановление регистров POP BC POP HL RET ;возврат ──────────────────────────────────────────────────────────────── Адрес 15764. Печать символа без изменения памяти. Символ поместите в аккумулятор. 15764 RST 32 DEFW #0010 RET ──────────────────────────────────────────────────────────────── Адрес 15768. Восстановление с ожиданием INTRQ. Используется также с адреса 15770 (отдача команды из рег. A с ожиданием INTRQ). 15768 LD A,8 ;восстановление 15770 OUT (31),A 15772 PUSH HL ;сохранение HL RST 32 ;проверка нажатия BREAK DEFW #1F54 JR C,15781;если нажато, то сообщение *BREAK* RST 32 DEFW #1B7B 15781 POP HL ;восстановление HL IN A,(255);INTRQ поступил ? AND 128 JR Z,15772;если нет, то повтор RET ;возврат ──────────────────────────────────────────────────────────────── Адрес 15789. Проверка наличия диска в дисководе. Никаких установок не требуется. 15789 LD A,8 ;команда восстановления CALL 15770 ;выдача команды и ожидание INTRQ LD DE,0 ;за 65536 проходов индексный сигнал должен измениться IN A,(31) ;берем индексный сигнал для образца AND 2 LD B,A ;запоминаем его 15802 IN A,(31) ;берем его снова AND 2 CP B ;он изменился ? RET NZ ;если да, то возврат INC DE ;следующая попытка LD A,E ;попытки кончились OR D JR NZ,15802;если нет, то повтор JP 16103 ;обработка ошибки NO DISC ──────────────────────────────────────────────────────────────── Адрес 15816. Выбор дисковода, определенного по умолчанию. Вход: можно установить время перемещения головки и режим дисковода согласно описанию команды #01. Выход: эти переменные могут быть изменены согласно этому описанию. Используется также с адресов: 15819 - выбор дисковода. Номер задайте в рег. A, остальное как и для предыдущей подпрограммы. 15869 - задержка в 725779 тактов. 15871 - задержка любой нужной длительности. В рег. A установите число, определяющее длительность задержки. 15816 LD A,(23833);берем номер дисковода по умолчанию 15819 LD (23798),A;установка номера выбранного дисковода LD HL,23830 ;выбор дисковода LD C,A LD A,60 OR C OUT (255),A LD (HL),A CALL 15880 ;берем время перемещения головки дисковода AND 128 ;бит 7 выключен ? JR Z,15866 ;если да, то инициализацию не проводим CALL 15789 ;проверка наличия диска в дисководе CALL 15894 ;определение времени перемещения головки дисковода CALL 15889 ;берем тип дисковода CP 255 ;в этой переменной 255 ? JR Z,15866 ;если да, то не определяем его PUSH HL ;сохраняем адрес переменной с типом дисковода CALL 8138 ;определение количества дорожек дисковода POP HL ;восстановление адреса переменной типа CP 80 ;установка этой переменной LD A,0 JR NZ,15865 LD A,128 15865 LD (HL),A Внимание, ошибка!!! Не проверяется количество сторон дисковода и предполагается, что он односторонний. 15866 CALL 7734 ;проверка индексной области диска 15869 LD A,0 ;задержка в 725779 тактов 15871 LD C,255 15873 DEC C JR NZ,15873 DEC A JR NZ,15871 RET ;возврат ──────────────────────────────────────────────────────────────── Адрес 15880. Выборка времени перемещения головки текущего дисковода. Установите 23798. На выходе в A будет время перемещения головки дисковода, а в HL - адрес, по которому оно находится. Используется также с адреса 15883 (выборка параметра дисковода; в DE поместите адрес таблицы параметров и установите 23798; На выходе в A будет параметр, в HL - адрес его ячейки). 15880 LD DE,23802 ;берем адрес таблицы скоростей перемещения головок 15883 LD HL,(23798);смещение равно номеру дисковода ADD HL,DE ;вычисление адреса ячейки с параметром LD A,(HL) ;берем оттуда параметр RET ;возврат ──────────────────────────────────────────────────────────────── Адрес 15889. Выборка типа дисковода. Вход: установите 23798. Выход: в A тип дисковода, в HL - адрес его ячейки. 15889 LD DE,23752;берем адрес таблицы типов дисководов JR 15883 ;выборка параметра и возврат ──────────────────────────────────────────────────────────────── Адрес 15894. Определение времени перемещения головки дисковода. 15894 CALL 15880 ;берем адрес ячейки с временем перемещения головки LD B,8 ;начнем с наименьшего LD C,4 ;4 попытки 15901 LD (HL),B ;установка времени перемещения головки LD A,8 ;восстановление CALL 15770 LD A,32 ;позиционирование на дорожку 32 LD B,11 CALL 15940 LD B,(HL) ;берем время перемещения головки LD A,1 ;позиционирование на дорожку 1 с заданным временем CALL 15940 IN A,(31) ;головка на дорожке 0 ? AND 4 JR NZ,15935;если да, то ошибка XOR A ;позиционирование на дорожку 0 IN A,(31) ;головка на дорожке 0 ? AND 4 RET NZ ;если да, то возврат 15935 INC B ;увеличение времени перемещения головки на 1 DEC C ;следующая попытка RET Z ;если попытки кончились, то возврат JR 15901 ;повтор ──────────────────────────────────────────────────────────────── Адрес 15940. Позиционирование. В A поместите физический номер дорожки, в B - время перемещения головки и выберите сторону. 15940 OUT (127),A;помещение номера дорожки в регистр данных LD A,B ;получение команды позиционирования OR 24 JP 2048 ;позиционирование с быстрой скоростью Внимание!!! Здесь нужно JP 15070, т.к. 2048 гасит биты скорости перемещения головки дисковода, следовательно позиционирование работает только с быстрой скоростью. ──────────────────────────────────────────────────────────────── Адрес 15948. Позиционирование. На входе в A должен быть физический номер дорожки, а в B - время перемещения головки дисковода. 15948 OUT (127),A;загрузка номера дорожки в регистр данных PUSH BC ;сохранение времени перемещения головки дисковода LD B,A ;головка уже спозиционирована ? IN A,(63) CP B POP BC ;восстановление времени перемещения головки PUSH AF ;сохранение результата проверки LD A,B ;получение команды позиционирования OR 24 CALL 2048 ;преобразование и выдача команды и ожидание INTRQ Внимание!!! Позиционирование осуществляется только с быстрой скоростью перемещения головки, т.к. в 2048 используется AND 252. Для исправления ситуации здесь нужно поставить JP 15770. POP AF ;восстановление результата проверки положения головки RET Z ;если головка была спозиционирована, то возврат PUSH BC ;сохранение времени перемещения головки ? CALL 15869 ;задержка в 725779 тактов POP BC ;восстановление времени перемещения головки RET ;возврат ──────────────────────────────────────────────────────────────── Адрес 15971. Позиционирование головки дисковода. Вход: в рег. A установите логический номер требуемой дорожки и установите 23757. На выходе 23757 обнуляется. Используется также с адреса 16032 (задержка в 2168937 тактов). 15971 LD C,A ;загрузка номера дорожки в регистр C CALL 8171 ;выбор верхней стороны диска CALL 15889 ;берем тип дисковода AND 2 ;дисковод двухсторонний ? CALL NZ,16042;если да, то выбор стороны PUSH BC ;сохраним номер дорожки BIT 7,(HL) ;дисковод 40-дорожечный ? JR Z,16003 ;если да, то номера дорожек не меняем BIT 0,(HL) ;используем только 40 дорожек ? JR NZ,16003 ;если нет, то номера дорожек не меняем IN A,(63) ;берем номер текущей дорожки CP C ;головка уже спозиционирована ? JR Z,16002 ;если да, то номера дорожек не меняем RLCA ;делим номер текущей дорожки на 2 OUT (63),A LD A,C ;делим номер требуемой дорожки на 2 RLCA 16002 LD C,A 16003 CALL 15880 ;берем время перемещения головки дисковода LD B,A IN A,(63) ;головка уже спозиционирована ? CP C PUSH BC ;сохраним номер требуемой дорожки CALL NZ,15869;если головка не спозиционирована, то задержка в 725779 тактов POP BC ;восстановление номера требуемой дорожки LD A,C CALL 15948 ;позиционирование POP BC ;восстановление номера требуемой дорожки LD A,C ;установка регистра дорожки OUT (63),A LD A,(23757) ;нужна задержка после операции ? OR A RET Z ;если нет, то возврат XOR A ;в следующий раз задержка не понадобится LD (23757),A 16032 LD B,3 ;задержка в 2168937 тактов 16034 LD A,255 CALL 15871 DJNZ 16034 RET ;возврат ──────────────────────────────────────────────────────────────── Адрес 16042. Выбор стороны при позиционировании. Вход: в C поместите логический номер дорожки и выберите верхнюю сторону диска. Выход: будет выбрана сторона, а в C будет физический номер дорожки. 16042 LD A,C ;деление номера дорожки на 2 OR A RRA LD C,A RET NC ;если номер дорожки был четный, то возврат JP 8182;иначе выбор нижней стороны диска ──────────────────────────────────────────────────────────────── Адрес 16050. Проверка индексной области дорожки. Установите 23761 и поместите в B время перемещения головки дисковода. Выбирается верхняя сторона и при ошибке в 23831 помещается 255. В регистр H помещается номер текущей дорожки. Используется также с адреса 16103 (обработка ошибки NO DISC). 16050 CALL 8171 ;выбор верхней стороны диска IN A,(31) ;берем состояние контроллера AND 128 ;сохранение флага готовности LD (23757),A IN A,(63) ;берем номер текущей дорожки LD H,A ;на случай возврата CALL 15940 ;преобразование и выполнение команды из рег. B Внимание!!! Перед CALL 15940 в регистр B надо поместить время перемещения головки дисковода, иначе команда, которая выполнится перед проверкой зависит от содержимого регистра B на входе в подпрограмму и последствия могут быть весьма плачевными. LD C,127 ;адрес регистра данных LD D,1 ;число,определяющее количество попыток DI ;запрет прерываний LD A,192 ;чтение индексной области OUT (31),A PUSH BC ;сохранение адреса регистра данных LD B,3 ;определяем количество попыток 16078 IN A,(255) ;берем состояние сигналов DRQ и INTRQ AND 192 JR NZ,16144 ;если какой-нибудь сигнал поступил, то начало чтения INC DE ;следующая попытка LD A,E OR D JR NZ,16078 DJNZ 16078 ;повтор до конца попыток POP BC ;восстановление адреса регистра данных EI ;разрешение прерываний LD A,208 ;остановка контроллера OUT (31),A LD A,(23761);ошибку игнорировать ? Ошибка!!! Надо LD A,(23831). CP 255 RET Z ;если да, то возврат 16103 CALL 10027 ;установка TAPE LOADING ERROR LD A,255 ;в следующий раз ошибку игнорировать LD (23831),A JP 10011 ;обработка ошибки NO DISC 16114 POP BC ;восстановление адреса регистра данных IN H,(C) ;чтение первого байта 16117 IN A,(255) ;ожидание какого-нибудь сигнала AND 192 JR Z,16117 EI ;на случай возврата Ошибка!!! Так можно потерять байт при чтении. RET M ;если поступил INTRQ, то возврат DI ;запрет прерываний IN A,(127) ;чтение байта JR 16117 ;повтор ──────────────────────────────────────────────────────────────── Адрес 16130. В комментариях не нуждается. 16130 LD (23807),A RET ──────────────────────────────────────────────────────────────── Адрес 16134. Похоже на предыдущее. 16134 LD (23808),HL RET ──────────────────────────────────────────────────────────────── Адрес 16138. Запись сектора. Спозиционируйте головку и установи- те 23807 и 23808. 16138 LD A,160;команда записи сектора JR 16144;переход к подпрограмме чтения / записи сектора ──────────────────────────────────────────────────────────────── Адрес 16142. Загрузка сектора. Установите 23807 и 23808 и спози- ционируйте головку. Используется также с адреса 16144 (загрузка / запись сектора; установите все для 16142 плюс в A поместите команду чтения или записи сектора). 16142 LD A,128 ;команда чтения сектора 16144 LD (23806),A ;установка команды 16147 LD D,10 ;10 попыток 16149 PUSH DE ;сохранение счетчика попыток DI ;запрет прерываний LD A,(23807) ;установка сектора INC A OUT (127),A LD HL,(23808);берем адрес чтения / записи LD C,127 ;берем адрес регистра данных LD A,(23806) ;отдаем команду OUT (31),A CP 160 ;была команда записи сектора ? PUSH AF CALL Z,16314 ;если да, то запись данных POP AF CALL NZ,16341;иначе чтение данных POP DE ;восстановление счетчика попыток EI ;разрешение прерываний IN A,(31) ;берем состояние контроллера LD B,A ;сохраняем его AND 127 ;все в порядке ? RET Z ;если да, то возврат LD HL,10712 ;адрес сообщения READ ONLY AND 64 ;запрещена запись ? JR NZ,16203 ;если да, то переход на обработку ошибки LD A,B ;восстановление состояния контроллера AND 4 ;была потеря данных ? JR Z,16288 ;если нет, то обработка дисковых ошибок DEC D ;следующая попытка JR NZ,16149 ;если попытки не кончились, то повтор 10200 LD HL,10722 ;адрес сообщения DISC ERROR 16203 LD A,208 ;команда прерывания OUT (31),A LD A,B ;восстановление состояния контроллера AND 1 ;контроллер был занят ? JP NZ,16103 ;если да, то обработка ситуации NO DISC IN A,(63) ;если ошибка произошла в секторе 10 дорожки OR A ;0, то возврат (игнорирование) JR NZ,16223 IN A,(127) CP 10 RET Z PUSH HL ;сохранение адреса сообщения CALL 7575 ;очистка экрана POP HL ;восстановление адреса сообщения RST 24 ;печать сообщения LD HL,10771 ;печать TRK: RST 24 IN A,(63) ;печать номера дорожки CALL 7587 LD HL,10776 ;печать SEC: RST 24 IN A,(95) ;печать номера сектора CALL 7587 LD HL,10750 ;печать RETRY,ABORT,IGNORE? RST 24 16251 CALL 4178 ;ввод клавиши CP "I" ;нажато I ? RET Z ;если да, то возврат CP "R" ;нажато R ? JR Z,16276 ;если да, то перепозиционирование и повтор CP "A" ;нажато A ? JR NZ,16251 ;если нет, то повтор ввода клавиши CALL 10027 ;установка TAPE LOADING ERROR LD A,7 ;дисковая ошибка LD (23823),A JP 467 ;завершение 16276 LD A,(23797) ;перепозиционирование CALL 15971 CALL 16032 ;задержка в 2168937 тактов JP 16149 ;повтор Ошибка!!! Надо JP 16147 для того, чтобы обновить число попыток. 16288 DEC D ;следующая попытка JP Z,16200 ;если попытки кончились, то обработка DISC ERROR PUSH DE ;сохранение счетчика попыток CALL 15880 ;берем время перемещения головки дисковода AND 2 ;оно равно 10 ? JR NZ,16301 INC (HL) ;если нет, то увеличение его на 1 16301 CALL 15768 ;восстановление LD A,(23797) ;перепозиционирование CALL 15971 POP DE ;восстановление счетчика попыток JP 16149 ;повтор ──────────────────────────────────────────────────────────────── Адрес 16314. Запись данных на диск. Установите в HL адрес блока данных, в DE - число, определяющее количество циклов, за которое должна начаться запись, в C - адрес регистра данных контроллера и отдайте команду записи. Используется также с адреса 16330 (то же, что и 16314, но без обработки NO DISC). 16314 LD B,4 ;установка количества попыток 16316 IN A,(255) ;поступил какой-нибудь сигнал ? AND 192 JR NZ,16337;если да, то начинаем запись INC DE ;следующая попытка LD A,E OR D JR NZ,16316 DJNZ 16316 RET ;если попытки кончились, то возврат 16330 IN A,(255) ;поступил какой-нибудь сигнал ? AND 192 JR Z,16330 ;если нет, то ожидание его RET M ;если поступил INTRQ, то возврат 16337 OUTI ;вывод байта из вашей области в регистр данных JR 16330 ;повтор ──────────────────────────────────────────────────────────────── Адрес 16341. Чтение данных с диска. Все установки аналогично подпрограмме 16314, но отдать нужно команду чтения. Используется также с адpеса 16357 (то же, что и 16341, но без обработки NO DISC). 16341 LD B,4 ;установка количества попыток 16343 IN A,(255) ;поступило что-нибудь ? AND 192 JR NZ,16364;если да, то начинаем читать INC DE ;следующая попытка LD A,E OR D JR NZ,16343 DJNZ 16343 RET ;если попытки кончились, то возврат 16357 IN A,(255) ;поступил какой-нибудь сигнал ? AND 192 JR Z,16357 ;если нет, то ждем его RET M ;если это INTRQ, то возврат INI ;чтение байта JR 16357 ;повтор
Другие статьи номера:
Похожие статьи:
В этот день... 12 сентября