Орион-Про/OS-DOS/Руководство системного программиста

Материал из Emuverse
Данный материал защищён авторскими правами!

Использование материала заявлено как добросовестное, исключительно для образовательных некоммерческих целей.

Автор: © 1993,1995 ORIONSOFT, В.П.Сугоняко

Операционная система (ОС) СР/М-80 (Control Program for Microcomputers) была разработана в 1977 г фирмой DIGITAL RESEARCH Inc. первоначально для компьютера MDS800 фирмы INTEL, а затем стала самой популярной для 8-разрядных микропроцессоров I8080 и Zilog Z80. В отличие от других операционных систем CP/M имеет небольшой набор стандартных и быстро осваиваемых непрофессиональными пользователями директив, легко адаптируется под компьютер любой конфигурации, и занимает минимальным объемом ОЗУ. Благодаря этому она стала стандартом для восьмиразрядных микрокомпьютеров.

Для ОС СР/М было написано несколько десятков тысяч пакетов программ, в том числе трансляторы, практически, всех языков высокого уровня, электронные таблицы и базы данных. Первые версии популярных сейчас программ Lotus 1-2-3, Frame Work, Dbase и др. появились еще под СР/М.

Наибольшее распространение получили версии СР/М — 1.4, 2.2, 3.0 и 3.0+. Версия 2.2 появилась в 1979 г. и значительно превосходила своих предшественниц, в частности поддерживала файлы объемом до 8 Мбайт (вместо 512 Кбайт) и имела вдвое увеличенное количество системных функций (средства прямого доступа к файлам и т. д.), а также значительно более усиленный набор системных утилит (загружаемых директив).

СР/М, версии 2.2, используется на отечественных ЭВМ СМ1800, СО-05 и ПК8020 («Корвет»), а версия 3.0, под именем «SCP», адаптирована на компьютере «Роботрон-1715».

ОС состоит из 3-х модулей — ССР, BDOS и BIOS. При установке СР/М на компьютер адаптации подлежит лишь модуль BIOS, выполняющий дисковые операции и операции ввода/вывода самого низкого уровня (т.е управление непосредственно «железом»). От того насколько удачно написан BIOS во многом зависит удобство пользования компьютером и программная совместимость. В нашем случае сложность адаптации BIOS заключалась в том, что первоначально он предназначался для управления аппаратными интерфейсными устройствами — дисплей (с аппаратным курсором), клавиатура и другие устройства ввода/вывода. В компьютерах «Корвет» и «Ори-он-128» аппаратные функции этих устройств реализованы программно, поэтому при адаптации ОС потребовалось применять всевозможные программные ухищрения.

В качестве базового шаблона при адаптации СР/М на «Орион-128» использован BIOS ПК «Корвет», расчитанный на БИС КР1818ВГ93. О том как устроен контроллер, как его собрать и отладить, а так же тест-программы и холодный загрузчик приведены в журнале «Радиолюбитель» NN 5-7 за 1993 г.

Авторская реализация СР/М для ПК «Орион-128» названа «OS-DOS» — ORIONSOFT Disk Operating System". Разработаны «OS-DOS48K» — для работы в ОЗУ страницы 0 и «OS-DOS60K» — для работы в странице 1. Соответсвенно присвоены версии X.4X и X.6X (более ранние — 2.4X, 2.6X).

В этой статье мы раскроем многие тайны OS-DOS, расскажем о том, как устроен BOOT-сектор (и что это такое), как пользовться функциями BDOS и векторов BIOS.

ВООТ-сектор

Напомним, как происходит процесс загрузки операционной системы в память компьютера. «Холодный» загрузчик LDOS$ [1] считывает первый сектор (1 Кбайт) нулевой дорожки дискеты в свой внутренный буфер. Затем первые 256 байт переносит в область 00-0FFH и передает управление по адресу 0000Н. Считывание сектора напрямую по адресу 0000Н (как это делается для простоты в реализациях других авторов) делает, практически, бесполезной директиву ССР — SAVE, так как уничтожает полезную информацию в области ТРА (области размещения пользовательских программ).

Размещение информации в области 00-0FFH (эта область является служебной при работе OS-DOS и не может быть затерта программами пользователя) приведено в дампе в таблице 1. Она состоит из набора служебных ячеек, констант и вторичного загрузчика. Вторичный загрузчик как раз и «знает», как загрузить и разместить СР/М в памяти компьютера. Такая двухступенчатая система загрузки позволяет иметь один на все случаи «холодный» загрузчик и применительно к загружаемой программе (не обязательно OS-DOS) — «свой», специализированный вторичный загрузчик.

                                                    Таблица 1
     0 1  2 3	4 5  6 7  8 9  А B  C D  E F
0000 C330 0000 0000 0000 0101 0301 0500 5000 .0............P.
0010 2800 040F 0084 017F 00C0 0020 0004 00D7 (.......... ....
0020 4F52 494F 4E20 3132 382E 3200 9D00 AC00 ORION 128.2.....
0030 3100 012A 2B00 3A0A 00FE 023E 5001 050E 1..*+.:....>P...
0040 CA48 003E 3001 0307 3208 0032 14F7 CDC2 .H.>0...2..2....
0050 00C3 5F00 3208 0032 14F7 CDC2 000E 0179 .._.2..2.......y
0060 3212 F73E 84CD A500 C5D5 CDAF 001A E6DD 2..>............
0070 C200 F8D1 C105 C27D 002A 2D00 E90C 3E06 .......}.*-...>.
0080 B9C2 5F00 1DCA 9300 3A08 00E6 EF32 14F7 .._.....:....2..
0090 C35D 003E 58CD A500 3A10 F70F DA98 003A .].>X...:......:
00A0 0800 C354 0032 10F7 3E0F 3DC2 AA00 C911 ...T.2..>.=.....
00B0 10F7 0113 F71A 1FD0 1FD2 B500 0A77 23C3 .............w#.
00C0 B500 3A0B 00B7 1E01 C81E 02C9 2020 2020 ..:.........    
00D0 4F52 494F 4E53 4F46 5420 2D20 2020 2020 ORIONSOFT -     
00E0 2020 2073 7567 6F6E 716B 6F20 772E 702E	 СУГОНЯКО В.П.
00F0 0000 0000 0000 0000 0000 0000 0000 0000  ................

Разберем более подробно назначение служебных ячеек и констант. По адресу 0000-0002 находится вектор перехода на дополнительный загрузчик. Наличие байта 0С3Н по адресу 0000Н указывает LDOS$ на то, что данная дискета содержит операционную систему. В противном случае (после процесса форматирования) там находится байт 0Е5Н и «холодный» загрузчик не передает управление дополнительному, а выводится сообщение «NON-SYSTEM DISK».

Далее. 0003-0007 — ячейки, используемые самой OS-DOS. По адресу 0007-001F находится информация описывающая структуру (или стандарт) дискеты: сколько дорожек, сторон, плотность записи и другую служебную информацию. Она формируется и записывается программой FORMAT.COM, применительно к тому режиму, в котором происходил процес форматирования дискеты. В наследство от «Корвета», некоторые «фирмы» пытаются всучить «Ориону» все многообразие этих «стандартов». Дискета: одно-двухсторонняя, 80-40 дорожек, одинарная — двойная плотность. Авторы поддерживают (и мы просим это делать пользователей ПК «Орион-128») только вариант: 80 дорожек, две стороны, двойная плотность. Это позволит получить максимальную полезную емкость дискеты и иметь единый «стандарт» для ПК «Орион-128», что избавит от проблем при распространении программ.

В ячейках 0020Н-002А размещается имя дискеты. Программа форматирования дискет FORMAT.COM, распространявшаяся с OS-DOS V2.3X, заносит в эти ячейки имя «ОРИОН-128.2». Начиная с OS-DOS V2.4X (2.6X) имя дискеты выводится перед выводом каталога дискеты командой DIR. Устанавливается имя в программе FORMAT-.COM или SYS.COM (конечно соответствующей версии).

По адресу 002В-002СН находится адрес размещения OS-DOS в ОЗУ при считывании ее со второго сектора (напомним: первый сектор, где размещался ВООТ-сектор и начало ССР мы считали в служебный буфер «холодного» загрузчика) и далее. Управление считанной операционной системе передается по адресу, находящемуся в ячейках 002D-002Е. Это адрес входа в вектор BIOS для «холодного» перезапуска OS-DOS, то есть производится повторное считывание ССР и BDOS с дискеты BIOSoм. Этим компенсируются потери части ССР при первичном считывании ОС загрузчиком LDOS$.

Ячейка 002FH — флаговая. Ее значение указывает на страницу (банк) загрузки OS-DOS. Флаг используется вторичным загрузчиком. 00 — указывает на основную страницу загрузки OS-DOS — VX.4X, 01 — загрузка в страницу 1 — OS-DOS VX.6X и т. д.

Начиная с адреса 0030Н по 00СВН находится вторичный загрузчик. После выполнения своих функций (считывание и запуск OS--DOS) он затирается. На его месте операционная система размещает свои служебные буферы.

Следует сказать, что построенный авторами по такой схеме ВООТ-сектор не требует изменений при применении его как для OS--DOS48K (размещается в основной памяти компьютера - V2.30, 2.31,2.40,2.41), так и для OS-DOS60K (размещается в дополнительной странице 1-3 — V2.60,2.61). Это же относится и к V3.60. Модификации подвергаются только две пары ячеек — 002В-002С и 002D-002Е. Для OS-DOS60К они имею следующие значение: 0CB00Н и 0DA00Н соответственно.

В процессе работы OS-DOS ячейки по адресу 0000-0007Н имеют следующее назначение:

0000-0002Н — вектор перехода в BIOS на перезагрузку OS-DOS («горячий старт»). По этому адресу передается управление после окончания выполнения пользовательской программы. При этом происходит восстанавлеие CCP и BDOS, если они были затерты.

0003Н — байт назначения логических устройств (БНЛУ)

Байт переназначения логических устройств делится на четыре поля (A,B,C,D) по два бита. Каждое поле определяет текущее назначение устройств.

      A    B	 C    D
   ---------------------
    D7D6 D5D4 D3D2 D1D0
   ---------------------
    LST  PUN  RDR  CON 
   LST - Устройство печати
   PUN - Устройство вывода данных (перфоратор)
   RDR - Устройства ввода данных (перфосчитыватель)
   CON - Консоль (дисплей-вывод, клавиатура-ввод) 

В OS-DOS для «Orion-PRO» каналы PUN и RDR используются для порта COM1 — интерфейс сети.

    A(D7-D6)	    B(D5-D4)	   B(D5-D4)	  D(D1-D0)
    --------	    --------	   --------	  --------
   /00 - TTY	   /00 - TTY	  /00 - TTY	 /00 - TTY
LST 01 - CRT	PUN 01 - PTP   RDR 01 - PRT   CON 01 - CRT
    10 - LPT	    10 - UP1	   10 - UR1	  10 - BAT
   \11 - UL1	   \11 - UP2	  \11 - UR2	 \11 - UC1 

   TTY - Низкоскоростная консоль (телетайп)
   CRT - Высокоскоростная консоль (дисплей)
   BAT - Устройство пакетной обработки
   UC1 - Консоль, определенная пользователем
   PTR - Устройство чтения с перфоленты
   UR1 - Устр.ввода N1, определенное пользователем
   UR2 - Устр.ввода N2, определенное пользователем
   PTP - Устр.вывода на перфоленту
   UP1 - Устр.вывода N1, определенное пользователем
   UP2 - Устр.вывода N2, определенное пользователем
   LPT - Построчно печатающее устройство
   UL1 - Дополнительное печатающее устройство 

Приведенная информация взята из фирменного руководства по СР/М-80 DIGITAL RESEARCH INC. и носит, скорее, просветительный характер. Известные реализации BIOS для СР/М ПК «Орион-128» (в том числе и авторский — OS-DOS) не предусматривают переключение логических устройств. Для этого они должны иметь программы--драйверы в теле BIOS. BDOS не оперируют ячейкой 0003Н, за исключение функций 7 и 8 которые только читают БНЛУ или заносят в него новое значение. Поэтому команды программы STAT-.COM, оперирующие переназначением логических устройств, так же изменяют лишь значение ячейки 0003Н и поэтому безполезны (пока!). OS-DOS при «холодном старте» в байт 0003Н заносит значение 00.

0004Н — номер текущего диска

0005-0007Н — вектор входа в BDOS для вызова функции на выполнение. Для этого предварительно подготавливается состояние регистров, затем вызывается функция, как подпрограмма по адресу 0005Н (CALL 5).

BIOS. Таблица векторов

Вход в BIOS (BASIC INPUT/OUTPUT SYSTEM) осуществляется через таблицу векторов. Она размещается в начале модуля BIOS. Таблица векторов состоит из 17 входов на подпрограммы, выполняющих функции управления и взаимодействия с «железом» компьютера. Некоторые из этих векторов могут быть «пустыми» для определенных функций (к примеру, содержать только команду RET — READER, PUNCH и др.), но вход в таблице векторов должен присутствовать.

Таблица входов векторов

Bas + 00H  JMP  BOOT	   ; "Холодный" старт системы
      03H  JMP  WBOOT	   ; "Горячий" старт системы
      06H  JMP  CONST	   ; Статус клавиатуры
      09H  JMP  CONIN	   ; Ввод символа с клавиатуры
      0CH  JMP  CONOUT    ; Вывод символа на дисплей
      0FH  JMP  LIST	   ; Вывод символа на принтер
      12H  JMP  PUNCH	   ; Вывод на перфоленту
      15H  JMP  READER    ; Ввод с перфоленты
      18H  JMP  HOME	   ; Установка дорожки 0 на
                          ; выбранном диске
      1BH  JMP  SELDSK    ; Выбор диска (0,1,2)
      1EH  JMP  SETTRK    ; Уст.номера дорожки (0-79)
      21H  JMP  SETSEC    ; Уст.номера сектора (1-10)
      24H  JMP  SETDMA    ; Уст.адреса буфера обмена
      27H  JMP  READ	   ; Чтение выбранного сектора
      2АH  JMP  WRITE	   ; Запись выбранного сектор
      2DH  JMP  LISTST    ; Статус состояния принтера
      30H  JMP  SECTRAN   ; Перенумерация секторов 

Значение BAS — это адрес начала размещения BIOS в памяти компьютера. Его следует считывать с ячеек по адресу 0001-0002Н. Для OS-DOS48K — 0AC00H, для OS-DOS60K — 0DA00H.

Таблица векторов по функциональному назначению делится на три основные группы:

  • реинициализация системы (BOOT и WBOOT)
  • ввод-вывод байтовой информации (CONST,CONIN, CONOUT,LIST,PUNCH,READER и LISTST)
  • блочный ввод-вывод для обмена с диском (HOME, SELDSK, SETTRK, SETSEK, SETDMA, READ, WRITE и SECTRAN)

Рассмотрим более подробно функциональные особенности векторов BIOS.

BOOT - Получает управление от вторичного загрузчика системы и выполняет инициализацию, включая выдачу сообщения о запуске OS-DOS. После инициализации параметров системы, вполнения файла AUTOEXEC.BAT (если он есть на загрузочной дискете) управление передает в модуль CCP для дальнейшей работы, установив текущим дисковод «А».

WBOOT — Получает управление, когда необходима (если затерты BDOS и CCP) перезагрузка системы. «Теплый старт» системы происходит и при передаче управление программой пользователя в ячейку с адресом 0000Н (стандартный способ окончания программ пользователя в среде CР/М) или вводе CTRL/C. При этом производится загрузка в память компьютера с системных дорожек диска — ССР и BDOS. По завершении инициализации WBOOT передает управление в ССР. Устанавливается номер текущего дисковода, инициализированный до рестарта системы.

CONST — Производит опрос активности клавиатуры и возвращает в регистре «А» — 0FFН, если клавиша клавиатуры нажата, или 00Н в противном случае. По выполняемой функции аналогична подпрограмме STAT (0F812Н) Мониора.

CONIN — Считывает символ с клавиатуры, ожидая факт нажатия клавиши. Результат возвращается в регистре «А». По выполняемой функции аналогична подпрограмме KBRD (0F803Н) Монитора.

CONOUT — Выводит символ из регистра «С» на экран дисплея По выполняемой функкции аналогична подпрограмме TVC (0F809Н) Монитора.

LIST - Выводит символ из регистра «С» на принтер. В теле BIOS OS-DOS драйвер принтера не содержится и загружается в виде СОМ-файла пользователем (DPRINT.COM).

PUNCH — Выводит байт на перфоратор. В реализации, ранее перечисленных версий OS-DOS фирмы «Орионсофт» вектор не используется. Установлена «заглушка».

READER — Считывает байт с перфосчитывателя. В реализации, ранее перечисленных версий OS-DOS вектор так же не используется. Установлена «заглушка».

HOME - Помещает считывающую головку выбранного диско-вода в исходное состояние, то есть на дорожку с номером «00». Можно использовать подпрограмму SETTRK с параметром равным 00H.

SELDSK — Выбирает дисковод, номер которого задается в регистре «C». Это необходимо для последующих операций чтения-/записи (C=0 — выбирается дисковод «А», C=1 — дисковод «B»). При каждом вызове подпрограмма SELDSK должна возвращать в регистровой паре HL адрес таблицы описания диска (DISK PARAMETER HEADER). Если делается попытка выбора несуществующего дисковода, то HL=0000H.

SETTRK — Выбирает дорожку на диске по содержимому регистра С (номер дорожки не должен привышать 79).

SETSEC — Выбирает сектор на выбранной дорожке по содержимому регистра C.

SETDMA — Устанавливает адрес буфера обмена, в который по регистру ВС, будет считана одна запись (128 байт) в память компьютера. По умолчанию устанавливается буфер по адресу 0080Н.

READ - Подпрограмма считывает одну запись с диска в память компьютера, начиная с адреса, установленного в последней операции SETDMA и заканчивая этим адресом + 128 байт. подпрограмма Предварительно устанавливают SETTRK, SETSEC. В регистре «А» возвращает следующие параметры:

  • А = 00 — нет ошибок
  • А > 0 — ошибка при считывании сектора

WRITE - Подпрограмма записывает одну запись из памяти компьютера (с адреса, определенного в последней операции SETDMA, размером в 128 байт) на выбранный сектор, выбранной дорожки, выбранного диска (операции SETSEC,SETTRK SETDSK). Возвращает параметры аналогичные команде READ.

Следует уточнить, что подпрограммы READ и WRITE предварительно вычисляют: в каком секторе, какой дорожки находится искомая запись. Затем производят считывание/запись сектора (1 Кбайт) и найденную запись (128 байт) переносят в буфер обмена по адресу, установленному в SETDMA.

Такая двойная «бухгалтерия» происходит из-за того, что в былые времена сектор имел размер в 128 байт и назывался - запись. Дорожки на дискете размещались с одной стороны и содержали по 40 секторов.

В настоящее время современные дисководы имеют более высокие плотности записи на дискету. Чтобы реализовать это достижение, пришлось изменить структуру дорожки — сделать меньше количество секторов — 5, а размер их увеличить до одного килобайта. Это уменьшило количество служебной информации на дорожке и резко повысило объем полезной.

Но BDOS остался без изменений и оперирует по «старинке» записями по 128 байт. Пришлось на BIOS возложить функции «бухгалтера».

LISTST — Производит опрос статуса состояния (готов/не готов) принтера. Подпрограмма в теле BIOS не содержится и загружается совместно с подпрограммой вывода символа на принтер — DPRINT.COM. При готовности принтера - возвращает врегистре «А» = 00Н, при неготовности А=FF.

SECTRAN — Осуществляет преобразование логического номера записи в физический сектор на диске. Изначально задумано для убыстрения доступа к информации на диске, за счет использования принципа чередования секторов на дорожке. Однако это было актуально в то время, когда размер записи и сектора равнялся 128 байтам. В настоящее время, в реализации современного BIOS (в том числе и для «Орион-128») данный вектор из-за двойной «бухгалтерии» утратил актуальность и не используется. Тем не менее по запросу BDOS он эмулирует свои функции.

Некоторые особенности в использовании векторов.

  • условием конца текстового файла в OS-DOS является включение в файл кода 1AН (или CTRL/Z).
  • периферийные устройства воспринимаются OS-DOS как «логические» устройства и соотносятся на физические — только посредством модуля BIOS.
  • обмен с диском всегда осуществляется с помощью вызова подпрограмм доступа к диску. Предварительно с помощью дополни тельных векторов выбирают номер диска, дорожку, сектор на дорожке и устанавливают адрес размещения считанной информации. После того как эти параметры установлены, осуществляется обращение к функциям READ или WRITE для выполнения собственно операции чтения/записи сектора. Выполняется несколько попыток (обычно 5-6) прежде, чем возвращается признак ошибочного завершения операции.

BDOS. Системные функции

Системные функции BDOS доступны пользователю только на логическом уровне ввода/вывода информации на диск и осуществляются через буфер обмена. Системный буфер обмена (по умолчанию) располагается по адресу 0080Н. Этот адрес может быть изменен функцией «Установить адрес буфера обмена» (Функция 26).

Операции с каталогом выполняются в резервном буфере, расположенном в теле BIOS, и не оказывают влияния на буфер обмена, за исключением функции «Поиск первого» и «Поиск следующего».

Функция 0. Процедура «горячий старт».
           Вход: Регистр С=00Н

Процедура «горячий старт» загружает в память компьютера модули ССР и BDOS СР/М. Управление передается ССР, при этом активным становится диск «А». Действие функции эквивалентно переходу по адресу 0000Н.

Функция 1. Консольный ввод.
           Вход: Регистр С=01Н
           Выход: Регистр А= код символа

Функция вводит с клавиатуры символ и возвращает его программе в регистр «А».

Отображаемые символы и управляющие — CR (Возврат каретки), LF (Перевод строки), BSP (Забой) выводятся с эхом на экран. Ввод управляющего символа CTRL/I (ТАВ) перемещает курсор на 8 позиций вправо. Осуществляется проверка на включение или выключение режима параллельной печати — CTRL/P (если загружен драйвер обслуживания принтера) и останов/пуск вывода информации на экран — CTRL/S. Функция находится в режиме ожидания до тех пор, пока не будет повторно нажата клавиша.

Функция 2. Вывод символа на консоль.
           Вход: Регистр С=02Н
           Выход: Регистр Е= код выводимого символа

Заданный в регистре «Е» символ (в пределах таблицы ASCII) выводится на экран дисплея. Аналогично функции 1 осуществляется проверка в наличии управляющих символов CTRL/I, CTRL/S, CTRL/P и др.

Функция 3. Ввод символа с логического устройства READER - перфосчитывателя.
           Вход: Регистр С=03Н
           Выход: Регистр А= код введенного символа

В разработанных авторами до настоящего версиях OS-DOS функция не выполняется и имеет «заглушку» на уровне вектора BIOS. Запланировано функции 3 и 4 переопределить для драйверов работы с сетью.

Функция 4. Вывод символа на логическое устройство PUSCH - перфоратор.
           Вход: Регистр С=04Н
           Регистр Е= код выводимого символа

Также как и функция 3 не выполняется и имеет «заглушку» на уровне вектора BIOS.

Функция 5. Вывод символа на логическое устройство LIST - принтер
           Вход: Регистр С=05Н
                 Регистр Е= код выводимого символа

До загрузки внешнего драйвера обслуживания принтера функция не выполняется и имеет «заглушку» на уровне вектора BIOS.

Функция 6. Ввод/вывод символа с консоли без эха (без отображения на дисплее).
           Вход: Регистр С=06Н
           Регистр Е= 0FFH или 0FEH          - при вводе
                   E= код выводимого символа - при выводе
           Выход: Регистр А= введенный символ или статус консоли

Если в регистре «Е» задано 0FFH (ввод символа без эха/опрос статуса), то в регистре «А» возвращается:

  • 00Н, если консоль не готова к вводу символа;
  • введенный символ при готовности консоли.

Если в регистре «Е» задано 0FEH (только опрос статуса), то в регистре «А» возвращается:

  • 00Н, если консоль не готова;
  • ненулевое значение при готовности консоли.

Если в регистре «Е» задан код, отличный от 0FFH или 0FEH, педполагается, что это код выводимого символа. Проверка на наличие, ранее указанных управляющих символов, не производится.

Функция 7. Получить байт назначения устройств (БНУ)
           Вход: Регистр С=07Н
           Выход: Регистр А= значение БНУ

Функция 8. Установка байта назначения устройств
           Вход: Регистр С=08Н
           Регистр Е= новое значения БНУ

Функция 9. Вывод символьной строки
           Вход: Регистр  С= 09Н

Регистр DЕ= адрес выводимой строки Эта функция выводит на консоль символьную строку, находящуюся по адресу, указанному в DE. Строка должна заканчиваться символом «$», который сам не выводится, а является признаком конца строки. При выполнении этой функции осуществляется проверка на управляющие символы CTRL/S, CTRL/P, CTRL/I.

Функция 10. Чтение в консольный буфер
            Вход: Регистр  С=0АН
                  Регистр DЕ= адрес буфера
            Выход: Введенные символы в консольном буфере

Эта функция читает набираемую на консоли последовательность символов (строку) в буфер по адресу, указанному в регистровой паре DE.

Буфер для чтения имеет следующий формат:

     DE:
     ..............................................
     : MX : NC : C1 : C2 : Cn	.  .  .  .  .  ????:
     :....:....:....:....:........................:

 Где
   «МХ»   - максимальное число символов, которые могут быть
            введены в данный буфер (задается программой
            пользователя от 1 до 255);
   «NC»   - число записанных символов в буфер, производится
            самой функцией.
 С1,С2... - символы, прочитанные с консоли. Символы «?»
            изображают неинициализированный остаток буфера.

Выход из функции происходит:

  • при вводе управляющего символа CR или LF.
  • при вводе максимального числа символов.

В процессе записи набираемой строки содержимое буфера может быть отредактировано путем ввода следующих управляющих сиволов:

  • CTRL/C — вызов процедуры «горячий старт» (если CTRL/C в начале строки);
  • CTRL/Е — ввод следующего символа с новой строки на экране CTRL/Р — включение/выключение режима параллельной печати;
  • CTRL/R — вывод обновленного (отредактированного) содержимого буфера;
  • CTRL/U — стирание буфера и перевод строки на экране (стертые символы сохраняются на экране);
  • ЗАБОЙ — стирание последнего символа в буфере и дублирование его на экране;
  • CTRL/Х — стирание буфера и введенной строки на экране.

Курсор возвращается в ту позицию строки, в которой был окончен запрос на ввод в буфер.

Функция 11. Опрос статуса консоли (клавиатуры)
            Вход: Регистр С=0ВН
            Регистр А= статус консоли

Функция опроса статуса консоли позволяет проверить факт ввода символа с клавиатуры. Если символ введен, в регистре «А» возвращается значение 01Н. В противном случае — А=00Н.

Функция 12. Запрос номера версии системы
            Вход: Регистр С=0СН
            Регистр HL= номер версии - 0022Н = СРМ 2.2

Функция 13. Сброс всех дисководов
            Вход: Регистр С=0DН

Применяется при замене дискеты без «теплого старта» (CTRL/C), который приводит к прерыванию программы. Смена дискеты без «теплого старта» или выполнения функции 13 приводит к ошибке ввода/вывода, а в некоторых случаях к порче каталога дискеты. После выполнения функции активным становится дисковод «А», при этом со всех дисководов снимается статус «R/O» (см.функцию 28), текущий адрес буфера обмена (DMA) равен 0080Н.

Функция 14. Активизировать диск
            Вход: Регистр  С= 0ЕН
            Регистр  Е= номер диска (0-диск «А», 1-диск «В», 2-диск «С»)

После активизации диск считается установленным до следующего «холодного/горячего старта» или «сброс дисков» (функция 13). Дальнейшие файловые операции будут производиться с активизированным диском, если номер диска в буфере FCB равен нулю. Номера дисков 1 и 2 в буфере FCB ссылаются соответственно на диски А и В.

Если установленный диск заменяется в процесс работы, то он автоматически переводится в режим «R/O» (только чтение).

Функция 15. Открытие файла
            Вход: Регистр  С=0FН
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= индекс описателя

Функция используется для записи в буфер информации о размещении заданного файла. Перед обращением программист должен заполнить с 0 по 12 байт буфера FCB. При выполнении функции информация из описателя каталога копируется в соответствующие байты буфера FCB, а регистре «А» возвращается индекс найденного описателя.

Если совпадающий описатель не найден (а проще — имя в каталоге), то в регистре «А» возвращается 0FFH.

Таким образом открытие файла обеспечивает доступ к нему для всех операций. При последовательном обращении к файлу, поле текущего номера записи (байт 32 буфера FCB) должно содержать 0.

Функция 16. Закрытие файла
            Вход: Регистр  С=10Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= индекс описателя

Функция осуществляет запись текущей информации из буфера FCB в соответствующий описатель файла в каталоге диска. При успешном завершении операции в регистре «А» возвращается индекс описателя в записи каталога. В противном случае А=0FFH.

При выполнении только операции чтения закрывать файл необязательно. Если использовалась операция записи в файл, то выполнение функции «Закрытие файла» обязательно для занесения полной информации о файле в каталог диска.

Функция 17. Поиск первого
            Вход: Регистр  С=11Н
            Регистр DЕ= Адрес буфера FCB
            Выход:Регистр  А= индекс описателя

Функция осуществляет поиск в каталоге заданного диска первого описателя, соответствующего заданному в буфере FCB. Если такой описатель найден, то в регистре «А» возвращается его индекс, а в буфере обмена (по DMA) — запись каталога, содержащая найденный описатель. Таким образом относительный начальный адрес найденного описателя в буфере обмена будет равен А*32. Если соответствующий описатель не найден, то в регистре «А» возвращается 0FFH.

Если буфер FCB в позиции соответствующей номеру диска, содержит символ «?»(код 3FH), то выбирается первый описатель каталога активизированного диска. Этот случай используется для просмотра текущего состояния всех описателей каталога активизированного диска (см.функцию 18).

Функция 18. Поиск следующего
            Вход: Регистр  С=12Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= индекс описателя

Функция «поиск следующего» аналогична функции «поиск первого», за исключением того, что просмотр каталога начинается с последнего описателя, совпавшего с заданным буфером FCB. Если соответствующий элемент не найден, то в регистре «А» возвращается 0FFH.

Функция 19. Стирание файла
            Вход: Регистр  С=13Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= индекс описателя

