В предыдущий раз пришлось уделить внимание и бегло рассмотреть работу с файлами в ОС CP/M. А так как «Быстро, хорошо не бывает» (с) было принято решение о необходимости подробного и основательного разбора данного вопроса, так что бы в будущих статьях не тратить на него время и место.

Статья была опубликована в 2020 году в 28 номере журнала по ZX Spectrum'у "ЗаRulem Печатное Слово".

Статья написана в соавторстве с Вадимом Чертковым.


Работа с файлами в ОС CP/M ведется через систему команд Базовой Дисковой Операционной Системе (БДОС). Это аппаратно-независимый модуль, обеспечивающий вместе с Базовой Системой Вода/Вывода (БСВВ) взаимодействие оператора с системой и управление ресурсами системы, прежде всего файлами. БДОС – логическое ядро ОС, которое с помощью механизма вызова системных функций создаёт стандартную среду для транзитных (запускаемых пользователем) программ.

Подробно о ОС CP/M в реализации для компьютера «Profi» и её компонентах, включая все команды БДОС, можно прочитать в брошюре фирмы KRAMIS «Описание операционной системы SP-DOS» (83 стр.). К сожалению, год издательства и иные реквизиты не указаны. Известно о двух изданиях данной брошюры, отличающихся обложками, но полностью идентичных по содержанию, даже опечатки на тех же местах. Брошюру в оригинальном виде в формате PDF можно скачать по ссылкам в конце статьи. Так же там имеется ссылка на незначительно доработанную версию брошюры. В частности всем операциям БДОС были присвоены символьные имена и для удобства добавлено два приложения. В дальнейшем ссылаться будем на доработанную версию брошюры.

В данной статье будут затронуты только вопросы работы с файлами.

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

Файловая система ОС обеспечивает четыре вида операций:

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

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

  3. Доступ к дискам. Они включают операции выбора диска, сброса диска, изменения состояния диска и определения свободного места на нем.

  4. Смешанные операции. Смешанные операции включают операции установки адреса прямого доступа для обмена с диском, установки кода пользователя, загрузки новой программы, доступа к операциям БСВВ и расширенной БДОС, а также доступа к системным переменным в БУС.

Система поддерживает от 1 до 16 логических дисков. Максимальный размер дискового файла - 8 Мбайт.

Область оглавления диска содержит от 1 до 16 блоков (действительное число задается в БСВВ), размещаемых в начале диска. В этой области содержатся элементы оглавления для каждого файла, в которых определены те блоки в области данных, которые принадлежат данному файлу.

Область оглавления логически разделена на 16 независимых оглавлений (USER) для каждого из 16 возможных пользователей 0-15. В каждый текущий момент времени только одна область пользователя доступна вызывающей программе на всех дисках системы. Эта область может быть изменена вызовом операции БДОС 32 (получение/установка кода пользователя). Область пользователя с кодом 0 имеет в CP/M особое значение. Файловая система обеспечивает открытие файлов в режиме только для чтения в этой области (если указанный файл имеет установленный системный атрибут) в том случае, если в текущей области пользователя указанный файл отсутствует. Это позволяет использовать программы с системным атрибутом, находящиеся в области пользователя 0 на системном диске из любой области пользователя, поэтому нет необходимости хранить их в каждой области пользователя.

Файловая система ОС не поддерживает каталоги, но их роль могут выполнять как раз области пользователей (USER’ы). Изначально это была попытка организации множественного доступа к информации на диске, когда у каждого пользователя был номер (от 0 до 15) и он имел доступ только к файлам в своей области (и к системным файлам в области USER 0). В настоящее время области пользователя (USER’ы) можно рассматривать как заранее созданные каталоги с предопределенными именами USER 0-15, без возможности их изменения. Что конечно не очень удобно, но все-таки лучше, чем единый общий каталог.

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

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

Символы «???» и «?*?» также не должны содержаться в именах файлов, записанных в оглавлении, так как они используются для создания неявных имен. Операция подготовки БУФ при обнаружении в имени или типе файла символа «*» заполняет остаток имени или типа символами «?», формируя, таким образом, неявное имя.

