Приветствую Вас, дорогие читатели и редак-
торы журнала "Eldorado"! Как здорово, что
у нас в Ярославле наконец-то появился свой
электронный журнал. Конечно ребятам еще
надо поработать над собой, но первые шаги
были явно на уровне. Особенно порадовала
музыка. Ну вот, спасибо сказал, а теперь о
маленькой ошибочке, которая закралась в
первую статью "Система":
Есть:
zag LD С,5
LD DE,(23796)
RET
Должно быть:
zag LD С,5
LD DE,(23796)
JP #3D13
Так же хотелось бы отметить, что приведен-
ная в первом номере "Eldorado" статья
"Система" предназначалась явно для начи-
нающих. А это значит, что необходимо было
толком рассказать, КАК запихать полученный
загрузчик в первую БЕЙСИК-стоку, если TASM
держит там свой резидент! Поработайте.
Лично я эмулирую при помощи DEFB и DEFW
БЕЙСИК-операторы. Могу поделиться.
Теперь по делу. Я, собственно, хотел бы
продолжить тему загрузчиков, и поговорить
об обращении непосредственно к ПЗУ DOS и о
прямом программировании ВГ 93.
Вообще говоря о программировании ВГ 93 и
работе с диском без использования систем-
ных переменных DOS говорилось и писалось
немало. Наиболее подробная, на мой взгляд,
информация публиковалась в третьем издании
книги "ZXSpectrum для пользователей и про-
граммистов" (ZXSpectrum & TR-DOS) Н.Родио-
нова и А.Ларченко. Но изложение информации
в этом, и ему подобных, изданиях несколько
суховато. А листинги подпрограмм ДОС'а или
не даются вообще или не комментируются.
Короче, далее я попытаюсь наиболее доступ-
но и ясно рассказать о ВГ 93 и опираясь на
изложенную информацию рассказать о некото-
рых подпрограммах ДОС'а.
Здесь и далее: ВГ93 - м-ма КР1818ВГ93;
ОС - операционная система (Бейсик и т.п.);
ДОС - дисковая операционная система;
Начнем с того, что ВГ-шка для вас (и для
процессора) - всего лишь несколько портов.
Послал в один порт число, в другой порт
другое число, в третий порт послал код ко-
манды; глядишь - а на дисководе и лампочка
загорелась, и уже диск крутится, а если
что нибудь из четвертого порта почитать,
то может даже что-нибудь да и прочитается.
Следует отметить несколько крайне важных
вещей:
1. ПЗУ ДОС, а вместе с ним и регистры ВГ
(порты) включаются только тогда, когда вы-
полняется какая-либо команда по адресу
#3D00 - #ЗDFF (15616 - 15871). В ПЗУ ОС
там находится знакогенератор и передавать
ему управление просто так еще никто (слава
Богу) не додумался. Отключается же ПЗУ ДОС
(а вместе с ним и порты ВГ9З) при выполне-
нии любой команды по адресу, большему чем
#ЗFFF (16383), то есть в ОЗУ.
2. Из пункта 1. следует, что управлять ВГ
можно только подпрограммами ДОС'а, а чтобы
это сделать необходимо его хорошо изучить.
3. Из пунктов 1. и 2. следует, что обра-
щаться к необходимым нам частям ДОС нужно
каким-то особым, извратным способом. Об
этом мы поговорим несколько позже.
А вот те самые регистры-порты ВГ93:
╔═════════╦═══════════════════╦══════════╗
║ Адрес ║ Название регистра ║ Доступ ║
╠═════════╬═══════════════════╬══════════╣
║#1F (31) ║ Рег. команд ║ Запись ║
║#1F (31) ║ Рег. состояний ║ Чтение ║
║#3F (63) ║ Рег. дорожки ║ Чт./зап. ║
║#5F (95) ║ Рег. сектора ║ Чт./зап. ║
║#7F (127)║ Рег. данных ║ Чт./зап. ║
╚═════════╩═══════════════════╩══════════╝
А это (^) не совсем регистр ВГ, но нам это
без разницы.
╔═════════╦═══════════════════╦══════════╗
║#FF (255)║ Системный регистр ║ Чт./зап. ║
╚═════════╩═══════════════════╩══════════╝
Адрес - номер порта.
Доступ - это что с ним можно делать (чт./
зап. это чтение и запись соответственно).
Напомню, что для нас, в принципе, слова
"порт" и "регистр" являются синонимами.
Регистр команд - в него записывается ко-
манда, понятная ВГ. Принятая команда не-
медленно выполняется. Можно только записы-
вать.
Регистр состояний - отдельные биты этого
регистра указывают на корректность приня-
той команды и т.п. (что-то вроде регистра
F в Z-80). Только чтение.
Регистры дорожки и сектора - указывают на
положение головки дисковода. Являются
входными параметрами для некоторых команд
ВГ. Чтение и запись. Для тех, кто
путается, напомню:
Регистр данных - через него передаются или
принимаются записываемые или считываемые
данные (иногда - вспомогательные). Чтение
и запись.
Системный регистр - при чтении из него
указывает на готовность дисковода принять
или выдать очередной байт, а также на
окончание операции. При записи - системную
информацию (номер дисковода, метод записи
FM/MFM, сторона и т.п.). Подробнее:
При чтении из порта #FF:
╔═════╦══════════════════════════════════╗
║ Бит ║ Назначение ║
╠═════╬══════════════════════════════════╣
║ 0-5 ║ Не представляют интереса ║
║ 6 ║ Запрос данных ║
║ 7 ║ Конец операции ║
╚═════╩══════════════════════════════════╝
При записи:
╔═════╦══════════════════════════════════╗
║ Бит ║ Назначение ║
╠═════╬══════════════════════════════════╣
║ 0-1 ║ Выбор дисковода (00,01,10,11 ║
║ ║ A, В, С, D) ║
║ 2 ║Сброс микроконтроллера (практичес-║
║ ║ки не требуется) ║
║ 3 ║ Блокировка сигнала HLT ВГ. Для ║
║ ║ нормальной работы должна быть 1. ║
║ 4 ║ Выбор головки: 0 - 1-ая, нижняя; ║
║ ║ 1 - 2-ая, верхняя.║
║ 5 ║Метод записи: ║
║ ║0 - FM частотная модуляция ║
║ ║1 - MFM модифицированная частотная║
║ ║модуляция. Обычно пользуются MFM. ║
║ 6-7 ║ Не используются ║
╚═════╩══════════════════════════════════╝
------------------------------------------
Практический интерес для нас на данном
этапе представляет чтение из системного
регистра (порта):
Запрос данных - до тех пор, пока в этом
разряде записан 0, дисковод не готов при-
нять (выдать) очередной байт данных. Ведь
процессор действует намного быстрее, чем
ВГ93 и оба они передают данные гораздо
быстрее, чем дисковод (собачка-то бежит
быстрее человека! Ха-ха).
Конец операции - ну, тут все понятно: 0 в
этом разряде означает, что текущая опера-
ция не завершена. Только следует отметить
один очень интересный момент: при чтении
сектора контроллер САМ определяет, сколько
байт будет считано (не зависимо от того,
хотите вы этого или нет). То же самое и
при записи сектора(ов). Подумайте над этим
моментом, мы еще вернемся к нему.
Поскольку мы с Вами говорим о чтении с
диска при помощи прямого управления ВГ, то
не имеет смысла (пока) рассказывать о всех
командах управления ВГ.
Рассмотрим самые необходимые:
(здесь следует сказать, что у команд ВГ93
нет мнемоник, как у ассемблера, поэтому
просто пишут название команды (группы ко-
манд) и битовую раскладку)
Поиск - 0001hvxx. Эта команда устанавлива-
ет магн. головку на дорожку, номер кото-
рой задан в регистре ДАННЫХ. Предполагает-
ся, что в регистре ДОРОЖКИ находится номер
дорожки, на котором стоит головка. Жела-
тельно (но необязательно) выполнять при
параметре v=1.
h = 0 - во время выполнения команды
головка будет поднята над диском и не
будет выдан сигнал на включение дви-
гателя дисковода;
h = 1 - головка будет опущена в рабо-
чее положение и сигнал на включение
будет выдан.
v - имеет смысл, только при h=1. При
v = 1 значение регистра дорожки срав-
нивается со значением, считанным с
диска.
хх - скорость выполнения операции:
00 - максимальная, 01,10 - промежу-
точные, 11 - минимальная.
Чтение сектора(ов) - 1OOmsecO. Название
говорит само за себя. Номер сектора зада-
ется в регистре СЕКТОРА.
m = 0 - прочитать только один сектор.
m = 1 - все сектора до конца дорожки.
s - сторона дискеты (0-ниж., 1-верх.)
Практического значения не имеет, т.к.
стороной диска занимается СИСТЕМНЫЙ
регистр, но может пригодиться (см.^).
e - если этот бит установлен, то меж-
ду выдачей сигнала на установку голо-
вок в рабочее положение и началом
операции делается задержка в 15 мс.
c - проверять (1) или нет (0) сторо-
ну дискеты при операции (см. параметр
s). Дело в том, что сторона дискеты
записываеся при форматировании, но об
этом мы поговорим в следующий раз.
Это две простейшие операции, опираясь на
которые мы с Вами рассмотрим чтение с дис-
ка.
Вот упрощенный драйвер дисковых операций,
приведенный в ZX-РЕВЮ 4'95 (зачем изобре-
тать велосипед?):
© ALANSOFT'95
SMALL DISK-DRIVER
Слегка переделал Nicolas Viper.
На входе должны быть заданы:
HL = адрес загрузки;
DE = дорожка,сектор;
В = число секторов.
ORG 50000
DRIVER
DI
LD IX,#2F65 ;(12133) Подпрогамма
CALL DOS ;инициализации.
L1 PUSH DE ;Сохраняем DE и ВС.
PUSH ВС ;
OR A ;Переводим из логи-
LD A,D ;ческого номера до-
RRA ;рожки в физический.
LD С,A ;(обсудим позже)
LD A,#3С ;#3С=%00111100
JR NC,L2 ;#2С=%00101100
LD A,#2С ; ^сторона.
;
L2 LD IX,#2FЧD ;Подпрограмма уста-
CALL DOS ;новки на дорожку.
;(12109)
POP ВС ;Восстанавливаем
POP DE ; ВС и DE.
М2 PUSH HL ;Сохраняем
PUSH DE ; регистры.
PUSH ВС ;
LD IX,#2F1В ;{12059) Собственно
CALL DOS ;чтение.
POP ВС ;Восстанавливаем
POP DE ; регистры.
POP HL ;
INC Н ;Поскольку считаем,
;что длина сектора
;256 байт.
INC E ;Следующий сектор.
LD A,15 ;15=%00001111
AND E ;Если E=16, то E=0,
LD E,A ;флаг Z=1 и переход
JR Z,L5 ;на следующую дорож-
DJNZ М2 ;ку, иначе просто
;следующий сектор.
JR EXIT ;На выход.
L5 INC D ;Следующая дорожка.
DJNZ L1 ;
EXIT EI ;
RET ;Выход.
;
DOS ;На стеке - адрес
;возврата.
PUSH IX ;На стеке - адрес
;вызываемой процеду-
;ры.
JP #3D2F ;(1566З) Подключает-
;ся ПЗУ ДОС, а там
находится:
#3D2F NOP
#3D30 RET. По RET управление передает-
ся нужной Вам подпрограмме
ПЗУ ДОС, а она вернется в точку, откуда
вызывали процедуру "DOS".
Перед тем, как разбирать вызываемые нашим
драйвером процедуры ДОС'а, напомню, что
существует два способа нумерации дорожек и
секторов:
1. Логический. К нему мы с Вами привыкли.
Дорожки нумеруются от нуля и до 159.
Сектора нумеруются: 0..15
2. Физический. Дорожки нумеруются: 0..79,
но на каждой стороне. Нулевая логическая -
это нулевая верхняя физическая, первая ло-
гич. это нулевая верхняя и т.д.. Сектора
нумеруются: 1..16. Такой способ наиболее
понятен ВГ и Вашему флоппи-диск-кранчеру
(шутка).
А вот и процедурки ДОС'а:
#2F65 Сброс (восстановление) контроллера.
Обязательно обращаться в начале работы!
Ничего интересного. Если захотите, то я
расскажу о ней в следующих публикациях.
#2FЧD Установка на дорожку:
Входные параметры в регистрах :
A - Системная информация. Обычно #3С или
#2С, что соответствует:
#3С - А,?,разрешен HLT,верхняя головка,MFM
#2С - то же, но с нижней головкой. Подроб-
нее смотрите в описании системного р-ра.
С - Физический номер дорожки.
В регистре дорожки - номер дорожки, на
которой стоит головка.
#2FЧD OUT (#FF),A ;установка системной
;информации. Исполь-
;зуется для установ-
;ки стороны диска.
LD A,С ;В рег. данных номер
OUT (#7F),A ;нужной дорожки.
CALL #ЗDFD ;Задержка
LD A,#18 ;#18=%00011000 Ко-
OUT (#1F),A ;манда "Поиск".
М1 IN A,(#FF) ;Ждем, пока команда
AND #80 ;исполняется.
JR Z,М1 ;#80=%10000000
PUSH ВС ;
CALL #ЗDFD ;Еще одна задержка.
POP ВС ;
RET ;Возврат
------------------------------------------
#ЗDFD LD A,#50 ;Подпрограмма
W1 LD С,#FF ;задержки.
W2 DEC С ;
JR NZ,W2 ;
DEC A ;
JR NZ,W1 ;
RET ;Возврат
#2F1В Чтение дорожки.
Входные параметры:
E - логический номер сектора.
HL - адрес загрузки.
Предполагается, что головка установлена на
ту дорожку, с которой необходимо читать.
#2F1В LD A,E ;Был логический -
INC A ;стал физический.
OUT (#5F),A ;Посылаем в регистр
;сектора
PUSH HL ;
LD D,#14 ;#14=20 Сколько раз
;повторять, в случае
PUSH DE ;ошибки.Сохраняем.
L1 DI ;Запрет прерываний!
LD С,#7F ;Адрес р-ра данных.
LD A,#80 ;#80=%10000000 Ко-
OUT (#1F),A ;манда "чтение".
CALL #ЗFE5 ;Собственно чтение.
POP DE ;Восстанавливаем ре-
POP HL ;гистры.
IN A,(#1F) ;Проверка на ошибку.
AND #7F ;#7F=%01111111
RET Z ;Возврат, если окей.
DEC D ;Уменьшаем счетчик.
PUSH HL ;
PUSH DE ;
JR NZ,L1 ;Повтор, если D<>0.
#2F39 HALT ;Повись!
#2FЗA ... ;
;
... ;
;
#ЗFE5 IN A,(#FF) ;Ожидаем разрешения.
AND #С0 ;#С0=%11000000
JR Z,#ЗFE5 ;
RET М ;Возврат, если конец
;См. таблицу по Сис-
;темному р-ру. Флаг
;S дублирует старший
;разряд р-ра.
INI ;Читаем.
;INI=IN (HL),(С)
; INC HL
JR #ЗFE5 ;Зацикливание.
Вот и все. Надеюсь вы поняли большую часть
изложенного материала. Если хотите продол-
жения, то сообщите об этом в редакцию "El-
dorado" или Condor soft'у лично. А я бы
вам рассказал о записи (без исп. сист. пе-
ременных ДОС'а), о том, как сделать музыку
во время загрузки (см. "BATLE СOMMAND",
"BLINKY'S", "INSULT") и еще о чем-нибудь.
В статье использовался материал книги
А.Ларченко и Н.Родионова
"ZX Specrtum & TR DOS для пользователей и
программистов" издательства "ПИТЕР" 1994г.
Это издание - лучшая настольная книга для
программиста и пользователя.
И на последок: большое человеческое спаси-
бо сэру Клайву Синклеру за машину, которая
научила нас радости программирования.
© 1995 Nicolas Viper
Other articles: