┌──────────────────────────────┐ │ │ │ ЧИТАТЕЛЬ - ЧИТАТЕЛЮ │ │ │ └──────────────────────────────┘ (c) Иван Рощин, г.Москва, 1996 TR-DOS: как не допустить ошибки ? Вы удивитесь, если узнаете, сколько программ не распознают ошибки при работе с диском, не- правильно распознают их, а также зависают или сбрасываются при их возникновении. Разумеется, при написании собственных программ таких ситуаций следует избегать, хотя это не так-то просто. Дело в том, что корректная обработка ошибок становится возможной лишь при работе напрямую с микрокон- троллером дискового интерфейса, а это доступно далеко не каждо- му. Несмотря на это, надежность программ можно значительно уве- личить, если использовать наря- ду с обычными функциями TR-DOS специальные процедуры для распо- знавания ошибочных ситуаций. В этой статье пойдет речь об одной из самых распространенных ошибок ввода-вывода - отсутствии диска в дисководе. Также будет сказано несколько слов о прямом программировании ВГ93 и о про- граммах, контролирующих смену диска. Известно, что перед началом любой дисковой операции, связан- ной с чтением или записью дан- ных, необходимо, чтобы диск был установлен в дисковод и дверца дисковода была закрыта. Если это условие не выполняется, програм- ма (если она грамотно написана) обычно выдает одно из следующих сообщений: - No disk - Disk not present - Disk not ready Специальная процедура для оп- ределения наличия диска в диско- воде была бы очень полезной. Приведу лишь один из возможных примеров ее использования: если ваша программа использует интер- претатор системных функций TR-DOS и не осуществляет перех- ват ошибок, то при их возникно- вении (в частности, при отсут- ствии диска) может произойти сброс компьютера (что очень не- желательно). Но если с помощью указанной процедуры обнаружить отсутствие диска еще до вызова интерпретатора, можно избежать неприятных последствий (конечно, если не произойдет какой-нибудь другой ошибки). Рассмотрим несколько возмож- ных способов реализации такой процедуры: 1) Пробуем прочитать ка- кой-нибудь сектор (естественно, не с помощью вызова интерпрета- тора системных функций, а при прямом программировании контрол- лера). Так как считанная инфор- мация не понадобится, чтение можно проводить, скажем, в об- ласть ПЗУ. В случае неудачи счи- таем, что диска нет. Недостатки: неудачное считы- вание сектора еще не значит, что диск отсутствует. Вполне может быть, что сектор был записан с ошибкой или сектора с таким но- мером вообще нет на дорожке (т.к. в общем случае формат дис- ка может быть произвольным). Достоинства: при работе с диском фиксированного формата этот способ вполне подходит. 2) Делаем попытку прочитать первый встреченный заголовок сектора. В случае неудачи счи- таем, что диска нет. Недостатки: в общем случае диск может быть и неформатиро- ванным, при этом ничего прочи- тать не удастся, и мы получим неверный результат. Достоинства: этот способ го- дится для любого форматированно- го диска и достаточно прост в реализации. 3) Используем регистр состоя- ний микроконтроллера. Прежде чем говорить о дос- тоинствах и недостатках этого метода, вспомним, что такое ре- гистр состояний и что можно уз- нать с его помощью. Регистр состояний отражает корректность заданной команды, а также состояния микроконтролле- ра при ее выполнении. Каждый бит в нем указывает на определенный параметр и связан с выполнением конкретной команды. При выполне- нии команд восстановления и по- зиционирования биты системного регистра имеют следующее назна- чение: 0 - занято, идет выполнение команды; 1 - индексный импульс; 2 - магнитная головка находится в исходном положении; 3 - ошибка в контрольном коде; 4 - ошибка позиционирования; 5 - магнитная головка находится в рабочем положении; 6 - защита записи; 7 - указывает на готовность дис- ковода к выполнению команды. Нас будут интересовать лишь 1 и 6 биты регистра состояний, поэтому поговорим о них подроб- нее. Если посмотреть на дискету, мы увидим большое отверстие в центре, а рядом с ним - малень- кое круглое отверстие в кор- пусе дискеты и отверстие чуть меньшего диаметра на самом маг- нитном диске. Это так называе- мое индексное отверстие, кото- рое служит для ориентации маг- нитной головки дисковода на дис- кете. Когда отверстия в корпусе и на самом диске совпадают (а это происходит при каждом оборо- те диска), контроллер считает, что магнитная головка находится в начале дорожки. Отмечу, что вероятность случайного совпаде- ния отверстий составляет пример- но 3%. Значение 1-го бита регистра состояний определяется состоя- нием индексного отверстия: ┌───────────────────┬────────────────────┐ │ ситуация │ значение 1-го бита │ ├───────────────────┼────────────────────┤ │Диска нет │ 1 │ ├───────────────────┼────────────────────┤ │Диск есть, │ │ │отверстия в корпусе│ 1 │ │и на самом диске │ │ │совпадают │ │ ├───────────────────┼────────────────────┤ │Диск есть, │ │ │отверстия в корпусе│ 0 │ │и на самом диске │ │ │не совпадают │ │ └───────────────────┴────────────────────┘ Шестой бит системного регис- тра отражает состояние прорези для защиты записи: ┌───────────────────┬────────────────────┐ │ ситуация │ значение 6-го бита │ ├───────────────────┼────────────────────┤ │Диска нет │ 0 │ ├───────────────────┼────────────────────┤ │Диск есть, │ │ │прорезь открыта │ 0 │ ├───────────────────┼────────────────────┤ │Диск есть, │ │ │прорезь закрыта │ 1 │ └───────────────────┴────────────────────┘ Ясно, что если 1-й бит равен 0 или 6-й бит равен 1, диск при- сутствует. Но, во-первых, при наличии диска эти биты могут принимать, вообще говоря, любые значения, а во-вторых, совершен- но неизвестно, закрыта ли двер- ца дисковода. Как же узнать ее состояние? Вспомним, что если она закрыта и двигатель дисково- да вращается, то будет вра- щаться и диск. Если же дверца открыта, диск вращаться не бу- дет. Ну а как определить, вра- щается диск или нет, мы уже знаем - нужно циклически прове- рять значение первого бита ре- гистра состояний. При каждом обороте диска этот бит меняет свое значение с 0 (отверстие на корпусе диска не совпадает с от- верстием на диске) на 1 (отвер- стия совпадают), и далее - опять на 0. Если этот бит не будет ме- нять своего значения - либо в дисководе нет диска, либо дверца открыта. Теперь мы легко можем ука- зать искомый алгоритм: - прочитать значение регистра состояний. Пусть s1 - значение 1-го бита, s2 - значение 6-го бита. - пусть s3=1, если диск вра- щается, и 0, если диск не враща- ется. - определить ситуацию по таб- лице: s1│s2│s3│ Номер ситуации ──┼──┼──┼──────────────── 0│ 0│ 0│ 2 0│ 0│ 1│ 3 0│ 1│ 0│ 2 0│ 1│ 1│ 3 1│ 0│ 0│ 1 1│ 0│ 1│ 3 1│ 1│ 0│ 2 1│ 1│ 1│ 3 Расшифровка номера ситуации: 1 - в дисководе нет диска; 2 - диск есть, но дверца диско- вода не закрыта; 3 - диск есть и дверца дисковода закрыта. Примечание: с вероятностью примерно 3% ситуация (2) может быть распознана как ситуация (1). Ну что же, осталось только привести текст процедуры на ас- семблере: 140. ;*********************************************** ;ПРОЦЕДУРА D_READY ОПРЕДЕЛЯЕТ, ВСТАВЛЕН ЛИ ;ДИСК В ДИСКОВОД И ЗАКРЫТА ЛИ ДВЕРЦА ДИСКОВОДА. ;В РЕГИСТРЕ A ВОЗВРАЩАЕТСЯ ЧИСЛО 1,2 ИЛИ 3, ;ОБОЗНАЧАЮЩЕЕ НОМЕР СИТУАЦИИ: ; ; 1 -в дисководе нет диска; ; 2 -диск есть, но дверца дисковода не ; закрыта; ; 3 -диск есть и дверца дисковода закрыта. ; ; Примечание: с вероятностью примерно 3% ситуация (2) ;может быть распознана как ситуация (1). D_READY XOR A ;УСТАНАВЛИВАЕМ ОДИН И ТОТ ЖЕ LD C,#3F ;НОМЕР ЦИЛИНДРА CALL TO_WG93 ;В РЕГИСТРЕ ДОРОЖКИ LD C,#7F ;И В РЕГИСТРЕ ДАННЫХ. CALL TO_WG93 LD A,#18 ;ПОЗИЦИОНИРОВАНИЕ. ГОЛОВКА НЕ БУДЕТ CALL TO_1F ;ДВИГАТЬСЯ, НО ДВИГАТЕЛЬ ВКЛЮЧИТСЯ. CALL READY ;ЖДЕМ ВЫПОЛНЕНИЯ... CALL STATUS ;ЧИТАЕМ РЕГИСТР СОСТОЯНИЯ. LD B,A ;И СОХРАНЯЕМ В РЕГИСТРЕ B. ;ТЕПЕРЬ ЧИТАЕМ РЕГИСТР СОСТОЯНИЯ В ЦИКЛЕ, ;ЧТОБЫ ОПРЕДЕЛИТЬ, ВРАЩАЕТСЯ ЛИ ДИСК. ;ЕСЛИ #300 РАЗ БУДЕТ СЧИТАНО ОДНО И ТО ЖЕ ;ЗНАЧЕНИЕ, ЗНАЧИТ, ДИСК НЕ ВРАЩАЕТСЯ. ; ; ПРИМЕЧАНИЕ: ЧИСЛО #300 ПОДОБРАНО ОПЫТНЫМ ПУТЕМ, ;ИСХОДЯ ИЗ МАКСИМАЛЬНОГО ВРЕМЕНИ РАБОТЫ ЦИКЛА ;(ЭТО ЧУТЬ БОЛЬШЕ ВРЕМЕНИ ОДНОГО ОБОРОТА ДИСКА, ;ИЛИ3 200ms). ЕСЛИ ПРОЦЕССОР РАБОТАЕТ БЫСТРЕЕ ИЛИ ;ДИСК ВРАЩАЕТСЯ МЕДЛЕННЕЕ, ЧИСЛО НУЖНО УВЕЛИЧИТЬ. LD HL,#300 ;СЧЕТЧИК LOOP_D PUSH HL PUSH BC CALL STATUS POP BC POP HL DEC HL CP B ;СРАВНИВАЕМ СЧИТАННОЕ И РАНЕЕ ПОЛУЧЕННОЕ ЗНАЧЕНИЯ LD A,1 ;ФОРМИРУЕМ 0-Й БИТ РЕГИСТРА A JR NZ,DISK_R ;ЕСЛИ ДИСК КРУТИТСЯ LD A,H OR L JR NZ,LOOP_D ;ПРОДОЛЖАЕМ СЧИТЫВАТЬ ЗНАЧЕНИЕ... ;ФОРМИРУЕМ В РЕГИСТРЕ A БАЙТ С ТАКИМ СОДЕРЖИМЫМ: ; ; БИТ 0: 0-ДИСК НЕ КРУТИТСЯ, 1-КРУТИТСЯ; ; БИТ 1: ТО ЖЕ, ЧТО БЫЛО В 6-М БИТЕ РЕГИСТРА СОСТОЯНИЙ ; БИТ 2: ТО ЖЕ, ЧТО БЫЛО В 1-М БИТЕ РЕГИСТРА СОСТОЯНИЙ ; ;В РЕЗУЛЬТАТЕ В РЕГИСТРЕ A ПОЛУЧАЕМ ЧИСЛО ОТ 0 ДО 7, ;И ДАЛЕЕ ОПРЕДЕЛЯЕМ НОМЕР СИТУАЦИИ ПО ТАБЛИЦЕ. DISK_R BIT 6,B JR Z,READY1 SET 1,A ;УСТАНОВЛЕНО ЗНАЧЕНИЕ 1-ГО БИТА. READY1 BIT 1,B JR Z,READY2 SET 2,A ;В A ПОЛУЧЕНО НУЖНОЕ ЗНАЧЕНИЕ READY2 LD (THIS_B+2),A ;МОДИФИЦИРУЕМ КОМАНДУ ;НО СНАЧАЛА ОТКЛЮЧАЕМ ДИСКОВОД: XOR A ;ЭТИ КОМАНДЫ, CALL TO_1F ;В ПРИНЦИПЕ, LD A,#D0 ;МОЖНО CALL TO_1F ;ВЫБРОСИТЬ. ;ЭТА КОМАНДА СООТВЕТСТВУЕТ LD A,(IX+0)...LD A,(IX+7): LD IX,TABL THIS_B LD A,(IX) ;ПОЛУЧИЛИ НОМЕР СИТУАЦИИ EI RET ;ТАБЛИЦА ДЛЯ ОПРЕДЕЛЕНИЯ НОМЕРА СИТУАЦИИ: TABL DB 2,3,2,3,1,3,2,3 ;*************************************** ;ВСПОМОГАТЕЛЬНЫЕ ПРОЦЕДУРЫ: TO_1F LD C,#1F 140. TO_WG93 LD IX,#2A53 JR TO_DOS READY LD IX,#3EF5 TO_DOS PUSH IX JP #3D2F ;*************************************** ;ПРОЦЕДУРА STATUS ВОЗВРАЩАЕТ СОДЕРЖИМОЕ ;РЕГИСТРА СОСТОЯНИЯ. ;ВХОД: A -СОДЕРЖИМОЕ РЕГИСТРА ДОРОЖКИ, ; B -СОДЕРЖИМОЕ РЕГИСТРА СЕКТОРА, ; КОТОРЫЕ БУДУТ УСТАНОВЛЕНЫ ПОСЛЕ ; ВЫХОДА ИЗ ПРОЦЕДУРЫ. ;ВЫХОД: A -ЗНАЧЕНИЕ, СЧИТАННОЕ ИЗ ПОРТА #1F. ;ПРЕРЫВАНИЯ ПОСЛЕ ВЫХОДА ЗАПРЕЩЕНЫ! STATUS DI LD C,#7F ;A=N ЦИЛИНДРА CALL TO_WG93 ;В РЕГИСТР ДАННЫХ LD (RG_D+1),A ;ДОРОЖКА LD A,B LD (RG_S+1),A ;СЕКТОР ;СОХРАНЯЕМ СОДЕРЖИМОЕ ЯЧЕЕК, КОТОРЫЕ ;МОГУТ БЫТЬ ИСПОРЧЕНЫ: LD A,(#5D0E) LD (ST1+1),A LD A,(#5D0C) LD (ST2+1),A LD A,(#5CB6) LD (ST3+1),A LD A,(#5D1F) LD (ST4+1),A LD A,(#5C3A) LD (ST5+1),A LD A,(#5D17) LD (ST6+1),A LD HL,(#5D1A) LD (ST7+1),HL LD HL,(#5D1C) LD (ST8+1),HL LD HL,(#5CF8) LD (ST9+1),HL ;УСТАНАВЛИВАЕМ СОДЕРЖИМОЕ НЕКОТОРЫХ ;ЯЧЕЕК ДЛЯ ПРАВИЛЬНОЙ РАБОТЫ: LD A,#FF LD (#5D0C),A LD (#5D1F),A DEC A LD (#5D0E),A LD A,#F4 LD (#5CB6),A LD HL,S_SPEC LD (#5D1A),HL LD HL,0 ADD HL,SP LD DE,-12 ADD HL,DE LD (#5D1C),HL LD A,0 ;0 В РЕГИСТР LD C,#3F ;ДОРОЖКИ CALL TO_WG93 LD A,#0A ;#A В РЕГИСТР LD C,#5F ;СЕКТОРА CALL TO_WG93 LD D,1 LD IX,16179 CALL TO_DOS ;ОПРЕДЕЛИЛИ #1F ;ТЕПЕРЬ ВОССТАНАВЛИВАЕМ СОДЕРЖИМОЕ ;РЕГИСТРОВ ДОРОЖКИ И СЕКТОРА: RG_D LD A,0 LD C,#3F CALL TO_WG93 RG_S LD A,0 LD C,#5F CALL TO_WG93 ;ВОССТАНАВЛИВАЕМ РАНЕЕ ЗАПОМНЕННОЕ ;СОДЕРЖИМОЕ ЯЧЕЕК: ST1 LD A,0 LD (#5D0E),A ST2 LD A,0 LD (#5D0C),A ST3 LD A,0 LD (#5CB6),A ST4 LD A,0 LD (#5D1F),A ST5 LD A,0 LD (#5C3A),A ST6 LD A,0 LD (#5D17),A ST7 LD HL,0 LD (#5D1A),HL ST8 LD HL,0 LD (#5D1C),HL ST9 LD HL,0 LD (#5CF8),HL LD A,B RET ;СЮДА БУДЕТ ПЕРЕДАНО УПРАВЛЕНИЕ, ЕСЛИ ;0-Й БИТ РЕГИСТРА СОСТОЯНИЙ РАВЕН 1: S_SPEC POP BC ;СОДЕРЖИМОЕ ПОРТА LD HL,(#5D1C) LD DE,12 ;ВОССТАНАВЛИВАЕМ ADD HL,DE ;УКАЗАТЕЛЬ LD SP,HL ;СТЕКА JR RG_D 2 Вам наверняка встречались программы, контролирующие смену диска в дисководе (например, Jemmini Commander). В них прове- ряются именно указанные выше би- ты системного регистра (в прин- ципе, достаточно следить за из- менением лишь какого-нибудь од- ного из двух битов). Вот прос- тейший алгоритм работы такой программы: Шаг 1: Прочитать значение регис- тра состояний. Если пер- вый бит равен 1, перейти к шагу 4. Шаг 2: N="Диск есть". Шаг 3: Прочитать значение регис- тра состояний. Если пер- вый бит равен 0, перейти к шагу 3. Шаг 4: N="Диска нет". Шаг 5: Прочитать значение регис- тра состояний. Если пер- вый бит равен 1, перейти к шагу 5, иначе к шагу 2. Примечание: программа рабо- тоспособна при условии, что от- верстие на самом диске не совпа- дает с отверстием на корпусе диска (это связано с использова- нием 1-го бита регистра состоя- ний). Кстати, у такой программы есть одна особенность, связан- ная с чтением регистра состоя- ний. Чтобы прочесть его значе- ние, нужно, чтобы двигатель дис- ковода работал. Поэтому ис- пользуется следующий прием: вы- полняется команда позиционирова- ния на дорожку, номер которой уже записан в регистр дорожки. При этом головка не будет дви- гаться, но двигатель дисковода включится. После окончания вы- полнения этой команды читается регистр состояний. Сразу после этого двигатель выключается, например, с помощью записи 0 в порт #FF (или в порт #1F). Меж- ду двумя последовательными чте- ниями регистра состояний делает- ся пауза, обычно 1/50 секунды. При этом двигатель не успевает раскрутиться, и лампочка диско- вода не загорается. Но если вни- мательно присмотреться, видно, что лампочка все же чуть-чуть светится (яркость свечения об- ратно пропорциональна длине пау- зы). Так вот, на некоторых дис- ководах (а именно - на ЕС 5323. 01) было замечено, что при рабо- те программ, контролирующих сме- ну диска, лампочка постоянно го- рит и двигатель работает. Привожу текст небольшой де- монстрационной программы, кон- тролирующей смену диска по вы- шеуказанному алгоритму. Програм- ма выводит на экран сообщения "DISK PRESENT" и "DISK NOT PRE- SENT". Выход - по нажатию любой клавиши (когда диск присутству- ет). 140. CALL 3435 ;CLS LD A,2 CALL 5633 M_1 CALL READ_S BIT 1,A JR NZ,M_4 M_2 LD A,1 LD (N),A LD DE,TEXT1 LD BC,23 CALL 8252 ;"DISK PRESENT" M_3 XOR A IN A,(254) AND 31 CP 31 RET NZ ;ЕСЛИ НАЖАТА КЛАВИША, ВЫХОДИМ CALL READ_S BIT 1,A JR Z,M_3 M_4 XOR A LD (N),A LD DE,TEXT2 LD BC,23 CALL 8252 ;"DISK NOT PRESENT" M_5 CALL READ_S BIT 1,A JR NZ,M_5 JR M_2 N DB 0 ;1-ЕСТЬ ДИСК, 0-НЕТ. TEXT1 DB 22,0,0,16,7,17,0,"DISK PRESENT " TEXT2 DB 22,0,0,16,7,17,0,"DISK NOT PRESENT" ;*************************************** ;ПРОЦЕДУРА READ_S ОСУЩЕСТВЛЯЕТ ЧТЕНИЕ ;РЕГИСТРА СОСТОЯНИЙ. ПЕРЕД ЧТЕНИЕМ ;ПРОИЗВОДИТСЯ ВКЛЮЧЕНИЕ ДВИГАТЕЛЯ ;ДИСКОВОДА, А ПОСЛЕ ЧТЕНИЯ -ВЫКЛЮЧЕНИЕ И ;ПАУЗА В3 1/50 СЕКУНДЫ. READ_S XOR A ;УСТАНАВЛИВАЕМ ОДИН И ТОТ ЖЕ LD C,#3F ;НОМЕР ЦИЛИНДРА CALL TO_WG93 ;В РЕГИСТРЕ ДОРОЖКИ LD C,#7F ;И В РЕГИСТРЕ ДАННЫХ. CALL TO_WG93 LD A,#18 ;ПОЗИЦИОНИРОВАНИЕ. ГОЛОВКА НЕ БУДЕТ CALL TO_1F ;ДВИГАТЬСЯ, НО ДВИГАТЕЛЬ ВКЛЮЧИТСЯ. CALL READY ;ЖДЕМ ВЫПОЛНЕНИЯ... CALL STATUS ;ЧИТАЕМ РЕГИСТР СОСТОЯНИЯ. EI ;РАЗРЕШАЕМ РАНЕЕ ЗАПРЕЩЕННЫЕ ПРЕРЫВАНИЯ PUSH AF XOR A CALL TO_1F ;ВЫКЛЮЧАЕМ ДВИГАТЕЛЬ LD A,#D0 CALL TO_1F HALT 3 ;ЗАДЕРЖКА 1/50 СЕКУНДЫ POP AF RET ;*************************************** ;ВСПОМОГАТЕЛЬНЫЕ ПРОЦЕДУРЫ: TO_1F LD C,#1F TO_WG93 LD IX,#2A53 JR TO_DOS READY LD IX,#3EF5 TO_DOS PUSH IX JP #3D2F ;*************************************** ;ПРОЦЕДУРА STATUS ВОЗВРАЩАЕТ СОДЕРЖИМОЕ ;РЕГИСТРА СОСТОЯНИЯ. ;ВХОД: A -СОДЕРЖИМОЕ РЕГИСТРА ДОРОЖКИ, ; B -СОДЕРЖИМОЕ РЕГИСТРА СЕКТОРА, ; КОТОРЫЕ БУДУТ УСТАНОВЛЕНЫ ПОСЛЕ ; ВЫХОДА ИЗ ПРОЦЕДУРЫ. ;ВЫХОД: A -ЗНАЧЕНИЕ, СЧИТАННОЕ ИЗ ПОРТА #1F. ;ПРЕРЫВАНИЯ ПОСЛЕ ВЫХОДА ЗАПРЕЩЕНЫ! STATUS DI LD C,#7F ;A=N ЦИЛИНДРА CALL TO_WG93 ;В РЕГИСТР ДАННЫХ LD (RG_D+1),A ;ДОРОЖКА LD A,B LD (RG_S+1),A ;СЕКТОР ;СОХРАНЯЕМ СОДЕРЖИМОЕ ЯЧЕЕК, КОТОРЫЕ ;МОГУТ БЫТЬ ИСПОРЧЕНЫ: LD A,(#5D0E) LD (ST1+1),A LD A,(#5D0C) LD (ST2+1),A LD A,(#5CB6) LD (ST3+1),A LD A,(#5D1F) LD (ST4+1),A LD A,(#5C3A) LD (ST5+1),A LD A,(#5D17) LD (ST6+1),A LD HL,(#5D1A) LD (ST7+1),HL LD HL,(#5D1C) LD (ST8+1),HL LD HL,(#5CF8) LD (ST9+1),HL ;УСТАНАВЛИВАЕМ СОДЕРЖИМОЕ НЕКОТОРЫХ ;ЯЧЕЕК ДЛЯ ПРАВИЛЬНОЙ РАБОТЫ: LD A,#FF LD (#5D0C),A LD (#5D1F),A DEC A LD (#5D0E),A LD A,#F4 LD (#5CB6),A LD HL,S_SPEC LD (#5D1A),HL LD HL,0 ADD HL,SP LD DE,-12 ADD HL,DE LD (#5D1C),HL LD A,0 ;0 В РЕГИСТР LD C,#3F ;ДОРОЖКИ CALL TO_WG93 LD A,#0A ;#A В РЕГИСТР LD C,#5F ;СЕКТОРА CALL TO_WG93 LD D,1 LD IX,16179 CALL TO_DOS ;ОПРЕДЕЛИЛИ #1F ;ТЕПЕРЬ ВОССТАНАВЛИВАЕМ СОДЕРЖИМОЕ ;РЕГИСТРОВ ДОРОЖКИ И СЕКТОРА: RG_D LD A,0 LD C,#3F CALL TO_WG93 RG_S LD A,0 LD C,#5F CALL TO_WG93 ;ВОССТАНАВЛИВАЕМ РАНЕЕ ЗАПОМНЕННОЕ ;СОДЕРЖИМОЕ ЯЧЕЕК: ST1 LD A,0 LD (#5D0E),A ST2 LD A,0 LD (#5D0C),A ST3 LD A,0 LD (#5CB6),A ST4 LD A,0 LD (#5D1F),A ST5 LD A,0 LD (#5C3A),A ST6 LD A,0 LD (#5D17),A ST7 LD HL,0 LD (#5D1A),HL ST8 LD HL,0 LD (#5D1C),HL ST9 LD HL,0 LD (#5CF8),HL LD A,B RET ;СЮДА БУДЕТ ПЕРЕДАНО УПРАВЛЕНИЕ, ЕСЛИ ;0-Й БИТ РЕГИСТРА СОСТОЯНИЙ РАВЕН 1: S_SPEC POP BC ;СОДЕРЖИМОЕ ПОРТА LD HL,(#5D1C) LD DE,12 ;ВОССТАНАВЛИВАЕМ ADD HL,DE ;УКАЗАТЕЛЬ LD SP,HL ;СТЕКА JR RG_D * * * 2