Описанные выше условия работы с именем файла справедливы только в случае подготовки БУФ (Блока Управления Файлом, о нём чуть ниже) средствами БДОС (операция 152), если же БУФ готовиться самостоятельно, то следовать указанным соглашениям не обязательно. Однако при необходимости получить доступ к такому файлу средствами БДОС (например, из командной строки), эти соглашения должны использоваться. В противном случае интерпретатор команд не найдет в оглавлении файл, если в его наименовании используются символы нижнего регистра. Беря это во внимание, очень рекомендуется придерживаться указанного соглашения.

Символ

Код

Нуль

00h

Пробел

20h

CR

0Dh

Табуляция

09h

: (двоеточие)

3Ah

; (точка с запятой)

3Bh

= (знак равно)

3Dh

^ (знак карет)

5Eh

. (точка)

2Eh

[ (открывающая прямоугольная скобка)

5Bh

] (закрывающая прямоугольная скобка)

5Dh

< (открывающая угловая скобка)

3Ch

> (закрывающая угловая скобка)

3Eh

, (запятая)

2Ch

Таблица 1. Ограничители имени файла

Каждый файл состоит из 128-байтовых записей. Позиция каждой записи определяется номером произвольного доступа записи. Для файлов создаваемых последовательно, первая запись имеет позиции 0 и последняя - позицию, на одну меньше, чем число записей в файле.

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

Работа с файлами осуществляется посредством Блока Управления Файлом (БУФ).

БУФ - это структура данных, которая организуется и инициализируется транзитной программой, а также используется файловой системой при доступе к файлам через оглавление. Все операции с файлами обращаются за исходной информацией к БУФ. Система хранит текущее состояние файла в БУФ во время исполнения файловых операций. Кроме того, операции произвольного доступа используют 3 байта, следующие за БУФ, для определения номера произвольной записи.

При вызове операций, осуществляющих доступ к файлам или оглавлению, регистровая пара DE должна содержать адрес БУФ, указывающего на файл или файлы, с которыми должна производится операция. Для большинства операций длина БУФ равна 33 байт, а для операций произвольного доступа, вычисление размера файла и свободного места на диске размер БУФ равен 36 байт (таблица 2). Число одновременно созданных БУФ, а значит и число рабочих файлов, ограничено только объёмом свободной памяти и здравомыслием программиста.

Таблица 2. Формат БУФ и назначение его полей.
Таблица 2. Формат БУФ и назначение его полей.

где:

байт 0:

ДС

Код диска (0-16)

0- выбор текущего диска

1- выбор диска A

2- выбор диска B

---

16- выбор диска P

байты 1-8:

И1...И8

Содержат имя файла в символах верхнего латинского регистра. Старшие биты позиций И5-И8 могут использоваться системой и не должны использоваться прикладной программой. Старшие биты позиций И1-И4 могут использоваться прикладной программой для внутренних атрибутов.

байты 9-11:

Ф1...Ф3

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

 

Ф1'=1

(старший бит байта Ф1) обозначает файл R (только для чтения);

 

Ф2'=1

(старший бит байта Ф2)обозначает файл типа S (системный);

байт 12:

Содержит номер текущего экстента (USER’а), обычно устанавливается в 0 вызывающей программой. Может изменяться от 0 до 31 в процессе обмена с файлом;

байт 13:

С1

Счетчик байтов (число записей в последней записи файла). Должен устанавливаться прикладными программами;

байт 14:

С1

Резервируется для системы;

байт 15:

СЧ

Счетчик записей для экстента "3К". Принимает значения от 0 до 128;

байты 18-31:

В0-ВN

Резервируются для системы. Содержат номера блоков, занимаемых файлом;

байт 32:

Т3

Текущая запись для обмена с файлом в последовательном режиме. Обычно должна устанавливаться в 0 вызывающей программой при создании или открытии файла;

байты 33-35:

R0,R1,R2

Номер произвольной записи в пределах 0-65535. Используется только в произвольном режиме доступа к файлу младший байт R0, старший - R1, байт R2 содержит признак переполнения

Для операций доступа к оглавлению вызывающая программа перед вызовом операции должна инициализировать байты 0-11 БУФ.

Операция переименования файла требует, чтобы новое имя было помещено в байты 17-27 БУФ.

Перед вызовом операций открытия и создания файла вызывающая программа должна инициализировать байты 0-12 БУФ. Обычно байт 12 устанавливается в 0.

