Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 августа!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Ассемблер для крэкера

Под редакцией Еpшова В.Г.
DATA    ENDS
; -----------------------------------------------
CODESG  SEGMENT PARA 'Code'
BEGIN   PROC    FAR
        ASSUME CS:CODESG,DS:DATDSG,SS:STACK,ES:DATASG
        PUSH    DS
        SUB     AX,AX
        PUSH    AX
        MOV     AX,DATASG
        MOV     DS,AX
        MOV     ES,AX
        CLD
        LEA     DI,NAMETAB
        CALL    Q10CLR          ;Очистить экран
        CALL    Q20CURS         ;Установить курсор
A20LOOP:
        CALL    B10READ         ;Ввести имя с клавиатуры
        CMP     NAMELEN,00      ;Есть ли еще имена?
        JZ      A30             ; нет - идти на сортировку
        CMP     NAMECTR,30      ;Введено 30 имен?
        JE      A30             ; да - идти на сортировку
        CALL    D10STOR         ;Записать имя в таблицу
        JMP     A20LOOP
A30:                            ;Конец ввода имен
        CALL    Q10CLR          ;Очистить экран
        CALL    Q20CURS         ; и установить курсор
        CMP     NAMECTR,01      ;Введено менее 2 имен?
        JBE     A40             ; да - выйти
        CALL    G10SORT         ;Сортировать имена
        CALL    K10DISP         ;Вывести результат на экран
A40:    RET                     ;Завершить программу
BEGIN   ENDP
;               Ввод имен с клавиатуры?
;               ----------------------
B10READ PROC
        MOV     AH,09
        LEA     DX,MESSG1       ;Вывести текст запроса
        INT     21H
        MOV     AH,0AH
        LEA     DX,NAMEPAR      ;Ввести имя
        INT     21H
        MOV     AH,09
        LEA     DX,CRLF         ;Вывести CRLF
        INT     21H

        MOV     BH,00           ;Очистить поле после имени
        MOV     BL,NAMELEN      ;Получить счетчик символов
        MOV     CX,21
        SUB     CX,BX           ;Вычислить оставшуюся длину
B20:
        MOV     NAMEFLD[BX],20H ;Установить символ пробела
        INC     BX
        LOOP    B20
        RET
B10READ ENDP
;               Запись имени в таблицу:
;               ----------------------
D10STOR PROC
        INC     NAMECTR         ;Число имен в таблице
        CLD
        LES     SI,NAMEFLD
        MOV     CX,10
        REP MOVSV               ;Переслать имя в таблицу
        RET
D10STOR ENDP
;               Сортировка имен в таблице:
;               -------------------------
G10SORT PROC
        SUB     DI,40           ;Установить адреса останова
        MOV     ENDADDR,DI
G20:
        MOV     SWAPPED,00      ;Установить начало
        LEA     SI,NAMETAB      ; таблицы
G30:
        MOV     CX,20           ;Длина сравнения
        MOV     DI,SI
        ADD     DI,20           ;Следующее имя для сравнения
        MOV     AX,DI
        MOV     BX,SI
        REPE CMPSB              ;Сравнить имя со следующим
        JBE     G40             ; нет перестановки
        CALL    H10XCHG         ; перестановка
G40:
        MOV     SI,AX
        CMP     SI,ENDADDR      ;Конец таблицы?
        JBE     G30             ; нет - продолжить
        CMP     SWAPPED,00      ;Есть перестановки?
        JNZ     G20             ; да - продолжить,
        RET                     ; нет - конец сортировки
G10SORT ENDP
;               Перестановка элементов таблицы:
;               ------------------------------
H10XCHG PROC
        MOV     CX,10
        LEA     DI,NAMESAV
        MOV     SI,BX
        REP MOVSW               ;Сохранить меньший элемент

        MOV     CX,10
        MOV     DI,BX
        REP MOVSW               ;Переслать больший элемент
                                ; на место меньшего
        MOV     CX,10
        LEA     SI,NAMESAV
        REP MOVSW               ;Переслать сохраненный
                                ; элемент на место большего
        MOV     SWAPPED,01      ;Признак перестановки
        RET
H10XCHG ENDP
;               Вывод на экран отсортированные имена:
;               ------------------------------------
K10DISP PROC
        LEA     SI,NAMETAB
K20:
        LEA     DI,NAMESAV      ;Начальный адрес таблицы
        MOV     CX,10
        REP MOVSV
        MOV     AH,09
        LEA     DX,NAMESAV
        INT     21H             ;Вывести на экран
        DEC     NAMECTR         ;Это последний элемент?
        JNZ     K20             ; нет - повторить цикл,
        RET                     ; да - выйти
K10DISP ENDP
;               Очистка экрана:
;               --------------
Q10CLR  PROC
        MOV     AX,0600H
        MOV     BH,61H          ;Цвет (07 для ч/б)
        SUB     CX,CX
        MOV     DX,184FH
        INT     10H
        RET
Q10CLR  ENDP
;               Установка курсора:
;               -----------------
Q20CURS PROC
        MOV     AH,02
        SUB     BH,BH
        SUB     DX,DX           ;Установить курсор в 00,00
        INT     10H
        RET
Q20CURS ENDP

CODESG  ENDS
        END     BEGIN
__________________________________________________________________________

     Рис.14.6. Сортировка таблицы имен


     ОПЕРАТОРЫ ТИПА, ДЛИНА И РАЗМЕРА
     ________________________________________________________________

     Ассемблер  содержит  ряд  специальных  операторов,   которые    могут
оказаться полезными при программировании.  Например, при  изменении  длины
таблицы придется модифицировать программу (для нового определения таблицы)
и процедуры,  проверяющие  конец  таблицы.  В  этом  случае  использование
операторов TYPE (тип), LENGTH (длина) и SIZE (размер) позволяют  уменьшить
число модифицируемых команд.
     Рассмотрим определение следующей таблицы из десяти слов:

               TABLEX    DW   10 DUP(?) ;Таблица из 10 слов

Программа может использовать оператор TYPE  для  определения  типа  (DW  в
данном  случае),  оператор  LENGTH  для  определения  DUP-фактора  (10)  и
оператор SIZE для определения числа  байтов  (10  х  2  =  20).  Следующие
команды иллюстрируют три таких применения:

               MOV  AX,TYPE TABLEX      ;AX=0002
               MOV  BX,LENGTH TABLEX    ;BX=000A  (10)
               MOV  CX,SIZE TABLEX      ;CX=0014  (20)

     Значения LENGTH и SIZE можно использовать  для  окончания  табличного
поиска или сортировки.  Например, если  регистр  SI  содержит  продвинутый
адрес таблицы при осуществлении поиска, то проверка на конец таблицы может
быть следующий:

               CMP  SI,SIZE TABLEX

     В главе 23 "Справочник по  директивам  ассемблера"  дается  детальное
описание операторов TYPE, LENGTH и SIZE.


     ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
     ________________________________________________________________

     - Для    большинства   применений,   определяйте   таблицы,   имеющие
родственные элементы одной длины и формата данных.

     - Стройте таблицы на основе форматов данных. Например, элементы могут
быть символьные или числовые длиной один, два и более байтов каждый. Может
оказаться более практичным определение двух таблиц:  одна,  например,  для
трехсимвольных  значений  номеpов,  а другая для двухбайтовых значений цен
единиц товара.  В процессе поиска адрес элементов таблицы  номеров  должен
увеличиваться на 3,  а адрес элементов таблицы цен - на 2.  Если сохранить
число выполненных циклов при поиске на равно,  то,  умножив это число на 2
(SHL  сдвиг  влево  на  один  бит),  получим  относительный адрес искомого
значения цены. (Начальное значение счетчика циклов должно быть равно -1).

     - Помните,  что DB позволяет определять значения, не превышающие 256,
а  DW записывает байты в обратной последовательности.  Команды CMP и CMPSW
предполагают,   что   байты   в   сравниваемых   словах   имеют   обратную
последовательность.

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

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


     ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
     ________________________________________________________________

     14.1. Определите таблицу, которая содержит имена дней недели, начиная
с воскресения.

     14.2 Предполагая, что воскресенье равно 1, напишите  команды  прямого
доступа  к  таблице,  определенной  в  вопросе  14.1.  используйте   любые
подходящие имена.

     14.3 Определите три отдельных связанных таблицы, содержащих следующие
данные:
          а) числовые элементы: 06, 10, 14, 21, 24;
          б)  элементы  наименований:  видеокассеты,  приемники,   модемы,
     клавиатуры, дискеты;
          в) цены: 93.95, 82.25, 90.67, 85.80, 13.85.

     14.4  Составьте  программу,  позволяющую  вводить  числовой   элемент
(ITEMIN) и количество (QTYIN) с клавиатуры.  Используя таблицу из  вопроса
14.3, разработайте программу табличного поиска  элемента  равного  ITEMIN.
Выделите из таблиц наименование и  цену.  Рассчитайте  величину  стоимости
(Количество х Цена ) и выдайте на экран наименование и стоимость.

     14.5 Используя описание таблицы из вопроса 14.3, составьте процедуры:
а) пересылающую содержимое одной таблицы  в  новую  (пустую)  таблицу;  б)
сортирующую содержимое новой таблицы в восходящей последовательности.



ГЛАВА 15                                    Дисковая память I: Организация
__________________________________________________________________________

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


     ВВЕДЕНИЕ
     ________________________________________________________________

     Диск  является  распространенным  средством  для  более  или    менее
долговременного хранения данных.  Процессы  обработки  данных  на  твердом
диске (винчестере) аналогичны процессам для  гибких  дисков  (дискет),  за
исключением  того,  что возможно потребуется обеспечить пути для доступа к
многочисленным подоглавлениям винчестера.  Для  обработки  файлов  полезно
ознакомиться с организацией дисковой памяти.  Каждая cторона стандартной 5
1/4 дюймовой дискеты содержит 40 концентрических дорожек,  пронумерованных
от 00 до 39. На каждой дорожке форматируется восемь или девять секторов по
512 байтов каждый.
     Данные записываются  на диск в виде файлов,  аналогично тому,  как вы
записываете ассемблерные программы.  Хотя на типы  данных,  которые  можно
хранить   в   файле,   не   существует  каких-либо  ограничений,  типичный
пользовательский  файл  содержит  списки  заказчиков,  описи   товаров   и
предложений или списки имен и адресов. Каждая запись содержит информацию о
конкретном заказчике или описание товара.  Внутри файла все  записи  имеют
одинаковую  длину  и  формат.  Запись  может  содержать oдно или несколько
полей.  Файл заказчиков,  например,  может состоять из записей,  в которые
входит номер заказчика,  имя заказчика и долговой баланс. Эти записи могут
быть  расположены  в  порядке  возрастания  номеров  заказчиков  следующим
образом:

       ---T---T-----¬---T---T-----¬---T---T-----¬   ---T---T-----¬
       ¦#1¦имя¦суммদ#2¦имя¦суммদ#3¦имя¦сумма¦...¦#n¦имя¦сумма¦
       L--+---+------L--+---+------L--+---+------   L--+---+------

     Для  программирования  дисковых  файлов  следует  в   общих    чертах
ознакомится только с концепцией  и  терминологией.  Если  в  данной  главе
размеры диска не указываются, то предполагается диск 5 1/4" формата.


     ЕМКОСТЬ ДИСКА
     ________________________________________________________________

     Емкость гибких дисков:

          Версия DOS       Число       Число      Число       Всего
            и тип         дорожек     секторов   байтов в    на двух
            диска        на стороне  на дорожке  секторе     сторонах

          До DOS 2.0          40         8         512        327 680
          DOS 2.0 и после     40         9         512        368 640
          Высокая плотность   80        15         512      1 228 800
          3 1/2"              80         9         512        737 280

     Емкость твердых дисков:

             Тип           Число       Число       Число       Всего
            диска         дорожек     секторов    байтов в    на 4-х
                         на стороне  на дорожке   секторе     сторонах

          10 мегабайт        306         17        512      10 653 696
          20 мегабайт        614         17        512      21.377.024

     Указание  стороны  (головки),  дорожки  или    сектора    на    диске
осуществляется по номеру.  Для стороны и дорожки отсчет ведется с 0, а для
сектора - с 1.


     ОГЛАВЛЕНИЕ ДИСКА (КАТАЛОГ)
     ________________________________________________________________

     Для  того,  чтобы  организовать  хранение  информации    на    диске,
операционная система DOS резервируют определенные сектора для своих  нужд.
Организация данных на дискете или на твердом диске существенно зависит  от
их емкости.  Форматированная двухсторонняя дискета с девятью секторами  на
дорожке содержит следующую системную информацию:

          Сторона Дорожка Сектор

               0     0     1       Запись начальной загрузки
               0     0     2-3     Таблица распределения файлов (FAT)
               0     0     4-7     Каталог
               1     0     1-3     Каталог
               1     0     4 ...   Файлы данных

     Область записей данных начинается с третьего сектора на  1-й  стороне
0-й дорожки и продолжается до девятого сектора. Следующие записи заносятся
на 0-ю сторону 1-й доpожки, затем на 1-ю сторону 1-й дорожки, затем на 0-ю
сторону 2-й дорожки и т.д. Такая особенность заполнения дисковой памяти на
противоположных дорожках  снижает  число  перемещений  головки  дисковода.
Данный метод используется как для гибких, так и для твердых дисков.
     При использовании утилиты FORMAT /S для форматизации дискеты,  модули
DOS IBMBIO.COM и IBMDOS.COM записывается в первые сектора области данных.
     Все файлы, даже меньшие 512 байт (или  кратные  512),  начинаются  на
границе сектора.  Для каждого файла DOS создает на нулевой  доpожке  диска
элемент оглавления.  Каждый такой элемент описывает имя,  дату,  размер  и
расположение файла на диске. Элементы оглавления имеют следующий формат:

Байт                     Назначение

0-7       Имя файла,  определяемое из программы,  создавшей  данный  файл.
          Первый байт может указывать на статус файла: шест.00 обозначает,
          что данный файл не используется,  шест.E5 - файл удален, шест.2E
          - элемент подоглавления.
8-10      Тип файла
11        Атрибут файла, определяющий его тип:
          шест.00 - обычный файл;
          шест.01 - файл можно только читать;
          шест.02 - "спрятанный" файл;
          шест.04 - системный файл DOS;
          шест.08 - метка тома;
          шест.10 - подоглавление;
          шест.20 - архивный файл (для твердого диска).
12-21     Зарезервировано для DOS.
22-23     Время дня, когда файл был создан или последний раз изменялся,  в
          следующим двоичном формате:

                            |чччччммммммссссс|

24-25     Дата создания или последнего изменения файла, сжатая в два слова
          в следующем двоичном формате:

                           |ггггггг|ммммддддд|

          где год начинается с 1980 и может принимать  значения  от  0  до
          119, месяц - от 1 до 12, а день - от 1 до 31.
26-27     Начальный кластер  файла.  Относительный  номер  последних  двух
          секторов каталога.  Первый файл  данных  (без  COM-модулей  DOS)
          начинается  на  относительном  кластере  002.  Текущая  сторона,
          дорожка и кластер зависят от емкости диска.
28-31     Размер файла в  байтах.  При  создании  файла  DOS  вычисляет  и
          записывает размер файла в это поле.

     Все поля в каталоге диска,  превышающие  один  байт,  записываются  в
обратной последовательности байтов.


     ТАБЛИЦА РАСПРЕДЕЛЕНИЯ ФАЙЛОВ
     ________________________________________________________________

     Назначение таблицы распределения файлов (FAT - File Allocation Table)
- распределение дискового пространства для файлов.  Если вы создаете новый
файл или изменяете существующий, то DOS меняет элементы таблицы  файлов  в
соответствии с расположением файла на  диске.  Запись  начальной  загрузки
находится на секторе 1, далее на секторе 2 начинается  FAT.  FAT  содержит
элементы для каждого кластера, длина элементов FAT зависит  от  устройства
дисковой памяти.  Кластер для односторонних дискет представляет собой один
сектор, для двухсторонних дискет - смежную пару секторов.  Одно  и  то  же
число  элементов  в  FAT  определяет  в  два  pаза  больше   данных    для
двухсторонних дискет, чем для односторонних.
     Первые байты FAT определяют тип устройства:

               FE   Односторонняя на 8 секторов
               FC   Односторонняя на 9 секторов
               FF   Двухсторонняя на 8 секторов
               FD   Двухсторонняя на 9 секторов
               F9   Повышенная емкость (1,2 мегабайта)
               F8   Твердый диск

     Второй и  третий  байты  пока  содержат  FFFF.  В  следующей  таблице
показана организация данных  для  нескольких  типов  устройств  (приведены
начальные и конечные  номера  секторов).  Колонка  "Кластер"  представляет
число секторов в кластере:

          Устройство диска         Запись   FAT  Каталог Кластер
                                   нач.загр.
          Односторонний, 8 секторов    1    2-3     4-7     1
          Односторонний, 9 секторов    1    2-5     6-9     1
          Двухсторонний, 8 секторов    1    2-3     4-10    2
          Двухсторонний, 9 секторов    1    2-5     6-12    2
          Повышенная емкость (1,2 М)   1    2-15   16-29    1
          Твердый диск XT              1    2-17   18-49    8
          Твердый диск AT              1    2-838   4-115   4

     Начиная с четвертого байта, элементы FAT определяют  сектора.  Каждый
такой элемент имеет длину 12 битов. (В версии DOS 3 и старше элементы  FAT
для твердого диска могут иметь длину 16 битов).  Два первых элемента  FAT,
известные как относительные сектора 000 и 001,  соответственно,  указывают
на два последних сектора оглавления, определяя его размер и формат. Первый
файл данных начинается на относительном секторе 002.  Каждый  элемент  FAT
состоит из трех  шест.цифр  (12  битов),  которые  указывают  на  характер
использования конкретного сектора:

          000  свободный кластер,
          nnn  относительный номер следующего кластера для файла,
          FF7  неиспользуемый кластер (сбойная дорожка),
          FFF  последний кластер файла.

     Предположим, например, что дискета содержит только один файл с именем
PAYROLL.ASM, занимающий относительные сектора  002,  003  и  004.  Элемент
оглавления для этого файла содержит имя файла PAYROLL, тип - ASM,  шест.00
для обычного файла, дату создания,  002  -  номер  первого  относительного
сектора файла и размер файла в битах.  Таблица FAT  в  этом  случае  может
выглядеть следующим образом  (кроме  того,  что  в  каждой  паре  байты  в
обратной последовательности):

          Элемент FAT:        |FDF|FFF|003|004|FFF|000|000|...|000|
          Относительн.сектор:   0   1   2   3   4   5   6  ...конец

     Первые  два  элемента  FAT  указывают  расположение    каталога    на
относительных секторах 000 и  001.  Для  ввода  рассматриваемого  файла  в
память, система выполняет следующие действия:

          1. DOS получает доступ к дискете и ищет в каталоге имя PAYROLL и
     тип ASM.
          2.  Затем  DOS  определяет  по  каталогу    положение    первого
     относительного сектора  файла  (002)  и  загружает  содержимое  этого
     сектора в буферную область в основной памяти.
          3.  Номер  второго  сектора  DOS  получает  из  элемента    FAT,
     соответствующего  относительному  сектору    002.    Из    диаграммы,
     приведенной  выше,  видно,  что  этот  элемент  содержит  003.    Это
     обозначает, что файл продолжается в относительном  секторе  003.  DOS
     загружает содержимое этого сектора в буфер в основной памяти.
          4.  Номер  третьего  сектора  DOS  получает  из  элемента   FAT,
     соответствующего относительному сектору 003.  Этот  элемент  содержит
     004, значит  файл  продолжается  в  относительном  секторе  004.  DOS
     загружает содержимое этого сектора в буфер в основной памяти.
          5. Элемент FAT для относительного сектора 004 содержит шест.FFF,
     что свидетельствует о том, что больше нет данных для этого файла.

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

          - Умножить 15 на 1,5, получим 22,5.
          -  Выполнить  выборку  содержимого  байтов  22  и  23  из   FAT.
     Предположим, что они содержат F*FF.
          - Переставить байты: FFF*.
          - Так как номер 15-нечетный, то первые три цифры - FFF указывают
     на отсутствие других кластеров для данного файла.

     Теперь  рассмотрим  файл,  который    занимает    четыре    кластера,
начинающихся с номера 15. Таблица FAT, начиная с байта 22 и далее, в  этот
pаз показана в правильной обратной последовательности байтов в паpах:

               6* 01 17 80 01 FF*F

Для того, чтобы найти первый элемент FAT, необходимо умножить 15  на  1,5,
получим 22,5, и выбрать содержимое  байтов  22  и  23,  как  в  предыдущем
примере.  В этот раз эти байты содержат 6*01, что после перестановки  байт
даст 016*.  Так как 15-число нечетное, то используются  первые  три  цифры
016. Второй кластер для файла, следовательно, имеет номер 016.
     Для того, чтобы найти третий кластер, необходимо умножить 16  на  1,5
получим 24. Затем следует выбрать содержимое байтов 24 и 25  таблицы  FAT.
Значение 1780 после перестановки  байтов  даст  8017.  Так  как  число  16
четное, то используются последние три цифры 017. Третий кластер для  файла
имеет номер 017.
     Для того, чтобы найти четвертый кластер, необходимо  умножить  17  на
1,5, получим 25.5. Затем следует выбрать содержимое байтов 25 и 26 таблицы
FAT.  Значение 8001 после перестановки байтов даст 0180. Так как число  17
нечетное, то используются первые три  цифры  018.  Четвертый  кластер  для
файла имеет номер 018.
     При использовании  этой  же  процедуры  для  локализации  содержимого
следующего элемента FAT по относительным адресам 27 и  28,  получим  FF*F,
что после перестановки даст *FFF.  Так как число 18  четное,  используются
последние три цифры FFF, что обозначает последний элемент.
     Как было ранее сказано, все файлы  начинаются  на  границе  кластеpа.
Кроме того,  совсем  не  обязательно  файл  должен  храниться  в  соседних
кластерах, он может быть разбросан на диске по разным секторам.
     Если в программе необходимо определить тип установленного  диска,  то
можно обратиться к таблице FAT непосредственно, или, что предпочтительней,
использовать функцию DOS 1BH или 1CH.


     ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
     ________________________________________________________________

     - Независимо от размеров все файлы начинаются на границе кластера.

     - Оглавление  (каталог)  содержит для каждого файл на диске элементы,
определяющие имя, тип, атрибуты, дату, начальный сектор и pазмер файла.

     - Таблица  распределения  файлов  (FAT)  содержит  один  элемент  для
каждого кластеpа в каждом файле.


     ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
     ________________________________________________________________

     15.1. Какую длину в байтах имеет стандартный сектор?

     15.2. Где расположена запись начальной загрузки?

     15.3. Как обозначаются в оглавлении удаленные файлы?

     15.4. Какие  дополнительные  действия  выполняются  при  форматизации
дискеты по команде DOS FORMAT /S?

     15.5. Где и каким образом обозначается в таблице FAT, что устройством
является твердый диск?

     15.6. Имеется файл размером 2890 (десятичное) байтов: а)  Где  хранит
cистема размер файла? б) Как выражается этот  размер  в  шестнадцатиричном
формате? в) Покажите значение в том виде, как оно записывается системой.



ГЛАВА 16                    Дисковая память II: Функции базовой версии DOS
__________________________________________________________________________

     Ц е л ь: Раскрыть  основные  требования  к  программированию  функций
базовой версии DOS для обработки дисковых файлов.


     ВВЕДЕНИЕ
     ________________________________________________________________

     В начале данной главы рассматриваются  функции  базовой  версии  DOS,
определяющие  блок  управления  файлом  (FCB),  а  затем  будут   показаны
возможности создания и обработки дисковых файлов последовательным и прямым
доступом. Все рассматриваемые операции были введены в первых версиях DOS и
возможны во всех последующих версиях.
     Обработка дисковых файлов в базовой DOS  включает  определение  блока
управления файлом (FCB - file control block), который описывает файл и его
записи.  Передача адреса блока FCB в DOS  обязательна  для  всех  дисковых
операций  ввода-вывода.  Новых  команд  ассемблера  в  данной  главе    не
потребуется.
     Управление вводом и выводом осуществляется специальными прерываниями.
Запись файла на диск требует, чтобы прежде он был "создан"  и  DOS  смогла
сгенерировать соответствующий элемент в оглавлении. Когда все записи файла
будут записаны, программа должна "закрыть" файл, так, чтобы DOS  завершила
обработку оглавления.  Чтение файла требует, чтобы он был сначала "открыт"
для того, чтобы убедиться  в  его  существовании.  Так  как  записи  имеют
фиксированную длину  и  в  силу  соответствующей  организации  оглавления,
обработка  записей    дискового    файла    может    осуществляться    как
последовательно, так и произвольно.
     Метод  доступа  к  дисковой  памяти,  поддерживающий    использование
оглавления, "блокирование"  и  "разблокирование"  записей,  обеспечивается
прерыванием DOS  21H.  Более  низкий  уровень,  обеспечивающий  абсолютную
адресацию дисковых секторов,  также  через  DOS,  выполняется  посредством
прерываний 25H и 26H. Самый низкий уровень обеспечивается прерыванием BIOS
13H, которое позволяет выполнить произвольную адресацию в дисковой  памяти
по  номеру  дорожки  и  сектора.  Методы  DOS    осуществляют    некоторую
предварительную обработку   до   передачи   управления  в  BIOS.  В  гл.17
объясняется применение предпочтительных  функций  расширенного  DOS  2,  а
гл.18 представляет основные дисковые операции в BIOS.  Напоминание: Термин
кластер определяет один или более секторов  с  данными  в  зависимости  от
дискового устройства.


     БЛОК УПРАВЛЕНИЯ ФАЙЛОМ (FCB)
     ________________________________________________________________

     Для  выполнения  операций  ввода-вывода  на  диске  в  базовой    DOS
необходимо в области данных определить блок FCB.  Блок FCB не поддерживает
путь  доступа  к  файлу,  поэтому  он  используется  главным  образом  для
обработки файлов в текущей директории.  Блок FCB содержит описание файла и
его  записей  в  приведенном    ниже    формате.    Пользователь    должен
инициализировать байты 0-15 и 32-36, байты 16-31 устанавливаются DOS:

Байты                              Назначение

0         Указывает дисковод: 01 для дисковода A, 02 для B и т.д.
1-8       Имя файла,  выравненное по левой границе с конечными  пробелами,
          если имя меньше 8 байт.  Поле может содержать  зарезервированные
          имена, например, LPT1 для принтера.
9-11      Тип файла для дополнительной идентификации,  например,  DTA  или
          ASM. Если тип файла меньше трех байт, то он должен быть выравнен
          по левой границе и дополнен конечными пробелами.  DOS хранит имя
          и тип файла в оглавлении.
12-13     Номер текущего блока. Блок содержит 128 записей. Для локализации
          конкретной записи  используется  номер  текущего  блока  и номер
          текущей записи (байт 32).  Первый  блок  файла  имеет  номер  0,
          второй - 1 и т.д. Операция открытия файла устанавливает в данном
          поле 0.
14-15     Логический  размер  записи.   Операция  открытия  инициализирует
          размер записи значением 128 (шест.80).  После открытия  и  перед
          любой  операцией  чтения или записи можно устанавливать в данном
          поле любое требуемое значение длины записи.
16-19     Размер файла.  При создании файла DOS вычисляет и записывает это
          значение (произведение  числа  записей  на  размер  записей)   в
          оглавление.   Операция   открытия   выбирает   размер  файла  из
          оглавления и заносит его в данное поле.  Программа может  читать
          это поле, но не может менять его.
20-21     Дата.   При  создании  или  последней  модификации   файла   DOS
          записывает дату в оглавление. Операция открытия выбирает дату из
          оглавления и заносит в данное поле.
22-31     Зарезервировано для DOS.
32        Текущий номер записи.  Данное поле содержит текущий номер записи
          (0-127) в  текущем блоке (см.  байты 12-13).  Система использует
          текущие  значения  блока  и  записи  для  локализации  записи  в
          дисковом файле. Обычно номер начальной записи в данном поле - 0,
          но его можно заменить для начала последовательной  обработки  на
          любое значение от 0 до 127.
33-36     Относительный  номер  записи.   Для  произвольного  доступа  при
          операциях чтения   или   записи  данное  поле  должно  содержать
          относительный номер записи.  Например,  для произвольного чтения
          записи  номер 25 (шест.19),  необходимо установить в данном поле
          шест.19000000. Произвольный  доступ  характеризуется  тем,   что
          система  автоматически  преобразует относительный номер записи в
          текущие  значения  блока  и   записи.   Ввиду   ограничения   на
          максимальный   размер   файла  (1.073.741.824  байтов),  файл  с
          короткими  записями  может  содержать  больше  записей  и  иметь
          больший  относительный  номер записи.  Если размер записи больше
          64, то байт 36 всегда содержит 00.

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


     ИСПОЛЬЗОВАНИЕ БЛОКА FCB ДЛЯ СОЗДАНИЯ ФАЙЛА НА ДИСКЕ
     ________________________________________________________________

     Для  ссылки  на  каждый  дисковый  файл  программа  должна  содержать
правильно составленный блок управления файлом.  Операции  ввода-вывода  на
диск требуют установки адреса блока FCB в  регистре  DX.  Доступ  к  полям
блока FCB осуществляются по этому адресу с помощью регистровой пары DS:DX.
Для  создания  нового  файла  программа  использует  функцию  шест.16    в
прерывании DOS INT 21H следующим образом:

               MOV  AH,16H     ;Создание
               LEA  DX,FCBname ; дискового файла
               INT  21H        ;Вызов DOS

     DOS  осуществляет  поиск  имени  файла  и  тип  файла,  взятого    из
соответствующих  полей  FCB,  в  оглавлении.  Если  элемент    оглавления,
содержащий  необходимое  имя  (и  тип),  будет  найдено,  то  DOS  очищает
найденный элемент для нового использования, если такой  элемент  не  будет
найден, то DOS ищет свободный элемент. Затем операция устанавливает размер
файла в 0 и  "открывает"  файл.  На  этапе  открытия  происходит  проверка
доступного    дискового    пространства,    результат    такой    проверки
устанавливается в регистре AL:

               00   На диске есть свободное пространство
               FF   На диске нет свободного пространства.

     При открытии также устанавливается в блок FCB номер текущего блока  -
0 и размер записей (по умолчанию) -  128  (шест.80)  байтов.  Прежде,  чем
начать запись файла, можно заменить это значение по умолчанию на требуемый
размер записей.
     Для  определения  выводной  записи  необходимо   прежде    обеспечить
начальный адрес этой записи в область передачи данных (DTA - disk trausfer
area).  Так как блок FCB содержит размер записей, то в  DTA  не  требуется
устанавливать ограничитель конца записи.  Затем с помощью функции  шест.1A
необходимо сообщить DOS адрес DTA.  В  любой  момент  времени  может  быть
активен только один DTA. В следующем примере инициализируется адрес DTA:

               MOV  AH,1AH         ;Установка адреса
               LEA  DX,DTAname     ; DTA
               INT  21H            ;Вызов DOS

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

               MOV  AH,15          ;Последовательная
               LEA  DX,FCBname     ; запись
               INT  21H            ;Вызов DOS

     Операция записи использует информацию из блока FCB и  адрес  текущего
буфера DTA.  Если длина записи равна размеру сектора, то запись  заносится
на диск.  В противном случае записи заполняют буфер  по  длине  сектора  и
затем буфер записывается на  диск.  Например,  если  длина  каждой  записи
составляет 128 байтов,  то буфер заполняется четырьмя записями (4*128=512)
и затем буфер записывается в дисковой сектор.
     После успешного занесения записи на диск DOS увеличивает в блоке  FCB
размер файла на размер записи и текущий номер записи  на  1.  Когда  номер
текущей записи достигает 128, происходит сброс этого значения в 0 и в  FCB
увеличивается номер текущего блока на 1. Операция возвращает в регистре AL
следующие коды:

               00   Успешная запись.
               01   Диск полный.
               02   В области DTA нет места для одной записи.

     Когда запись файла завершена, можно, хотя и  не  всегда  обязательно,
записать маркер конца файла (шест.1A).  Для  закрытия  файла  используется
функция шест.10:

               MOV  AH,10H         ;Закрыть
               LEA  DX,FCBname     ; файл
               INT  21H            ;Вызов DOS

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

               00   Успешная запись.
               FF   Описание файла оказалось в неправильном элементе
                    оглавления (возможно в результате смены дискеты).


     ПРОГРАММА: ИСПОЛЬЗОВАНИЕ FCB ДЛЯ СОЗДАНИЯ ФАЙЛА НА ДИСКЕ
     ________________________________________________________________

__________________________________________________________________________

        page    60,132
TITLE   FCBCREAT (EXE) Использование FCB для создания файла
;----------------------------------------------------------
STACKSG SEGMENT PARA STACK 'Stack'
        DW      80 DUP(?)
STACKSG ENDS
;----------------------------------------------------------
DATASG  SEGMENT PARA 'Data'
RECLEN  EQU     32
NAMEPAR LABEL   BYTE            ;Список параметров:
MAXLEN  DB      RECLEN          ; макс.длина имени
NAMELEN DB      ?               ; число введенных символов
NAMEDTA DB      RECLEN DUP(' ') ; область передачи (DTA)

FCBREC  LABEL   BYTE            ;FCB для дискового файла
FCBDRIV DB      04              ; дисковод D
FCBNAME DB      'NAMEFILE'      ; имя файла
FCBEXT  DB      'DAT'           ; тип файла
FCBBLK  DW      0000            ; номер текущего блока
FCBRCSZ DW      ?               ; размер логической записи
FCBFLSZ DD      ?               ; размер файла (DOS)
        DW      ?               ; дата (DOS)
        DT      ?               ; зарезервировано (DOS)
FCBSQRC DB      00              ; номер текущей записи
        DD      ?               ; относительный номер

CRLF    DB      13,10,'$'
ERRCDE  DB      00
PROMPT  DB      'Name? ','$'
ROW     DB      01
OPNMSG  DB      '*** Open error ***',  '$'
WRTMSG  DB      '*** Write error ***', '$'
DATASG  ENDS
; ---------------------------------------------------------
CODESG  SEGMENT PARA 'Code'
BEGIN   PROC    FAR
        ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG
        PUSH    DS
        SUB     AX,AX
        PUSH    AX
        MOV     AX,DATASG
        MOV     DS,AX
        MOV     ES,AX
        MOV     AX,0600H
        CALL    Q10SCR          ;Очистить экран
        CALL    Q20CURS         ;Установить курсор
        CALL    C10OPEN         ;Открыть, установить DTA
        CMP     ERRCDE,00       ;Есть место на диске?
        JZ      A20LOOP         ; да - продолжить,
        RET                     ; нет - вернуться в DOS
A20LOOP:
        CALL    D10PROC
        CMP     NAMELEN,00      ;Конец ввода?
        JNE     A20LOOP         ; нет - продолжить,
        CALL    G10CLSE         ; да - закрыть файл
        RET                     ; и вернуться в DOS
BEGIN   ENDP
;               Открытие дискового файла:
;               ------------------------
C10OPEN PROC    NEAR
        MOV     AH,16H          ;Функция создания файла
        LEA     DX,FCBREC
        INT     21H
        CMP     AL,00           ;Есть место на диске?
        JNZ     C20             ; нет - ошибка

        MOV     FCBRCSZ,RECLEN  ;Размер записи (EQU)
        LEA     DX,NAMEDTA      ;Загрузить адрес DTA
        MOV     AH,1AH
        INT     21AH
        RET
C20:
        LEA     DX,OPNMSG       ;Сообщение об ошибке
        CALL    X10ERR
        RET
C10OPEN ENDP
;               Ввод с клавиатуры:
;               -----------------
D10PROC PROC    NEAR
        MOV     AH,09           ;Функция вывода на экран
        LEA     DX,PROMPT       ;Выдать запрос
        INT     21H

        MOV     AH,0AH          ;Функция ввода
        LEA     DX,NAMEPAR      ;Ввести имя файла
        INT     21H
        CALL    E10DISP         ;Прокрутка на экране

        CMP     NAMELEN,00      ;Имя введено?
        JNE     D20             ; да - продолжить,
        RET                     ; нет - выйти
D20:
        MOV     BH,00           ;Заменить символ Return
        MOV     BL,NAMELEN
        MOV     NAMEDTA[BX],' ' ;Записать пробел
        CALL    F10WRIT         ;Вызвать
                                ; подпрограмму записи
        CLD
        LEA     DI,NAMEDTA      ;Очистить
        MOV     CX,RECLEN / 2   ; поле
        MOV     AX,2020H        ; имени
        REP STOSW
        RET                     ;Выйти
D10PROC ENDP
;               Прокрутка и установка курсора:
;               -----------------------------
E10DISP PROC    NEAR
        MOV     AH,09           ;Функция вывода на экран
        LEA     DX,CRLF         ;CR/LF
        INT     21H             ;Вызов DOS
        CMP     ROW,18          ;Последняя строка экрана?
        JAE     E20             ; да - обойти,
        INC     ROW             ; нет - увеличить строку
        RET
E20:
        MOV     AX,0601H        ;Прокрутка на 1 строку
        CALL    Q10SCR
        CALL    Q20CURS         ;Установить курсор
        RET
E10DISP ENDP
;               Запись на диск:
;               --------------
F10WRIT PROC    NEAR
        MOV     AH,15H          ;Функция записи
        LEA     DX,FCBREC
        INT     21H
        CMP     AL,00           ;Запись без ошибок?
        JZ      F20             ; да
        LEA     DX,WRTMSG       ; нет -
        CALL    X10ERR          ; выдать сообщение
        MOV     NAMELEN,00
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
__________________________________________________________________________

     Рис.16.1. Создание дискового файла.


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

FCBDRIV   Программа должна создать файл на диске в дисководе 4 (или D).
FCBNAME   Имя файла - NAMEFILE.
FCBEXT    Тип файла - DAT.
FCBBLK    Начальное значение номера текущего блока - 0.
FCBRCSZ   Размер  записей   неопределен,   так   как   операция   открытия
          устанавливает в данном поле значение 128.
FCBSQRC   Начальное значение номера текущей записи - 0.

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

BEGIN     Инициализирует  сегментные  регистры,   вызывает   C10OPEN   для
          создания файла и установки адреса DTA для DOS,  вызывает D10PROC
          для ввода имени файла.  Если ввод пустой,  то  происходит  вызов
          G10PROC для завершения программы.
C10OPEN   Создает для файла элемент  в  директории,  устанавливает  размер
          записей -  32  (шест.20)  и  инициализирует адрес буфера DTA для
          DOS.
D10PROC   Выдает  запрос  на  ввод  имен,  вводит  имена  с  клавиатуры  и
          вызывает процедуру F10WRIT для записи вводимых имен на диск
E10DISP   Управляет прокруткой и установкой курсора.
F10WRIT   Записывает имена в дисковой файл.
G10CLSE   Записывает маркер конца файла и закрывает файл.
X10ERR    Выдает на экран сообщение  об  ошибке  в  случае  не  корректной
          операции создания файла или записи данных.

     Каждая операция записи автоматически добавляет  1  к  FCBSGRC  (номер
текущей записи) и шест.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.


     ПОСЛЕДОВАТЕЛЬНОЕ ЧТЕНИЕ ДИСКОВОГО ФАЙЛА
     ________________________________________________________________

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

               MOV  AH,OFH         ;Открытие
               LEA  DX,FCBname     ; файла
               INT  21H            ;Вызов DOS

     Операция открытия начинается с поиска в оглавлении элемента с  именем
и типом файла, определенными в FCB.  Если такой элемент не будет найден  в
оглавлении, то в регистре AL устанавливается шест.FF. Если элемент найден,
то в регистре AL устанавливается  00  и  в  FCB  заносится  действительный
размер  файла,  а  также  устанавливается номер текущего блока в 0,  длина
записи в шест.80.  После открытия можно заменить длину  записи  на  другое
значение.
     DTA должно содержать определение считываемой записи в соответствии  с
форматом, который использовался при создании файла.  Для установки  адреса
DTA используется функция шест.1A (не путать с  маркером  конца  файла  EOF
шест.1A) аналогично созданию дискового файла:

               MOV  AH,1AH         ;Установка
               LEA  DX,DTAname     ; адреса DTA
               INT  21H            ;Вызов DOS

     Для последовательного чтения записей  с  диска  используется  функция
шест.14:

               MOV  AH,14H         ;Последовательное
               LEA  DX,FCBname     ; чтение записей
               INT  21H            ;Вызов DOS

     Чтение  записи  с  диска  по  адресу  DTA  осуществляется  на  основе
информации в блоке  FCB.  Операция  чтения  устанавливает  в  регистре  AL
следующие коды возврата:

          00  Успешное чтение.
          01  Конец файла, данные не прочитаны.
          02  В DTA нет места для чтения одной записи.
          03  Конец файла, прочитана частичная запись, заполненная нулями.

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


     ПРОГРАММА: ИСПОЛЬЗОВАНИЕ FCB ДЛЯ ЧТЕНИЯ ДИСКОВОГО ФАЙЛА
     ________________________________________________________________

__________________________________________________________________________

TITLE   FCBREAD (EXE) Чтение записей созданных в CREATDSK
; -------------------------------------------------------
STACKSG SEGMENT PARA STACK 'Stack'
        DW      80 DUP(?)
STACKSG ENDS
;--------------------------------------------------------
DATASG  SEGMENT PARA 'Data'
FCBREC  LABEL   BYTE            ;FCB для файла
FCBDRIV DB      04              ; дисковод D
FCBNAME DB      'NAMEFILE'      ; имя файла
FCBEXT  DB      'DAT'           ; тип файла
FCBBLK  DW      0000            ; номер текущего блока
FCBRCSZ DW      0000            ; длина логической записи
        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
DATASG  ENDS
;--------------------------------------------------------
CODESG  SEGMENT PARA 'Code'
BEGIN   PROC    FAR
        ASSUME  CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG
        PUSH    DS
        SUB     AX,AX
        PUSH    AX
        MOV     AX,DATASG
        MOV     DS,AX
        MOV     ES,AX
        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     X,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
        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
Q1OSCR  ENDP
;               Установка курсора:
;               -----------------
Q20CURS PROC    NEAR
        MOV     AH,02
        MOV     BH,00
        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
__________________________________________________________________________

     Рис.16.2. Чтение дискового файла


     На рис.16.2 приведена  программа,  которая  выполняет  чтение  файла,
созданного предыдущей программой, и вывод на экран имен из записей  файла.
Обе программы содержат идентичные блоки 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.


     ПРЯМОЙ ДОСТУП
     ________________________________________________________________

     До сих пор в этой главе  рассматривалась  последовательная  обработка
дисковых файлов, которая адекватна как  для  создания  файла,  так  и  для
печати его содержимого или внесения  изменений  в  небольшие  файлы.  Если
программа ограничена только возможностью  последовательной  обработки,  то
для изменения файла она должна считывать каждую запись, вносить  изменения
в определенные из них и заносить записи в  другой  файл  (программа  может
использовать один  DTA,  но  потребуются  различные  блоки  FCB).  Обычной
практикой является чтение входного файла с диска A и  запись  обновленного
файла на диск  B.  Преимущество  этого  способа  состоит  в  том,  что  он
автоматически оставляет резервную копию.
     В некоторых случаях применяется доступ к конкретным записям файла для
получения  информации,  например,  нескольких  служащих  или    о    части
ассортимента  товаров.  Для  доступа,  скажем,  к  300-ой  записи   файла,
последовательная обработка должна включать чтение всех 299  предшествующих
записей, пока не будет получена 300-я запись. П р и м е ч а н и е: система
может начать обработку с конкретного номера блока и записи).
     Несмотря на то, что файл создается последовательно, доступ к  записям
может быть последовательным или прямым (произвольным).  Требования  прямой
обработки, использующей вызов  DOS,  заключаются  в  установке  требуемого
номера записи в соответствующее поле FCB и выдаче команды  прямого  чтения
или записи.
     Произвольный доступ  использует  относительный  номер  записи  (байты
33-36) в блоке FCB. Поле имеет размер двойного слова и использует обратную
последовательность байт в словах. Для локализации требуемой записи система
автоматически преобразует относительный  номер  записи  в  номер  текущего
блока (байты 12-13) и номер текущей записи (байт 32).


                              Пpямое чтение
                             ---------------
     Операции открытия и установки DTA одинаковы как для прямой, так и для
последовательной обработки.  Предположим, что программа  должна  выполнить
прямой доступ к пятой записи файла.  Установим значение 05 в поле FCB  для
относительного номера записи и выполним  команды  для  прямого  чтения.  В
результате успешной операции содержимое пятой записи будет помещено в DTA.
     Для прямого чтения записи  необходимо  поместить  требуемое  значение
относительного номера записи в FCB и вызвать функцию шест.21:

               MOV  AH,21H         ;Запрос на
               LEA  DX,FCBname     ; прямое чтение
               INT  21H            ;Вызов DOS

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

               00   Успешное завершение
               01   Данные не доступны
               02   Чтение прекращено из-за нехватки места в DTA
               03   Прочитана частичная запись, заполненная нулями.

     Как видно, среди перечисленных кодов возврата  отсутствует  состояние
конец файла.  При корректном чтении записи предполагается единственный код
возврата  -  00.  Остальные  коды  возврата  могут  являться   результатом
установки неправильного  относительного  номера  записи  или  некорректная
установка адреса DTA или FCB.  Так как такие ошибки  легко  допустить,  то
полезно выполнять проверку регистра AL на ненулевое значение.
     Когда программа выдает первый  запрос  на  прямую  запись,  операция,
используя  оглавление  для  локализации  сектора,  на  котором   находится
требуемая запись, считывает весь сектор  с  диска  в  буфер  и  пересылает
запись в DTA.  Предположим, например, что записи имеют  размер  128  байт,
т.е. четыре записи в одном секторе.  Запрос на  прямое  чтение  записи  23
приводит к чтению в буфер четырех записей, лежащих в одном секторе:

            | запись 20 | запись 21 | запись 22 | запись 23 |

     Когда программа вновь выдаст прямой запрос на запись,  например,  23,
то операция сначала проверит содержимое буфера.  Так как данная запись уже
находится в буфере,  то  она  непосредственно  пересылается  в  DTA.  Если
программа запросит  запись  35,  который  нет  в  буфере,  операция  через
оглавление локализует требуемую запись, считает  весь  сектор  в  буфер  и
поместит запись в DTA.  Таким образом, операции прямого доступа к  записям
более эффективны, если номера записей близки друг к другу.


                              Пpямая запись
                             ---------------
     Операция создания файла и установки DTA одинаковы  как  для  прямого,
так и для последовательного доступа.  Для обработки  файла  учета  товаров
программа может, используя  прямой  доступ,  считать  необходимую  запись,
внести, введенные вручную, изменения (например, новое количество  товаров)
и вернуть запись на диск на то же место. Операция прямой записи использует
относительный номер  записи  в  блоке  FCB  и  функцию  шест.22  следующим
образом:

               MOV  AH,22H         ;Запрос на
               LEA  DX,FCBname     ; прямую запись
               INT  21H            ;Вызов DOS

     Операция устанавливает в регистре AL следующие коды возврата:

          00  Успешная операция
          01  На диске нет места
          02  Операция прекращена в результате недостаточного места в DTA.

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


     ПРОГРАММА: ПРЯМОЕ ЧТЕНИЕ ДИСКОВОГО ФАЙЛА
     ________________________________________________________________

        page    60,132
TITLE   RANREAD (COM) Прямое чтение записей,
;                        созданных в FCBCREAT
CODESG  SEGMENT PARA 'Code'
        ASSUME  CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG
        ORG     100H
BEGIN:  JMP     MAIN
;-----------------------------------------------------
FCBREC  LABEL   BYTE            ;FCB для дискового файла
FCBDRIV DB      04              ; дисковод D
FCBNAME DB      'MAMEFILE'      ; имя файла
FCBEXT  DB      'DAT'           ; тип файла
FCBBLK  DW      0000            ; номер текущего блока
FCBRCSZ DW      0000            ; длина логической записи
        DD      ?               ; размер файла (DOS)
        DW      ?               ; дата (DOS)
        DT      ?               ; зарезервировано (DOS)
        DB      00              ; номер текущей записи
FCBRNRC DD      000000000       ; относительный номер

RECLEN  EQU     32              ;Длина записи
RECDPAR LABEL   BYTE            ;Список параметров:
MAXLEN  DB      3               ;
ACTLEN  DB      ?               ;
RECDNO  DB      3 DUP(' ')      ;

NAMEFLD DB      RECLEN DUP(' '),13,10,'$' ;DTA

OPENMSG DB      '*** Open error ***',13,10,'$'
READMSG DB      '*** Read error ***',13,10,'$'
COL     DB      00
PROMPT  DB      'Record number? $'
ROW     DB      00
ENDCDE  DB      00
;-----------------------------------------------------
MAIN    PROC    NEAR
        CALL    Q10CLR          ;Очистить экран
        CALL    Q20CURS         ;Установить курсор
        CALL    C10OPEN         ;Открыть файл,
                                ; установить DTA
        CMP     ENDCDE,00       ;Открытие без ошибок?
        JZ      A20LOOP         ; да - продолжить,
        RET                     ; нет - завершить
A20LOOP:
        CALL    D10RECN         ;Получить номер записи
        CMP     ACTLEN,00       ;Есть запрос?
        JE      A40             ; нет - выйти
        CALL    F10READ         ;Чтение (прямой доступ)
        CMP     ENDCDE,00       ;Есть ошибки чтения?
        JNZ     A30             ; да - обойти
        CALL    G10DISP         ;Вывести на экран
A30:
        JMP     A20LOOP
A40:    RET                     ;Завершить программу
MAIN    ENDP
;               Подпрограмма открытия файла на диске:
;               ------------------------------------
C10OPEN PROC    NEAR
        MOV     AH,0FH          ;Функция открытия
        LEA     DX,FCBREC
        INT     21H
        CMP     AL,00           ;Открытие нормальное?
        JNZ     C20             ; нет - ошибка
        MOV     FCBRCSZ,RECLEN  ;Длина записи (EQU)
        MOV     AH,1AH
        LEA     DX,NAMEFLD      ;Установить адрес DTA
        INT     21H
        RET
C20:
        LEA     DX,OPENMSG
        CALL    X10ERR
        RET
C10OPEN ENDP
;               Ввод с клавиатуры номера записи:
;               -------------------------------
D10RECN PROC    NEAR
        MOV     AH,09H          ;Функция вывода на экран
        LEA     DX,PROMPT
        INT     21H
        MOV     AH,0AH          ;Функция ввода с клавиатуры
        LEA     DX,RECDPAR
        INT     21H
        CMP     ACTLEN,01       ;Проверить длину (0,1,2)
        JB      D40             ;Длина 0, завершить
        JA      D20
        SUB     AH,AH           ;Длина 1
        MOV     AL,RECDNO
        JMP     D30
D20:
        MOV     AH,RECDNO       ;Длина 2
        MOV     AL,RECDNO+1
D30:
        AND     AX,0F0FH        ;Удалить ASCII тройки
        AAD                     ;Преобразовать в двоичное
        MOV     WORD PTR FCBRNRC,AX
D40:
        MOV     COL,20
        CALL    Q20CURS         ;Установить курсор
        RET
D10RECN ENDP
;               Чтение дисковой записи:
;               ----------------------
F10READ PROC    NEAR
        MOV     ENDCDE,00       ;Очистить код завершения
        MOV     AH,21H          ;Функция прямого чтения
        LEA     DX,FCBREC
        INT     21H
        CMP     AL,00           ;Чтение без ошибок?
        JZ      F20             ; да - выйти
        LEA     DX,READMSG      ; нет - выдать
        CALL    X10ERR          ; сообщение об ошибке
F20:    RET
F10READ ENDP
;               Вывод имени на экран:
;               --------------------
G10DISP PROC    NEAR
        MOV     AH,09           ;Функция вывода на экран
        LEA     DX,NAMEFLD
        INC     21H
        INC     ROW
        MOV     COL,00
        RET
G10DISP ENDP
;               Очистка экрана:
;               --------------
Q10CLR  PROC    NEAR
        MOV     AX,0600H        ;Функция прокрутки
        MOV     BH,41H          ;Цвет (07 для ч/б)
        MOV     CX,0000
        MOV     DX,184FH
        INT     10H
        RET
Q10CLR  ENDP
;               Установка курсора:
;               -----------------
Q20CURS PROC    NEAR
        MOV     AH,02           ;Функция установки
        MOV     BH,00           ; курсора
        MOV     DH,ROW
        MOV     DL,COL
        INT     10H
        RET
Q20CURS ENDP
;               Вывод сообщения об ошибке на диске:
;               ----------------------------------
X10ERR  PROC    NEAR
        MOV     AH,09           ;DX содержит адрес
        INT     21H             ; сообщения
        INC     ROW
        MOV     ENDCDE,01
        RET
X10ERR  ENDP
        CODESG  ENDS
        END     BEGIN
__________________________________________________________________________

     Рис.16.3. Прямое чтение дисковых записей.


     На рис.16.3 приведена программа, которая  считывает  файл,  созданный
предыдущей программой (см.  рис.16.1).  Вводя  любой  относительный  номер
записи,  лежащей в границах файла, пользователь запрашивает вывод на экран
любой записи файла.  Если файл содержит 25 записей,  то правильными номера
являются номера от 00 до 24. Номер вводится с клавиатуры в ASCII формате и
должен быть в нашем случае одно- или двузначным числом.
     Программа содержит следующие процедуры:

C10OPEN   Открывает файл,  устанавливает размер записи 32 и  устанавливает
          адрес DTA.
D10RECN   Вводит номер записи с клавиатуры,  преобразует  его  в  двоичный
          формат и  записывает  полученное  значение  в  FCB.  В  качестве
          усовершенствования  процедуры  можно вставить проверку вхождения
          номера в границы от 00 до 24.
F10READ   Помещает требуемую запись в DTA в соответствии  с  относительным
          номером записи в FCB.
G10DISP   Выводит запись на экран.

     Процедура D10RECN вводит номер записи с клавиатуры и проверяет  длину
ввода в списке параметров. Возможны три варианта:

               00   Запрошен конец обработки
               01   Введено однозначное число (в регистре AL)
               02   Введено двузначное число (в регистре AX)

     Данная процедура преобразует  введенное  число  из  ASCII  формата  в
двоичный формат.  Так как значение  находится  в  регистре  AX,  то  лучше
использовать команду AAD для преобразования. После преобразования двоичный
код из регистра AX пересылается в  два  левых  байта  поля  относительного
номера записи в блоке FCB.  Если,  например,  введено  число  12  в  ASCII
формате, то AX будет содержать 3132. Команда AND преобразует это  значение
в 0102, а команда AAD - в 000C.  Результат преобразования заносится в поле
относительного номера записи блока FCB в виде С000 0000.


     ПРЯМОЙ БЛОЧНЫЙ ДОСТУП
     ________________________________________________________________

     Если в программе имеется достаточно места,  то  одна  прямая  блочная
операция может записать весь файл из DTA на диск, а также  прочитать  весь
файл с диска в DTA.  Данная особенность весьма полезна для записи на  диск
таблиц, которые другие программы могут считывать в память для обработки.
     Начать можно с любого правильного относительного номера записи. Число
записей также может быть любым, хотя  блок  должен  находится  в  пределах
файла. Перед началом необходимо открыть файл и инициализировать DTA.
     Для операции прямой блочной записи необходимо установить  в  регистре
CX требуемое число записей, установить в FCB стартовый относительный номер
записи и выдать функцию шест.28:

               MOV  AH,28H         ;Операция прямой блочной записи
               MOV  CX,records     ;Установка числа записей
               LEA  DX,FCBname     ;
               INT  21H            ;Вызов DOS

     Операция преобразует относительный номер записи в текущие номер блока
и  номер  записи.  Полученные  значения  используются   для    определения
начального  адреса  на  диске.  В  результате  операции  в  регистре    AL
устанавливаются следующие коды возврата:

               00   Успешное завершение для всех записей
               01   На диске недостаточно места.

     Кроме того операция устанавливает в FCB в поле относительного  номера
записи и полях текущих номеров блока и  записи  значения,  соответствующие
следующему номеру записи.  Например, если были записаны записи с 00 до 24,
то следующий номер записи будет 25 (шест.19).
     Для операции прямого блочного чтения необходимо установить в регистре
CX требуемое число записей и использовать функцию шест.27:

               MOV  AH,27H         ;Операция прямого блочного чтения
               MOV  CX,records     ;Установка числа записей
               LEA  DX,FCBname     ;
               INT  21H            ;Вызов DOS

     Операция чтения возвращает в регистре AL следующие значения:

               00   Успешное чтение всех записей
               01   Прочитана последняя запись файла
               02   Прочитано предельное для DTA число записей
               03   Прочитана последняя запись файла не полностью.

     В регистре CX остается действительное число прочитанных записей, а  в