Функция стирает в каталоге диска все описатели файла (файлов), имя которого задано в буфере FCB. Поле номера диска не может содержать символ «?» (код 3FH).

Если соответствующий описатель найден в каталоге, в регистре «А» возвращается его индекс, подтверждающий выполнение операции, в противном случае возвращается 0FFH.

Функция 20. Последовательное чтение
            Вход: Регистр  С=14Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= индекс описателя

Функция читает 128 байтовую запись из файла, имя которого задано в буфере FCB, в буфер обмена. Буфер FCB должен содержать информацию о размещении файла на диске, для чего необходимо предварительно открыть файл (функция 15).

Чтение записи происходит из текущего екстента с текущим номером, с последующим прибавлением единицы, то есть устанавливается номер следующей записи. Если поле текущего номера записи переполняется, то следующая операция чтения автоматически открывает следующий экстент и поле текущего номера записи обнуляется.

Если операция чтения прошла успешно, в регистре «А» возвращается 00Н, в противном случае значение отличное от нуля.

Функция 21. Последовательная запись
            Вход: Регистр  С=15Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= индекс описателя

Функция заносит 128-байтовую запись из буфера обмена в файл, имя которого указано в буфере FCB. Буфер FCB должен содержать информацию о размещении файла (предварительное выполнение функции 15 или 22). Запись помещается в текущий экстент с текущим номером и к полю текущего номера записи прибавляется единица, то есть устанавливается номер следующей записи. Если поле текущего номера записи переполняется, то для следующей записи автоматически открывается следующий экстент, а поле текущего номера записи обнуляется.

Операция записи может происходить в ранее созданный файл, в этом случае вновь занесенные записи помещаются в те же блоки, что и ранее существовавшие в файле.

Если операция прошла успешно, то в регистре «А» возвращается 00Н, в противном случае — ненулевое значение.

Функция 22. Создание файла.
            Вход: Регистр  С=16Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= индекс описателя

Функция заполняет описатель файла нулями байты с 13 по 31 буфера FCB и записывает в каталог диска. Таким образом, функция «создание файла» так же, как и функция 15, обеспечивает доступ к файлу для всех операций. Байты с 0 по 12 буфера FCB заполняет пользователь. Они включают номер диска, имя и расширение файла. Следует помнить, что дублирование имен на одном диске не допускается. В этом необходимо убедиться, выполнив предварительно функцию 17.

При успешном окончании операции А=00Н, если в каталоге нет места (на диске записано уже 128 описателей), то в регистре «А» возвращается 0FFH.

Функция 23. Переименование файла.
            Вход: Регистр  С=17Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= индекс описателя

Функция заменяет имя файла (с расширением), заданное в байтах с 0 по 12 в буфере FCB, адрес которого указан в DE, на имя, заданное в байтах с 16 по 28 того же буфера FCB. Номер диска задается только в нулевом байте буфера FCB, байт 16 — всегда содержит 00Н.

Если переименование прошло успешно, в регистре «А» возвращается индекс описателя в каталоге, в противном случае — 0FFH.

Функция 24. Получить вектор активных дисков 
            Вход: Регистр  С=18Н
            Выход:Регистр HL= вектор действующих дисков

Вектор активных дисков представляет собой 16-битную величину и возвращается в регистре HL. Первый значащий бит регистра «L» соответствует диску «А», второй бит — диску «В». Нулевое значение бита означает, что соответствующий диск не установлен (не активизирован), единица — установлен функцией «Активизация диска» или одной из операций над файлом с явным заданием номера диска в поле номера диска буфера FCB.

Функция 25. Получить номер (имя) текущего диска
            Вход: Регистр  С=19Н
            Выход: Регистр  А= номер текущего диска

Функция возвращает в регистре «А» номер активного диска. А=00Н — диск «А», А=01Н — диск «В», А=02Н — диск «С».

Функция 26. Установить адрес буфера обмена (DMA)
            Вход: Регистр  С=1АН
            Регистр DЕ= Адрес буфера обмена

Буфер обмена представляет собой 128-байтовую область памяти, через которую осуществляется чтение/запись информации файла. Процедура «горячий/холодный старт» устанавливает буфер обмена по адресу 0080Н. Установленный адрес сохраняется до повторного вызова функции 26 с новым значением или выполнения процедуры «горячий/холодный старт».

Установив адрес буфера обмена и в цикле вызывая функцию «последовательное чтение», можно считать весь файл в память компьютера. Следует только не забывать после чтения каждой записи увеличивать адрес буфера обмена на 128 единиц.

Функция 27. Получить адрес вектора размещения блоков
            Вход: Регистр  С=1ВН
            Выход: Регистр HL= начальный адрес вектора размещения 
                   блоков для активизированного диска.

Вектор размещения блоков формируется в основной памяти для каждого установленного диска. Различные системные программы используют информацию, содержащуюся в векторе размещения блоков для определения величины свободной памяти на диске.

Функция 28. Записать ключ защиты записи на диска
            Вход: Регистр  С=1СН

Функция устанавливает временное запрещение записи на активизированный диск. В результате, вплоть до выполнения «горячего/холодного старта», любая попытка записи на активизированный диск вызовет сообщение об ошибке:

BDOS ERR ON D: R/O,  где D - имя диска
Функция 29. Получить вектор « R/O».
            Вход: Регистр  С=1DН
            Выход: Регистр HL= значение вектора R/O

Функция возвращает в паре регистров HL битовый вектор, указывающий на диски, для которых установлен бит защиты записи R/O (только чтение). Младший значащий бит соответствует диску «А», второй — «В» и т. д..

Функция 30. Установить атрибуты файла.
            Вход: Регистр  С=1ЕН
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= индекс описателя

Функция позволяет программно работать с индикатором доступа файла. Для файла, имя которого задано в буфере FCB, устанавливается индикатор доступа R/O (только чтение), если старший бит байта 9 буфера FCB содержит «1», или R/W (чтение/ запись), если этот бит содержит «0».

Функция 31. Получение адреса параметров дисковода
            Вход: Регистр  С=1FН
            Выход: Регистр HL= адрес параметров дисковода.

Функция используется для получения адреса блока параметров активного дисковода. Блок параметров (количество дорожек, секторов на дорожке и т. д.) размещается в BIOS.

Функция 32. Установка/опрос кода пользователя (USER)
            Вход: Регистр  С=20Н
            Регистр  Е= 0FFH (опрос) или код пользователя 
            Выход: Регистр  А= фактический код пользователя (при опросе)
                   или без значения (при установке).

Функция 33. Прямое чтение
            Вход: Регистр  С=21Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= код ошибки

Прямое чтение аналогично последовательному чтению файла, за исключением того, что прямое чтение позволяет производить записи с произвольно указанным номером. Для обращения к функции необходимо предварительно открыть файл и занести номер записи в поле номера записи при прямом доступе (буфер FCB — байты 33 и 34, байт 35 должен быть предварительно обнулен, так как ненулевое значение этого байта означает переполнение диска). В регистре «А» возвращается либо код ошибки, либо 00Н, что означает благополучное завершение операции. В этом случае в буфере обмена содержится считанная запись.

В отличии от последовательного чтения при прямом чтении после ввода записи поле номера записи прямого доступа в буфере FCB не изменяется и при повторном чтении произведет повторный ввод записи в буфер обмена с тем же номером.

Ошибки, возвращаемые в регистре «А» после выполнения операции прямого чтения, приведены ниже:

  • 01 — чтение отсутсвующих записей;
  • 03 — ошибка при закрытии текущего экстента;
  • 04 — попытка открыть несуществующий экстент;
  • 05 — переполнение каталога (при прямой записи);
  • 06 — физический конец диска.

Коды ошибок 01 и 04 встречаются в случае, когда при операции прямого чтения достигнут блок данных, который до этого не был записан, или экстент, который до этого не был организован.

Код ошибки 03 обычно не появляется при нормальной работе системы. Она может быть снята при повторном чтении или открытии файла.

Код 06 встречается при ненулевом значении 35-го байта в буфере FCB.

Функция 34. Прямая запись
            Вход: Регистр  С=22Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= код ошибки

Функция записывает на диск данные, находящиеся в буфере обмена. Если экстент на диске или блок данных, в которые поизводится запись, еще не отведены, осуществляется их выделение на диске. Как и при прямом чтении, номер записи (33 и 34 байт в буфере FCB) не меняется в результате выполнения прямой записи. Текущий номер экстента и текущий номер записи в экстенте вычисляются по заданному номеру прямой записи и заносятся в соответствующие байты буфера FCB. Коды ошибок, возвращаемые функцией при прямой записи, идентичны кодам ошибок при прямом чтении, за исключением кода 05.

Функция 35. Вычисление размера файла.
            Вход: Регистр  С=23Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Установка значения в номере поля записи при прямом доступе

Функция вычисляет размер файла, имя которого задано в буфере FCB, и возвращает его в байтах 33-35. Возвращаемый размер файла на самом деле на единицу меньше указанного значения. Значение представляется в записях, т.е по 128 байт.

Используя эту функцию, можно в конец существующего файла добавить дополнительные записи. Для этого следует:

  • получить номер (он уже увеличен на единицу) последней записи при помощи функции 35;
  • выполнить функцию «прямая запись» с этим номером;
  • затем выполнить функцию «прямая запись» нужное количество раз, увеличивая каждый раз номер записи на единицу.

Если файл записан последовательно, действительный размер файла совпадает с числом записей в нем. Если файл создан в режиме прямого доступа, и в области размещения файла существуют «дырки», то фактическое число записей меньше, чем указано в его размере.

Функция 36. Установить номер записи для прямого доступа
            Вход: Регистр  С=24Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Установка поля номера прямой записи

Функция является подготовительной и устанавливает номер записи прямого доступа (байты 33 и 34) по номеру текущего экстента и номеру текущей записи. Применяется при переходе из режима последовательного доступа в режим прямого.

К примеру, в процессе работы к файлу осуществляется последовательный доступ (чтение/запись) до соответствующей записи. Затем вызывается функция 36 и вычисляется номер прямой записи, и, начиная с этой записи выполняют операции прямой записи/чтения.

Функции 37-39 в СР/М версии 2.2 отсутствуют.

Функция 40. Прямая запись с заполнением нулями
            Вход: Регистр  С=28Н
            Регистр DЕ= Адрес буфера FCB
            Выход: Регистр  А= код ошибки

Функция аналогична «прямой записи» за исключением того, что при выделении нового блока, он предварительно на диске заполняется нулями.

Структура файлов СР/М

В СР/М под диском подразумевается логическое устройство представляющее собой некоторую внешнюю запоминающую среду с прямим доступом, допускающую как чтение, так и запись.

Все дорожки дискеты размечены (это выполняет программа форматирования) на секторы по 1 Кбайту. Каждая дорожка (за дорожку будем считать обе стороны дискеты) содержит 10 секторов (то есть 5 + 5 секторов с каждой стороны дискеты). Отсчет на дорожке начинается с первого сектора. Несложно вычислить, что полная емкость дискеты составит 800 Кбайт.

Однако не все пространство диска отведено пользователю.

Логически диск разбивается на три составных области:

  • системная область. В ней размещается BOOT-сектор, ССР, BDOS и BIOS как единый блок, предназначенный для загрузки в память компьютера. Она занимает нулевую и первую дорожки, то есть 20 Кбайт.
  • область каталога, для размещения описателей файлов. Занимает первых четыре сектора на второй дорожке.
  • область файлов. Все оставшееся пространство диска.

Пространство диска, отведенное под каталог и файлы, организовано блоками постоянной длины размером в два сектора, т.е 2 Кбайта. Это минимальная, логически учитываемая BDOS, единица измерения диска. Если сказать проще, то при записи файла даже размером в один байт — на диске для него будет отведен блок, т.е 2 Кбайта.

BDOS осуществляет обмен с диском (только посредством BIOS) по записям. Длина записи составляет 128 байт. В один сектор вмещается 8 записей. Только BIOS «знает» как в секторе расположены записи. Из-за такой двойной бухгалтерии «запись-сектор» конечно замедляется скорость обмена информацией с диском, но за то более рационально упаковывается информация, а следовательно и увеличилась полезная емкость дискеты.

В области каталога размещаются описатели файлов. Размер описателя (блок управления файлом — FCB) — 32 байта. Он содержит имя файла, расширение и номера блоков в которые операционная система разместила файл и другую служебную информацию. Пример размещения описателей файлов каталога приведен в таблице 2. Таблица условно разбита на две записи.

Один описатель расчитан на 16 Кбайт записываемой информации. Следовательно если файл дольше 16 Кбайт, то используется несколько описателей. Часть файла в 16 Кбайт называется экстентом. Поэтому если файл большой, то он состоит из нескольких экстентов, пронумерованных в порядке их создания. Несложно посчитать, что отведенное пространство под каталог допускает разместить 128 описателей. Однако этим невозможно гарантировать запись такого же количества файлов на дискету, если они имеют размер более 16 килобайт. В тоже время из-за блочного (по 2 Кбайта) принципа учета емкости диска, сохранение малых файлов приводит к его нерациональному использованию. Тем не менее со всем этим приходится мириться, с тем, чтобы иметь возможность создавать файлы с любым количеством записей — от нуля до полного использования диска (независимо от емкости диска, даже если это «Винчестер» на несколько десятков Мбайт).

Таблица 2.

0000 0041 5649 3130 3424 2042 5255 0000 0030 .AVI104$ BRU...0
0010 0200 0300 0400 0000 0000 0000 0000 0000 ................
0020 004B 4559 414C 5424 2042 5255 0000 0010 .KEYALT$ BRU....
0030 0500 0000 0000 0000 0000 0000 0000 0000 ................
0040 0046 5430 3120 2020 2042 5255 0000 0008 .FT01    BRU....
0050 0600 0000 0000 0000 0000 0000 0000 0000 ................
0060 0031 5F54 5820 2020 2042 5255 0000 0010 .1_ТХ    BRU....
0070 0700 0000 0000 0000 0000 0000 0000 0000 ................

0080 0044 4F53 525F 5458 2042 5255 0000 0080 .DOSR_TX BRU....
0090 0800 0900 0A00 0B00 0C00 0D00 0E00 0F00 ................
00A0 0044 4F53 525F 5458 2042 5255 0100 0008 .DOSR_TX BRU....
00B0 1000 0000 0000 0000 0000 0000 0000 0000 ................
00C0 0044 4F53 525F 5458 2042 5255 0200 0080 .DOSR_TX BRU....
00D0 1100 1200 1300 1400 1500 1600 1700 1800 ................
00E0 E546 4344 525F 5458 2042 5255 0100 0060 .FCDR_TX BRU...`
00F0 1900 1A00 1B00 1C00 1D00 1E00 0000 0000 ................

При считывании одной записи каталога, в ней располагается четыре описателя. По месту положения описателя в записи, он имеет номер от 0 до 3 и называется индексом описателя, который и возвращается при выполнении ряда функций BDOS.

При выполнении функции «открыть файл», операционная система переносит информацию из описателя (по данному файлу) в буфер, расположенный в памяти компьтера, при этом он, дополнително увеличивается еще на несколько ячейк. Этот буфер мы будем называть — буфер управления файлом или буфер FCB, который размещается по общепринятому адресу 005С-007FH. Если открывается несколько файлов для доступа к ним (чтение/запись), необходимо организовать несколько буферов FCB в других областях памяти компьютера.

Буфер FCB состоит из 33 байт (32 байта описателя и один «свой») в случае организации последовательного доступа, и из 36 (32+4) байт при прямом доступе. Структура буфера FCB приведена в таблице 3.

                                               Таблица 3
----------------------------------------------------------
|DR|F1|F2|//|F8|T1|T2|T3|EX|S1|S2|RC|D0|//|DN|CR|R0|R1|R2|
----------------------------------------------------------
 00 01 02 .. 08 09 10 11 12 13 14 15 16 .. 31 32 33 34 35 D
----------------------------------------------------------
 00 01 02 .. 08 09 0A 0B 0C 0D 0E 0F 10 .. 1F 20 21 22 23 H

   Где:
   DR       - номер диска. Может иметь значение от 0 до 2.
              при этом:  0 - соответствует активизированному
                             диску,
                         1 - соответствует диску "А"
                         2 - соответствует диску "В"
               В описателе этот байт выполняет другие функции.
              Если байт имеет знчение 0Е5Н - описатель (и 
              файл) - уничтожен, если - 0-F, то это номер 
              USER, к которому относится файл;
   F1..F8   - имя файла, состоящее из 1-8 больших латинских
              букв/цифр с нулевыми старшими битами. Имена
              короче 8 символов дополняются справа пробелами;
   T1,T2,T3 - тип файла, состоящий из 1-3 больших латинских
              букв/цифр с нулевыми старшими битами. Если
              символов меньше - заполняется нулями.
                Старший бит (D7) поля Т1 используется как
              индикатор доступа к файлу.  Если он равен 1,
              то файл R/O (только чтение), если - 0, то R/W
              (чтение/запись).  Старший бит поля Т2 (D7=1)
              указывает на принадлежность файла к группе - 
              системный. Такой файл не просматривается
              директивой DIR;
   EX       - текущий номер экстента.        Пользователем обычно
              устанавливается в ноль;
   S1,S2    - зарезервировано для внутреннего использования;
   RC       - число записей в текущем экстенте, принимает
              значение от 0 до 128;
   D0..DN   - номера блоков в экстенте, заполняются СР/М;
   CR       - текущий номер записи в экстенте.  В операциях
              последовательного чтения/записи обычно устанав-
              ливается в ноль;
   R0,R1    - номер записи при прямом доступе. Содержит
              16-битное значени (R0-младший байт, R1-старший);
   R2       - байт переполнения

Для осуществления доступа к файлу, пользователь заполняет в буфере FCB байты с 0 по 12, то есть указывает номер диска (0 — если обращается к уже активизированному, 1-2 — к дискам «А», «В» — соответственно), имя и тип файла и номер открываемого или создаваемого экстента (обычно — 0, то есть начать с начала). Затем необходимо выполнить функцию «открыть файл» или «создать файл», и операционная система заполнит остальные поля буфера FCB.

При выполнении последующих операций ввода/вывода BDOS корректирует содержимое буфера FCB, осуществляя автоматическое открытие/закрытие текущих экстентов файла.

По окончанию работы с файлом текущую информацию из буфера FCB необходимо записать в каталог, выполнив функцию «закрытие файла».