Кроме того, если работа с файлом будет осуществляться с начала файла в последовательном режиме, то перед началом работы байт 32 (ТЗ) должен быть установлен в 0.

После того, как БУФ активизирован операцией открытия или создания файла, программа не должна модифицировать его. Исключение составляют байты 33-35 (R0,R1,R2), в которых программа может устанавливать номер произвольной записи для режима произвольного доступа.

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

Старшие биты файла (И1',...И8') и типа файла (Ф1',...Ф3') БУФ содержат атрибуты файла; при этом значение 1 соответствует булевскому true (истина) и 0 - false (ложь).

Значения атрибутов следующие:

Ф1:

Атрибут "только для чтения"

при этом значению 1 соответствует "только для чтения" (read: R), а 0 - для записи (write: W) и чтения.

Ф2:

Системный атрибут.

Файлы с этим атрибутом в области пользователя 0 доступны из любой области пользователя в режиме "только для чтения" с системного диска (диска A:), при этом значению 1 соответствует "системный" (system: S), а значению 0 "несистемный" (directory: D).

И1',...,И4'

Атрибуты пользователя

Могут определяться пользователем.

И5',...,И8'

Интерфейсные атрибуты

используются системой и не могут использоваться как атрибуты файла.

Таблица 3. Атрибуты файла.

CP/M может обеспечить обмен несколькими записями с диском за одну операцию БДОС. Этот процесс называемый мультиселекторным обменом, удобно использовать при операциях обмена, когда размер физической записи больше 128 байт.

Количество записей, которое может участвовать в мультиселекторном обмене, изменяется в пределах от 1 до 128. Это значение устанавливается операцией БДОС 44 (установка мультиселекторного счетчика). Значение мультиселекторного счетчика определяет количество секторов, участвующих в обмене, для операций последовательного и произвольного обмена (операции 20, 21, 33, 34 и 40). Если значение мультиселекторного счетчика равно N, то вызов одной из указанных выше операций эквивалентен N последовательным вызовам при обмене по одному сектору. Если операция прерывается по ошибке (например, при достижении конца файла), Файловая система возвращает в регистре H количество записей, с которыми успешно осуществился обмен.

 При работе с файлами БДОС обнаруживает физические и логические ошибки и выдает на консоль сообщения об этих ошибках. Сообщение об ошибках подробно описаны в брошюре фирмы KRAMIS «Описание операционной системы SP-DOS», так что мы не будем сейчас на них останавливаться.

 С адреса 0 (0000h) по адрес 255 (00FFh) в CP/M расположена базовая страница памяти. Она так же хорошо описана в брошюре фирмы KRAMIS «Описание операционной системы SP-DOS», но сейчас важно упоминать, что если в программу были переданы параметры, то в области 1 БУФ (005Ch - 006Bh) подготавливается БУФ из первого имени файла из параметров, а в области 2 (006Ch - 007Bh) из второго имени. Если в параметрах команды имена файлов не указаны, то соответствующие поля заполняются пробелами.

Буфер ПДП по умолчанию с адреса 80h заполняется остатком параметрами команды, при этом в первый байт заносится количество символов остатка, а в последующие сам остаток. В буфере прямого доступа остаток ограничивается нулевым байтом. Так как файловая система использует вторую часть БУФ и буфер ПДП для дисковых операций, прикладные программы перед вызовом операций БДОС должны сохранить информацию, занесенную в них интерпретатором команд.

 В БДОС реализован целый набор операция по работе с файлами (таблица 3). Мы не будем рассматривать их все, так они хорошо описаны в брошюре от KRAMIS, номера страниц приведены в этой брошюре. На практике чаше всего необходимо производить чтения данных из файлов вот давайте и разберем, как эта задача решается в CP/M. Все примеры кода можно найти на прилагаемом образе диска.

Имя операции

Код

Описание

№ страницы

Стандартные операции

bdReset

13

0Dh

Сброс дисковой системы

39

bdDisk

14

0Eh

Выбор диска

39

bdOpen

15

0Fh

Открытие файла

40

bdClose

16

10h

Закрытие файла

42

bdSearch

17

11h

Поиск первого файла

43

bdSearch2

18

12h

Поиск следующего файла

44

bdDel

19

13h

Удаление файла

44

bdReadCon

20

14h

Последовательное чтение

45

bdWriteCon

21

15h

Последовательная запись

47

bdCreate

22

16h

Создание файла

48

bdRenem

23

17h

Переименование файла

49

bdDiskVec

24

18h

Получение вектора состояния дисков

50

bdDiskCur

25

19h

Получение текущего диска

50

bdPDPInst

26

1Ah

Установка адреса буфера ПДП

51

bdDistVec

27

1Bh

Получить адрес вектора распределения

51

bdProtect

28

1Ch

Установка защиты записи

52

bdProtVec

29

1Dh

Получение вектора защиты записи

52

bdAttrSet

30

1Eh

Установка атрибутов файла

52

bdDiskPar

31

1Fh

Получение адреса блока параметров диска

54

bdUser

32

20h

Получение/установка кода пользователя

54

bdReadRnd

33

21h

Произвольное чтение

54

bdWriteRnd

34

22h

Произвольная запись

56

bdSize

35

23h

Получение размера файла

58

bdRecRnd

36

24h

Установка номера произвольной записи

59

bdDiskRes

37

25h

Сброс диска

60

bdReadRnd0

40

28h

Произвольная запись с заполнением нулями

61

bdMultCount

44

2Ch

Установка мультиселектороного счётчика

61

bdErr

45

2Dh

Установка режима обработки ошибок

62

bdDiskFree

46

2Eh

Получение свободного места на диске

62

bdBSVV

50

32h

Вызов операции БСВВ или операции расширенной БДОС

66

bdBUFCreate

152

98h

Подготовка БУФ

72

Операции расширенной БДОС

 

50/129

32h/81h

Обмен с файлом

74

 

50/130

32h/82h

Обмен с диском

75

Таблица 4. Список операций БДОС связанных с работой с файлами