FCB в поле относительного номера записи и полях текущих  номеров  блока  и
записи устанавливаются значения, соответствующие следующему номеру записи.
     Если необходимо загрузить  в  память  весь  файл,  но  число  записей
неизвестно, то следует после операции открытия разделить размер  файла  на
длину записи.  Например, для размера файла шест.320 (800) и  длине  записи
шест.20 (32) число записей будет шест.19 (25).


     ПРОГРАММА: ПРЯМОЕ БЛОЧНОЕ ЧТЕНИЕ
     ________________________________________________________________

__________________________________________________________________________

TITLE   RANBLOK (COM) Прямое блочное чтение файла
CODESG  SEGMENT PARA 'Code'
        ASSUME  CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG
        ORG     100H
BEGIN:  JMP     MAIN
;----------------------------------------------------
FCBREC  LABEL   BYTE            ;FCB для дискового файла
FCBDRIV DB      04              ; дисковод D
FCBNAME DB      'NAMEFILE'      ; имя файла
FCBEXT  DB      'DAT'           ; тип файла
FCBBLK  DW      0000            ; номер текущего блока
FCBRCSZ DW      0000            ; логическая длина записи
FCBFLZ  DD      ?               ; DOS размер файла
        DW      ?               ; DOS дата
        DT      ?               ; DOS зарезервировано
        DB      00              ; номер текущей записи
FCBRNRC DD      00000000        ; относительный номер

DSKRECS DB      1024 DUP(?),'$' ;DTA для блока записей

ENDCODE DB      00
NORECS  DW      25              ;Число записей
OPENMSG DB      '*** Open error ***',13,10,'$'
READMSG DB      '*** Open error ***',13,10,'$'
ROWCTR  DB      00
; ---------------------------------------------------
MAIN    PROC    NEAR
        CALL    Q10CLR          ;Очистить экран
        CALL    Q20CURS         ;Установить курсор
        CALL    E10OPEN         ;Открыть файл,
                                ; установить DTA
        CMP     ENDCODE,00      ;Успешное открытие?
        JNZ     A30             ; нет - выйти
        CALL    F10READ         ;Читать записи
        CALL    G10DISP         ;Вывод блока на экран
A30:    RET                     ;Завершить программу
MAIN    ENDP
;               Открыть дисковый файл:
;               ---------------------
E10OPEN PROC    NEAR
        MOV     AH,0FH          ;Функция открытия файла
        LEA     DX,FCBREC
        INT     21H
        CMP     AL,00           ;Успешное открытие?
        JNZ     A30             ; нет - ошибка

        MOV     FCBRCSZ,0020H   ;Размер записи
        MOV     AH,1AH
        LEA     DX,DSKRECS      ;Установить адрес DTA
        INT     21H
        RET
E20:
        LEA     DX,OPENMSG      ;Ошибка открытия файла
        CALL    X10ERR
        RET
E10OPEN ENDP
;               Чтение блока:
;               ------------
F10READ PROC    NEAR
        MOV     AH,27H          ;Прямое чтение блока
        MOV     CX,NORECS       ;Число записей
        LEA     DX,FCBREC
        INT     21H
        MOV     ENDCODE,AL      ;Сохранить код возврата
        RET
F10READ ENDP
;               Вывод блока на экран:
;               --------------------
G10DISP PROC    NEAR
        MOV     AH,09           ;Функция вывода на экран
        LEA     DX,DSKRECS
        INT     21H
        RET
G10DISP ENDP
;               Подпрограмма очистки экрана:
;               ---------------------------
Q10CLR  PROC    NEAR
        MOV     AX,0600H        ;Функция скроллинга
        MOV     BH,41H          ;Цвет (07 для ч/б)
        MOV     CX,0000
        MOV     DX,184FH
        INT     10H
        RET
Q10CLR  ENDP
;               Подпрограмма установки курсора:
;               ------------------------------
Q20CURS PROC    NEAR
        MOV     AH,02           ;Функция установки курсора
        MOV     BH,00
        MOV     DH,ROWCTR
        MOV     DL,00
        INT     10H
        INC     ROWCTR
        RET
Q20CURS ENDP
;               Подпрограмма сообщения об ошибке диска:
;               --------------------------------------
X10ERR  PROC    NEAR
        MOV     AH,09           ;DX содержит адрес
        INT     21H             ; сообщения
        MOV     ENDCODE,01
        RET
X10ERR  ENDP

CODESG  ENDS
        END     BEGIN
__________________________________________________________________________

     Рис.16.4. Прямое блочное чтение.


     На рис.16.4 приведена программа, выполняющая  блочное  чтение  файла,
созданного  программой  на  рис.16.1.  Программа  устанавливает  начальный
относительный номер записи 00, в регистре CX - счетчик  на  25  записей  и
выводит на экран всю информацию из DTA (только для того, чтобы  убедиться,
что  информация  считана).  Другие  варианты  программы  могут    включать
установку другого начального номера записи и считывание менее 25 записей.
     В программе организованы следующие процедуры:

E10OPEN   Открывает файл,  устанавливает размер записи в FCB равным  32  и
          устанавливает адрес DTA.
F10READ   Устанавливает число записей равным 25 и выполняет блочное чтение
G10DISP   Выводит блок на экран.

     Операция чтения преобразует относительный номер записи  00  в  FCB  в
номер текущего блока 00 и номер текущей записи 00. В конце операции чтения
в FCB текущий номер записи будет содержать шест.19, а относительный  номер
записи - шест.19000000.


     АБСОЛЮТНЫЕ ОПЕРАЦИИ ДИСКОВОГО ВВОДА-ВЫВОДА
     ________________________________________________________________

     Для непосредственного доступа к  диску  можно  использовать  операции
абсолютного чтения и абсолютной записи с помощью функций  DOS  INT  25H  и
26H.  В этом  случае  не  используются  оглавление  диска  и  преимущества
блокирования и разблокирования записей, обеспечиваемые  функцией  DOS  INT
21H.
     Абсолютные  операции  предполагают,  что  все  записи  имеют   размер
сектора, поэтому прямой доступ осуществляется к полному сектору или  блоку
секторов.  Адресация диска  выполняется  по  "логическому  номеру  записи"
(абсолютный  сектор).  Для  определения  логического  номера  записи    на
двухсторонних дискетах с девятью секторами счет секторов ведется с дорожки
0, сектора 1, следующим образом:

               Дорожка     Сектор       Логический номер записи

                  0           1                   0
                  0           2                   1
                  1           1                   9
                  1           9                  17
                  2           9                  26

     Для двухсторонних дискет используется следующая формула:

               Логический номер записи = (дорожка х 9) + (сектор - 1)

     Например,  логический  номер  записи  на  дорожке  2  и  секторе    9
определяется как

               (2 х 9) + (9 - 1) = 18 + 8 = 26

     Фрагмент программы для абсолютных операций ввода-вывода:

               MOV  AL,drive#      ;0 для A, 1 для B и т.д.
               MOV  BX,addr        ;Адрес области ввода-вывода
               MOV  CX,sectors     ;Число секторов
               MOV  DX,record#     ;Начальный логический номер записи
               INT  25H или 26H    ;Абсолютное чтение или запись

     Операции абсолютного чтения  или  запись  разрушают  содержимое  всех
регистров,  кроме  сегментных,  и  устанавливают  флаг  CF  для  индикации
успешной (0) или безуспешной (1) операции.  В случае безуспешной  операции
содержимое регистра AL описывает характер ошибки:

                    AL             Причина

               1000 0000      Устройство не отвечает
               0100 0000      Ошибка установки головок
               0010 0000      Ошибка контролера
               0001 0000      Ошибка дискеты?
               0000 1000      Переполнение DMA при чтении
               0000 0100      Сектор не найден
               0000 0011      Попытка записи на защищенной дискете
               0000 0010      Не найден адресный маркер

     Команда INT записывает содержимое флагового регистра  в  стек.  После
завершения команды INT следует восстановить флаги, но проверив перед  этим
флаг CF.


     ДРУГИЕ ДИСКОВЫЕ ОПЕРАЦИИ
     ________________________________________________________________

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


                           Сброс диска: Шест.D
                          ---------------------


Страницы книги разрезаны по 70Кб, чтобы они не были гигантскими и недолго грузились, так что нажмите "Далее" чтобы читать дальше.
Назад  Далее

Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS