Материал: 1328

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

f20: ret f10writ endp

;Закрытие дискового файла:

g10clse

proc near

 

mov

namedta,1ah

;установить конец файла EOF

call

f10writ

 

mov

ah,10h

;функция закрытия

lea

dx,fcbrec

 

int

21h

 

ret

 

 

g10clse

endp

 

;Прокрутка экрана:

q10scr

proc near

;ax уже установлен

mov

bh,1eh

;цвет желтый на синем

mov

cx,0000

 

mov

dx,184fh

 

int

10h

;прокрутка

ret

 

 

q10scr

endp

 

;Установка курсора:

q20curs

proc near

 

mov

ah,02

 

mov

bh,00

 

mov

dl,00

 

mov

dh,row

;установить курсор

int

10h

 

ret

 

 

q20curs

endp

 

;Вывод сообщения об ошибке на диске:

x10err

proc near

 

mov

ah,09

;dx содержит

int

21h

; адрес сообщения

mov

errcde,01

;установить код ошибки

ret

 

 

x10err

endp

 

codesg

ends

 

end

begin

 

__________________________________________________________________________

Программа, приведенная в данном примере, создает дисковый файл по имени, которое вводится пользователем с клавиатуры. Блок FCB (fcbrec) в данной программе содержит следующие поля:

fcbdriv программа должна создать файл на диске 4 (или D). fcbname имя файла namefile.

fcbext тип файла dat.

fcbblk Начальное значение номера текущего блока 0.

fcbrcsz Размер записей не определен, так как операция открытия устанавливает в данном поле значение 128.

fcbsqrc -начальное значение номера текущей записи 0.

66

В программе организованы следующие процедуры:

begin вызывает c10open для создания файла и установки адреса DTA для DOS, вызывает d10proc для ввода имени файла. Если ввод пустой, то происходит вызов g10clse для завершения программы;

c10open создает для файла элемент в директории, устанавливает размер записей 32 (шест.20) и инициализирует адрес буфера DTA для DOS. d10proc выдает запрос на ввод имен, вводит имена с клавиатуры и

вызывает процедуру f10writ для записи вводимых имен на диск. e10dispуправляет прокруткой и установкой курсора. f10writ записывает имена в дисковой файл.

g10clse записывает маркер конца файла и закрывает файл.

x10err выдает на экран сообщение об ошибке в случае некорректной операции создания файла или записи данных.

Каждая операция записи автоматически добавляет 1 к fcbsqrc (номер текущей записи) и шест. 20 (размер записи) к fcbflsz (размер файла). Так как каждая запись имеет длину 32 байта, то операция заносит в буфер 16 записей и затем записывает весь буфер в сектор диска. Ниже показано содержимое DTA и буфера:

DTA: |текущая запись|

Буфер: |запись 00|запись 01|запись 02|...|запись 15| Если пользователь ввел 25 имен, то счетчик записей увеличится от 1 до 25

(шест.19). Размер файла составит:

25 * 32 байта = 800 байтов или шест. 320 Операция закрытия заносит во второй сектор оставшиеся в буфере девять

записей и изменяет в оглавлении дату и размер файла. Размер записывается байтами в переставленном порядке: 20030000. Последний буфер имеет следующий вид:

Буфер: |запись 16|запись 17|...|запись 24|шест.1A|...|...|

Для простоты в приведенной программе создаются записи файла, содержащие только одно поле. Записи большинства других файлов, однако, содержат различные символьные и двоичные поля и требуют описания записи в DTA. Если записи содержат двоичные числа, то не следует использовать маркер конца файла (EOF), так как двоичное число может совпасть с шест. кодом 1A.

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

FCB.

=================================================================

Пример П.1.5

; lab3pr5.asm программа, использующая FCB для чтения дискового файла

;Чтение записей созданных в CREATDSK

;-------------------------------------------------------

codesg segmentPARA 'Code'

assume cs:codesg,ds:codesg,ss:codesg,es:codesg

org

100h

; обход PSP

begin: jmp

main

;обход через данные

 

 

67

; ---------------------------------------------------

 

fcbrec label

byte

 

;FCB для файла

fcbdriv

db

04

; дисковод D

fcbname

db

'namefile'

; имя файла

fcbext

 

db

'dat'

; тип файла

fcbblk

 

dw

0000

; номер текущего блока

fcbrcsz

dw

0000

; длина логической записи

fcbflsz

 

dd

?

; размер файла (DOS)

 

 

dw

?

; дата (DOS)

 

 

dt

?

; зарезервировано (DOS)

fcbsqrc

db

00

; текущий номер записи

 

 

dd

?

; относительный номер

reclen

 

equ

32

;длина записи

namefld

db

reclen dup(' '), 13, 10, '$'

endcde

db

00

 

openmsg

db

'*** Open error ***', '$'

readmsg

db

'*** Read error ***', '$'

row

db

00

 

 

main

proc

far

 

 

 

mov

ax,0600h

 

 

call

q10scr

 

;очистить экран

 

call

q20curs

;установить курсор

 

call

e10open

;открыть файл и установить DTA

 

cmp

endcde,00

;открытие без ошибок?

 

jnz

a90

;

нет завершить

a20loop:

 

 

 

 

call

f10read

;прочитать запись

 

cmp

endcde,00

;чтение без ошибок?

 

jnz

a90

;

нет выйти

 

call

g10disp

;выдать имя на экран

 

jmp

a20loop

;продолжить

a90:

ret

 

 

;завершить

begin

endp

 

 

 

;Открытие файла на диске:

e10open

proc near

 

lea

dx,fcbrec

 

mov

ah,0fh

;функция открытия

int

21h

 

cmp

al,00

;файл найден?

jnz

e20

; нет ошибка

mov

fcbrcsz,reclen

;длина записи (EQU)

mov

ah,1ah

 

lea

dx,namefld

;адрес DTA

int

21h

 

ret

 

 

e20:

 

 

mov

endcde,01

;сообщение об ошибке

lea

dx,openmsg

 

call

x10error

 

 

 

68

ret e10open endp

;Чтение дисковой записи:

f10read

proc near

 

 

mov

ah,14h

;функция чтения

lea

dx,fcbrec

 

 

int

21h

 

 

cmp

namefld,1ah

;считан маркер EOF?

jne

f20

;

нет

mov

endcde,01

;

да

jmp

f90

 

 

f20:

 

 

 

cmp

al,00

;чтение без ошибок?

jz

f90

;

да выйти

mov

endcde,01

;

нет:

cmp

al,01

;конец файла?

jz

f90

;

да выйти,

lea

dx,readmsg

;

нет значит

call

x10err

; ошибка чтения

f90:

 

 

 

ret

 

 

 

f10read

endp

 

 

;Вывод записи на экран:

g10disp

proc near

 

 

mov

ah,09

;функция вывода на экран

lea

dx,namefld

 

 

int

21h

 

 

cmp

row,20

;последняя строка экрана?

jae

g30

;

нет...

inc

row

;

да увеличить строку

jmp

g90

 

 

g30:

 

 

 

mov

ax,0601h

 

 

call

q10scr

; прокрутить

call

q20curs

; установить курсор

g90: ret

 

 

 

g10disp

endp

 

 

;Прокрутка (скроллинг) экрана:

q10scr

proc near

;ax уже установлен

mov

bh,1eh

;установить цвет

mov

cx,0000

 

mov

dx,184fh

;функция прокрутки

int

10h

 

ret

 

 

q10scr

endp

 

;Установка курсора:

q20curs

proc near

mov

ah,02

mov

bh,00

69

mov dh,row mov dl,00 int 10h ret

q20curs endp

;Вывод сообщения об ошибке на диске:

x10err

proc

near

mov

ah,09

;dx содержит адрес

int

21h

; сообщения

ret

 

 

x10err

endp

 

codesg

ends

 

end

begin

 

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

begin вызывает процедуру e10open для открытия файла и установки DTA и вызывает f10read для чтения записей. Если считан маркер конца файла, то программа завершается, если нет, то вызывается процедура g10disp.

e10open открывает файл, устанавливает значение размера и записей, равное 32 (шест. 20), и инициализирует адрес DTA.

f10read выполняет последовательное чтение записей. Операция чтения автоматически увеличивает номер текущей записи в блоке FCB.

g10disp выводит на экран содержимое прочитанной записи.

x10err выводит на экран сообщение об ошибке в случае некорректной операции открытия или чтения.

Операция открытия выполняет поиск имени и типа файла в оглавлении. Если необходимый элемент оглавления найден, то автоматически в блок FCB заносятся размер файла, дата и длина записей. Первая операция чтения записи с номером 00 получает доступ к диску и считывает весь сектор (16 записей) в буфер. После этого первая запись заносится в DTA, а номер текущей записи в FCB увеличивается с 00 до 01:

Буфер: |запись 00|запись 01|запись 02|... |запись 15| DTA : |запись 00|

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

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

Операция чтения 16-й записи приводит к физическому чтению следующего сектора в буфер и пересылке первой записи сектора в DTA. Последующие операции чтения переносят остальные записи из буфера в DTA. Попытка прочитать после последней записи вызовет состояние конца файла и в регистр al будет записан код возврата шест. 01.

70

Источник: https://studfile.net/preview/16407385/