В качестве приложения к статье идет образ диска в формате «PRO». Его отлично распознают эмуляторы «ZXMAK2» (https://archive.codeplex.com/?p=zxmak2) и «UNREAL SPECCY» (https://sourceforge.net/projects/unrealspeccy/). Под ОС Windows с образом диска можно работать через программу «Stein Blume» (https://zx-pk.ru/threads/26454-steinblume-cp-m-disk-image-explorer-(ex-atm-cp-m-explorer).html). А записать на реальную дискетку образ можно через программу «ZX Disk Studio» (https://zx-pk.ru/threads/12842-zx-disk-studio-programma-dlya-raboty-s-obrazami-diskov.html).

Образ диска системный с установленным файловым менеджером «Hop Commander 1.03». Для просмотра и редактирования текстовых файлов с примерами кода имеется текстовый редактор «Write 3». Загрузить текст в него можно как из самого редактора, так и из файлового менеджера по клавише «F4» или последовательной комбинации клавиш «2»+«E».

Так же на диске есть ассемблер «m80» и линковщик «l80», которые позволят скомпилировать примеры. Для этого достаточно в файловом менеджере выбрать файлы «*.asm» по «Enter». В результате получиться запускаемый файл «*.COM».

 В ходе реализации заданий будем использовать уже знакомые по предыдущим статьям макросы, не буду повторно приводить их код, только коротко опишу. Сам код можно посмотреть в файле «BIOSK.INC» на прилагаемом образе диска.

.writed “значение”, [параметр] – выводит по текущем координатам на экран в десятичном формате 16 битное число 0…65535 или содержимое регистров A, SP, HL, DE, BC, IX, IY. Если выводиться 16 битное число, то в качестве «параметра» необходимо указать «1», противном случае его можно опускать или указывать «0».

Say “текст”, [регистр] – выводить «текст» по текущим координатам на экран, если указан один из следующих регистров A, SP, HL, DE, BC, IX, IY, то его значение в десятичной форме будет непечатно сразу за «текстом».

pause - ждет нажатия любой клавиши, если нажата «Esc», то производит холодный рестарт системы (то есть выход из текущей программы), а по любой другой продолжает выполнение программы.

.push <регистровые пары>/.pop <регистровые пары> - позволяют одной командой занести или снять со стека сразу несколько регистровых пар. Передаваемый список регистровых пар, должен быть в угловых кавычках и разделяться запятой. Пример: .push <hl, de>   …   .pop <de, hl>

.bdos “операция”, [параметр] – вызов «операции» БДОС, с передачей «параметра».

 Для визуализации действий будем выводить на экран ту информацию, которую загружаем из файла. Для этого будем работать с текстовым файлом. Так как в одном секторе 128 байт, в него помещаться 2 строки текста по 64 символов строке. Создадим текстовый файл «TEST.TXT» и пропишем в каждых 2 строках номер сектора, в котором находится эти строки.

Рисунок 1. Пример содержимого файла «TEST.TXT»
Рисунок 1. Пример содержимого файла «TEST.TXT»

Теперь всё готово к решению практических задач.

Задание 1. Подготовка БУФ средствами БДОС и в два этапа последовательно прочитать три сектора.

Заголовок всех листингов будет состоять из трех строчек.

.Z80             ; Указываем, что будем работать в мнемониках процессора z80
         org 100h

         INCLUDE BIOSK.INC ; Загружаем описание макросов
;----------------------------------------------------------------

Теперь создадим БУФ для работы с файлом. Для чего воспользуемся операцией БДОС 152 (bdBUFCreate). «Подготовка БУФ». Она готовит БУФ из имени файла. При её вызове в регистровой паре DE должен передаваться адрес блока подготовки имени файла (PFCB), имеющего следующий формат

PFCB:   DW      STRING ;адрес имени файла
        DW      AFCB   ;адрес подготавливаемого БУФ

Имя файла должно задаваться в следующем виде:

[D:]Имя файла[.тип файла]

где поля в квадратных скобках необязательны.

Соответственно в конце листинга добавляем строки с массивами исходных данных:

;======================================================================
; Информационные сообщения
err01:   db '<!> File not found! <!>', '$'
info01:  db '<.> Read 1 sector', 0dh, 0ah, '$'
info02:  db '<.> Read 2-3 sectors', 0dh, 0ah, '$'
;======================================================================

FileName:   db 'TEST.TXT', 0 ; Имя рабочего файла

PFCB:       dw FileName      ; Ссылка на имя рабочего файла
            dw FCB_file      ; Ссылка на БУФ рабочего файла

FCB_file:   ds 36            ; Блок управления файлом.

PDP_file:   ds 128*2         ; Буфер файла для загрузки данных с диска.

Теперь продолжим решение поставленной задачи.

.bdos bdBUFCreate,PFCB    ; Создаем БУФ для рабочего файла.
.bdos bdPDPInst,  PDP_file; Устанавливаем адрес буфера файла.
.bdos bdOpen,     FCB_file; Открываем файл.
inc a                     ; if a=255 Если на диске нет такого файла.
jp z, err.nofile          ; then Процедуру обработки ошибки рассматривать не будем.

По умолчанию в CP/M маркером конца текста для вывода на экран является знак «$». Ставим его за буфером файла.

ld a, '$'                 ; Маркер конце текста.
ld (PDP_file+128+1), a    ; Маркируем конец буфера файла.

Выводим информационную строку о том, какие сектора читаем.

.bdos bdWrite, info01

Выполняем чтение первого сектора и выводим на экран то, что прочитали.

.bdos bdReadCon, FCB_file ; Последовательное чтение 1 сектор.
.bdos bdWrite, PDP_file   ; Вывод прочитанного на экран.
pause

Так как на следующем этапе нужно будет читать два сектор за обращение, переносим маркер конца текста.

ld a, '$'                 ; Маркер конце текста.
ld (PDP_file+128*2+1), a  ; Переносим маркер конца буфера файла.

Завершаем выполнение задачи.

.bdos bdWrite, info02
.bdos bdMultCount, 2      ; Мультисекторный счетчик =2
.bdos bdReadCon, FCB_file ; Последовательное чтение 2-3 секторов
.bdos bdWrite, PDP_file   ; Вывод прочитанного на экран.
pause

После компиляции и запуска полученного кода на экране мы увидим следующее:

Рисунок 2. Выполнение задание 1
Рисунок 2. Выполнение задание 1

Задание 2. Подготовка БУФ вручную и в два этапа произвольно прочитать пять секторов.

Как видно из предыдущей задачи подготовить БУФ средствами БДОС не сложно. Но вручную это сделать иногда ещё проще. Для решения задачи 2, в конце листинга, в блоке данных, размещаем ручное описание БУФ:

            ; Блок управления файлом.
FCB_file:   db 0              ; ДС    Код диска 0-16. 0- текущий диск
               ;12346578
            db 'TEST    '     ; И1-И8 Имя файла
            db 'TXT'          ; Ф1-Ф8 Расширение файла
            db 0              ; ЗК    Номер экстента 0-31
            db 0              ; C1    Счётчик байтов
            ds 18             ; <!>   Не менять
            db 0              ; ТЗ    Текущая запись
            ds 3              ; R0-R2 Номер произвольной записи

Теперь просто опускаем вызов операции БДОС 152 (bdBUFCreate). «Подготовка БУФ», так как БУФ уже подготовили, остальное без изменений.

.bdos bdPDPInst,  PDP_file ; Устанавливаем адрес буфера файла.
.bdos bdOpen,     FCB_file ; Открываем файл.
inc a                      ; if a=255 Если на диске нет такого файла.
jp z, err.nofile           ; then

Начнём выполнение задания с чтения трёх секторов. Предварительно устанавливаем маркер конца данных:

ld a, '$'                  ; Маркер конце текста.
ld (PDP_file+128*3+1), a   ; Маркируем конец буфера файла.

Для включения произвольного доступа к файлу вызываем операций БДОС 36 (bdRecRnd) «Установка номера произвольной записи». В результате выполнения, которой в полях R0...R2 БУФ файла будет записан номер произвольной записи, следующий за записью, доступ к которой осуществляется  в последний раз. Эта же операция переводит файл в режим произвольного чтения.

.bdos bdRecRnd, FCB_file   ; Включаем произвольный режим доступа к файлу.

Теперь в поля R0..R1 заносим номер сектора с которого хотим начать чтение. Пусть, в нашем случае, это будет 7 сектор.

ld hl, 7                   ; Устанавливаем сектор для произвольного чтения.
ld (FCB_file+33), hl       ;

Далее действуем по схеме из задания 1, только вместо операции БДОС 20 (bdReadCon) «Последовательное чтение» используем операцию 33 (bdReadRnd) «Произвольное чтение».

.bdos bdMultCount, 3       ; Мультисекторный счетчик =3
.bdos bdWrite, info01
.bdos bdReadRnd, FCB_file  ; Произвольное чтение 3-х секторов.
.bdos bdWrite, PDP_file    ; Вывод прочитанного на экран.
pause

Читаем и выведем 3 и 4 сектора.

ld a, '$'                  ; Маркер конце текста.
ld (PDP_file+128*2+1), a   ; Переносим маркер конца буфера файла.

ld hl, 3                   ; Устанавливаем сектор для произвольного чтения.
ld (FCB_file+33), hl       ;

.bdos bdWrite, info02
.bdos bdMultCount, 2       ; Мультисекторный счетчик =2
.bdos bdReadRnd, FCB_file  ; Произвольное чтение 2-х секторов
.bdos bdWrite, PDP_file    ; Вывод прочитанного на экран.
pause

Скомпилировав и запустив программу, получим на экране следующий результат.

Рисунок 3. Выполнение задание 2
Рисунок 3. Выполнение задание 2

Задание 3. Переход от произвольного режима чтения к последовательному.

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

Прямой команды, на подобии операции БДОС 36 (bdRecRnd) «Установка номера произвольной записи» для реализации этой задачи нет. Если сразу после произвольного чтения, начать последовательное чтение, то первым прочитается последний прочтённый в предыдущий раз сектор. Например: в произвольном режиме были прочтены сектора 3, 4, 5, если сразу начать последовательное чтение, то будет прочтены сектора 5, 6, 7. Чтобы нивелировать данную ситуацию случае нужно сделать следующее, когда:

  1. необходимо продолжать последовательное чтение с текущей позиции в файле, нужно: установить мультиселекторный счётчик на 1, произвести техническое последовательное чтение одного сектора, после чего установить желаемое значение мультиселектороного счётчика и продолжить последовательное чтение.

  2. необходимо начать последовательное чтение с новой позиции в файле, нужно: установить в полях R1-R2 БУФ номер сектор, с которого необходимо производить чтение, так же установить мультиселекторный счётчик на 1, произвести техническое произвольное чтение, вернуть нужно значение мультиселекторному счётчику и начать последовательное чтение.

Как видно, ни чего сложного, хотя действий и больше чем при переходе к произвольному режиму чтения. Напишем код для примера, взяв за основу код от задачи 2, так как в нём уже есть переход к произвольному режиму чтения.

Предыдущее задание закончилось на том, что мы прочитали сектора 3, 4. Теперь последовательно прочитаем сектора 5, 6 а затем 7. Переходим в режим последовательного чтения.

.bdos bdMultCount, 1       ; Мультисекторный счетчик =1
.bdos bdReadCon, FCB_file  ; Техническое последовательное чтение 1-го сектора.
.bdos bdMultCount, 2       ; Мультисекторный счетчик =2

Читаем и выводим сектора 5, 6.

.bdos bdWrite, info03
.bdos bdReadCon, FCB_file  ; Последовательное чтение 2-х секторов
.bdos bdWrite, PDP_file    ; Вывод прочитанного на экран.
pause

Теперь прочитаем 7 сектор.

.bdos bdMultCount, 1       ; Мультисекторный счетчик =1
ld a, '$'                  ; Маркер конце текста.
ld (PDP_file+128+1), a     ; Переносим маркер конца буфера файла.

.bdos bdWrite, info04
.bdos bdReadCon, FCB_file  ; Последовательное чтение 1-го секторов
.bdos bdWrite, PDP_file    ; Вывод прочитанного на экран.
pause

Теперь прочитаем сектор 10, а затем сектор 11. Смещаемся в файле на 10 сектор.

.bdos bdRecRnd, FCB_file   ; Включаем произвольный режим доступа к файлу.
ld hl, 10                  ; Устанавливаем сектор для произвольного чтения.
ld (FCB_file+33), hl       ;
.bdos bdReadRnd, FCB_file  ; Техническое произвольное чтение 1-го секторов.

Читаем его.

.bdos bdWrite, info05
.bdos bdReadCon, FCB_file  ; Последовательное чтение 1-го секторов
.bdos bdWrite, PDP_file    ; Вывод прочитанного на экран.
pause

Последовательно читаем 11 сектор.

.bdos bdWrite, info06
.bdos bdReadCon, FCB_file  ; Последовательное чтение 1-го секторов
.bdos bdWrite, PDP_file    ; Вывод прочитанного на экран.
pause

Собственно, всё. Компилируем, запускаем и видим такую картину.

Рисунок 4. Выполнение задание 3
Рисунок 4. Выполнение задание 3

Статьи, графика – это все очень хорошо и полезно. Но в современном мире есть еще один способ передачи информации, который мы пока обходили стороной - я говорю о видео роликах. Не смотря на то, что этот способ имеет, целый ряд недостатков, он же обладает и некоторым набором плюсов. Поэтому было, приятно решения попробовать себя в этом направлении. Для чего был создан YouTube канал «Зазеркалье».

Компьютерщик, не совсем обычный человек. Жизнь его состоит из двух частей, и грань раздела проходит по стеклу монитора. Одна часть находится в реальном мире, а вторая в удивительной стране - Зазеркалье. И сложно сказать какая из частей главнее. Канал посвящен всем аспектам жизни по ту сторону монитора, в Зазеркалье. В первую очередь он будет отражать те грани этого мира, которые интересны нам, это: и ZX Spectrum, и OS/2, и различный языки программирования, и многое другое. Но мир Зазеркалья гораздо многограннее, так что если у кого-то вдруг появиться желание отразить интересные ему грань, будем рады предоставить эту площадку. Сложно надеяться на частый выход видео, но точно они будут - это однозначно.

На канале «Зазеркалье» выложено видео работы программ приведенных в заданиях. Ссылки на него можно найти в приложении.

С остальными аспектами работы с файлами, не сложно разобраться по аналогии, рамки статьи не позволяют уделить им время. Читайте брошюру фирмы KRAMIS «Описание операционной системы SP-DOS», там есть вся необходимая информация. Если все-таки останутся вопросы, с нами можно связаться по адресам:

  • FidoNet: Tarasow Aleksey 2:5053/57

  • E-mail: tae1980(очень злая собака)yandex.ru

А так же много материала форуме и в группе ВК.

Приложение:

Комментарии (0)