Жанр: Учеба
Ассемблер и программирование для IBM PC
...мма должна
проверять достижение конца области DISAREA во избежание разрушения. Хотя
программа предназначена для вывода на экран только ASCII-файлов, она имеет
проверку для страховки от всяких неожиданных несимвольных файлов.
Процедура G10XFER выполняет следующее:
1. Инициализирует адрес области SECTOR.
2. Инициализирует адрес области DISAREA.
3. При достижении конца области SECTOR считывает следующий сектор. В
случае конца файла, завершает работу программы, иначе инициализирует
адрес области SECTOR.
4. При достижении конца области DISAREA вставляет символы CR/LF, выводит
строку на экран и инициализирует адрес DISAREA.
5. Переписывает символ из области SECTOR в область DISAREA.
6. По символу "конец файла" (шест.1A) завершает работу программы.
7. По символу "конец строки" (шест.OA) выводит на экран строку и
переходит на п.2, по другим символам идет на п.3.
Попробуйте выполнить эту программу в отладчике DEBUG. При каждом
вводе с диска просмотрите содержимое области ввода и обратите внимание на
то, как DOS форматирует записи. Для улучшения данной программы организуйте
вывод на экран запроса для указания пользователем имени и типа файла.
ДРУГИЕ ДИСКОВЫЕ ФУНКЦИИ В РАСШИРЕННОЙ ВЕРСИИ DOS
________________________________________________________________
Получение размера свободного дискового пространства: шест.36
--------------------------------------------------------------
Данная функция выдает информацию о дисковой памяти. Для выполнения
функции необходимо загрузить в регистр DL номер дисковода (0 - текущий
дисковод, 1 - A, 2 - B и т.д.):
MOV AH,36H ;Запрос на
MOV DL,0 ; текущий дисковод
INT 21H ;Вызов DOS
При указании неправильного номера дисковода операция возвращает в
регистре AX шест.FFFF, иначе следующие значения:
в AX число секторов на кластер,
в BX число доступных кластеров,
в CX число байтов на сектор,
в DX общее число кластеров на дисководе.
В версии DOS младше 2.0 для получения информации о дисковой памяти
следует использовать функцию шест.1B (получить информацию из таблицы FAT).
Удаление файла: шест.41
-------------------------
Для удаления файлов из программы (за исключением файлов с атрибутом
"только чтение") используется функция шест.41. При этом в регистре DX
необходимо загрузить ASCIIZ строку, содержащую путь доступа и имя файла:
MOV AH,41H ;Запрос на удаление
LEA DX,PATHNAM ;ASCIIZ-строка
INT 21H ;Вызов DOS
В случае ошибки в регистре AX возвращается код 02 (файл не найден)
или 05 (нет доступа).
Управление файловым указателем: шест.42
-----------------------------------------
Система DOS имеет файловый указатель, который при открытии файла
устанавливается в 0 и увеличивается на 1 при последовательных операциях
записи или считывания. Для доступа к любым записям внутри файла можно
менять файловый указатель с помощью функции шест.42, получая в результате
прямой доступ к записям файла.
Для установки файлового указателя необходимо поместить в регистр BX
файловый номер и в регистровую пару CX:DX требуемое смещение в байтах. Для
смещений до 65.535 в регистре CX устанавливается 0, а в DX - смещение. В
регистре AL должен быть установлен один из кодов, который определяет точку
отсчета смещения:
0 - смещение от начала файла.
1 - смещение текущего значения файлового указателя, которое может
быть в любом месте, включая начало файла.
2 - смещение от конца файла. Размер файла (и следовательно смещение
до конца файла) можно определить, установив регистровую пару
CX:DX в 0 и используя код 2 в регистре AL.
В следующем примере устанавливается файловый указатель на смещение
1024 байта от начала файла:
MOV AH,42H ;Установка указателя
MOV AL,00 ; от начала файла
LEA BX,HANDLE1 ;Установка файлового номера
MOV CX,00 ;
MOV DX,1024 ;Смещение 1024 байта
INT 21H ;Вызов DOS
JC error
Правильно выполненная операция сбрасывает флаг CF и возвращает новый
указатель в регистровой паре DX:AX. Неправильная операция устанавливает
флаг CF в 1 и возвращает в регистре AX код 01 (ошибка кода отсчета) или 06
(ошибка файлового номера).
Проверка или изменение атрибута: шест.43
------------------------------------------
Для проверки или изменения файлового атрибута в оглавлении диска
используется функция шест.43H. При этом в регистре DX должен быть
установлен адрес ASCIIZ строки. Для проверки атрибута регистр AL должен
содержать 00. Для изменения атрибута регистр AL должен содержать 01, а
регистр CX - новое значение атрибута. Следующий пример устанавливает
нормальный атрибут:
MOV AH,43H ;Запрос на установку
MOV AL,01 ; нормального
MOV CX,00 ; атрибута
LEA DX,PATHNM2 ;ASCIIZ-строка
INT 21H ;Вызов DOS
В случае проверки функция возвращает текущий атрибут файла в регистре
CX. В случае изменения функция устанавливает в соответствующем элементе
оглавления атрибут из регистра CX. Неправильная операция возвращает в
регистре AX коды ошибок 02, 03 или 05.
Получить текущее оглавление: шест.47
--------------------------------------
Определение текущего оглавления для любого дисковода осуществляется с
помощью функции шест.47. При этом необходимо определить область памяти
достаточно большую, чтобы содержать пути доступа максимальной длины и
загрузить адрес этой области в регистр DX. Регистр DL должен содержать
номер дисковода: 0 - текущий, 1 - A, 2 - B и т.д. В результате выполнения
операция помещает в область памяти имя текущей директории (без номера
дисковода), например, в следующем виде:
ASSEMBLE\EXAMPLES
Нулевой байт (шест.00) идентифицирует конец составного имени пути
доступа. Для корневой директории возвращаемое значение состоит только из
одного байта - шест.00. Таким образом можно получить текущее имя пути
доступа для любого файла в подоглавлении. Пример на рис.17.5 демонстрирует
использование данной функции.
__________________________________________________________________________
TITLE GETPATH (COM) Получить текущий каталог
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; -----------------------------------------------
PATHNAM DB 65 DUP(' ') ;Имя текущего пути доступа
; -----------------------------------------------
MAIN PROC NEAR
MOV AH,19H ;Определить текущий диск
INT 21H
ADD AL,41H ;Заменить шест.номер
MOV DL,AL ; на букву: 0=A, 1=B ...
CAL B10DISP ;Выдать номер дисковода,
MOV DL,':'
CAL B10DISP ; двоеточие,
MOV DL,'\'
CAL B10DISP ; обратную косую
MOV AH,47H ;Получить текущий каталог
MOV DL,00
LEA SI,PATHNAM
INT 21H
A10LOOP:
CMP BYTE PTR [SI],0 ;Конец имени пути доступа
JE A20 ; да - выйти
MOV AL,[SI] ;Выдать на экран
MOV DL,AL ; имя пути доступа
CALL B10DISP ; побайтно
INC SI
JMP A10LOOP
A20: RET ;Выход в DOS
MAIN ENDP
B10DISP PROC NEAR
MOV AH,02 ;в DL - адрес элемента
INT 21H ;Функция вывода на экран
RET
B10DISP ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.17.5. Получить текущий каталог.
Поиск файлов по шаблону: шест.4E и шест.4F
--------------------------------------------
Данные функции аналогичны функциям шест. 11 и 12 базовой версии DOS.
Функция 4E используется для начала поиска в оглавлении, а функция 4F - для
продолжения. Для начала поиска в регистр DX необходимо загрузить адрес
ASCIIZ-строки, содержащей имя пути доступа и шаблон поиска. Шаблон поиска
может включать в себя символы ? и *. В регистре CX должно быть значение
атрибута в любой комбинации битов (нормальный, оглавление, спрятанный или
системный).
MOV AH,4EH ;Запрос на начало поиска
MOV CX,00H ;Нормальный атрибут
LEA DX,PATHNM1 ;ASCIIZ-строка
INT 21H ;Вызов DOS
Если операция находит файл, удовлетворяющий шаблону поиска, то в
текущий буфер DTA в FCB заполняется следующей информацией:
00 - резервировано DOS для последующего поиска
21 - атрибут файла
22 - время файла
24 - дата файла
26 - размер файла: младшее слово, затем старшее слово
30 - имя и тип в виде 13-байтовой ASCIIZ строки, завершаемой шест.00.
В случае ошибки в регистре AX возвращается код 02 (не найдено) или 18
(нет больше файлов). Для продолжения поиска файлов (после функции шест.4E)
используется функция 4F. Между этими функциями не следует нарушать
содержимое DTA.
MOV AH,4FH ;Запрос на продолжение поиска
INT 21H ;Вызов DOS
Единственно возможный код в регистре AX - 18 (нет больше файлов). Обе
рассмотренные функции не меняют состояние флага CF.
Переименование файла: шест.56
-------------------------------
Для переименования файла используется функция шест.56. При этом в
регистр DX должен быть загружен адрес ASCIIZ-строки, содержащей старые
значения дисковода, пути доступа, имени и типа файла, а в регистр DI (в
действительности ES:DI) - адрес ASCIIZ-строки, содержащей новые значения
дисковода, пути доступа, имени и типа файла. Если указывается номер
дисковода, то он должен быть одинаков в обоих строках. Путь доступа может
быть различным, поэтому данная операция может не только переименовывать
файл, но и переносить его в другое подоглавление.
MOV AH,56H ;Запрос на переименование файла
LEA DX,oldstring ;DS:DX
LEA DI,newstring ;ES:DI
INT 21H ;Вызов DOS
В случае ошибки регистр AX возвращает коды 03 (путь доступа не
найден), 05 (нет доступа?) и 17 (разные дисководы).
Другие функции DOS, имеющие отношение к дисковым файлам, включают
создание подоглавления (шест.39), удаление элемента оглавления (шест.3A),
изменение текущего оглавления (шест. 3B), управление вводом-выводом для
устройств (шест.44), дублирование файлового номера (шест.45),
принудительное дублирование файлового номера (шест.46), получение
состояния проверки ? (шест.54).
ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
________________________________________________________________
- Многие функции расширенной версии DOS оперируют с ASCIIZ-строками,
которые содержат путь доступа и завершаются байтом, содержащим шест.00.
- Функции создания и открытия возвращают значение файлового номера,
который используется для последующего доступа к файлу.
- В случае ошибок многие функции устанавливают флаг CF и помещают код
ошибки в регистр AX.
- Как правило, функция создания используется для записи файла, а
открытия - для чтения.
- После того, как файл записан на диск, его необходимо закрыть для
того, чтобы в оглавление были внесены соответствующие изменения.
ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
________________________________________________________________
17.1. Какие значения кодов возврата для ситуаций "файл не найден" и
"ошибка файлового номера" ?
17.2. Определите ASCIIZ-строку по имени PATH1 для файла CUST.LST на
дисководе C.
17.3. Для предыдущего файла (п.17.2) напишите команды а) определения
элемента по имени CUSTHAN для файлового номера, б) создание файла, в)
записи файла из области CUSTOUT (128 байт) и г) закрытия файла. Обеспечьте
проверку на ошибки.
17.4. Для файла (п.17.3) напишите команды а) открытия файла и б)
чтения файла в область CUSTIN. Обеспечьте контроль ошибок.
17.5. В каких случаях необходимо закрывать файл, который был открыт
только для чтения ?
17.6. Измените программу на рис.17.4 так, чтобы пользователь мог
вводить с клавиатуры имя файла, который необходимо выдать на экран.
Обеспечьте возможность любого числа запросов и завершение программы только
по пустому запросу, т.е. простому нажатию клавиши Return.
ГЛАВА 18 Дисковая память IV: Функции BIOS
__________________________________________________________________________
Ц е л ь: Показать основные требования к программированию функций BIOS
для создания и чтения дисковых файлов.
ВВЕДЕНИЕ
________________________________________________________________
Для дисковых операций можно программировать непосредственно на уровне
BIOS, хотя BIOS и не обеспечивает автоматически использование оглавления
или блокирование/деблокирование записей. Дисковая операция BIOS INT 13H
рассматривает все "записи", как имеющие размер сектора, а адресацию диска
осуществляет в терминах действительных номера дорожки и номера сектора.
Для дисковых операций чтения, записи и верификации необходима
инициализация следующих регистров:
AH Определяет тип операции: чтение, запись, верификация или
форматирование.
AL Определяет число секторов.
CH Определяет номер дорожки.
CL Определяет номер начального сектора.
DH Номер головки (стороны) : 0 или 1 для дискеты.
DL Номер дисковода: 0=A, 1=B и т.д.
ES:BX Адрес буфера ввода/вывода в области данных (за исключением
операции верификации).
ДИСКОВЫЕ ОПЕРАЦИИ В BIOS
________________________________________________________________
Для указания необходимой дисковой операции необходимо перед INT 13H
загрузить в регистр AH соответствующий код.
AH = 00: Сброс системы контролера дисковода
---------------------------------------------
Данная операция осуществляет полный сброс контролера дисковода и
требует для выполнения INT 13H загрузку в регистр AH значение шест.00.
Операция используется в случаях, когда после других дисковых операций
возвращается код серьезной ошибки.
AH = 01: Определить состояние дисковода
-----------------------------------------
Данная операция возвращает в регистре AL состояние дисковода после
последней операции ввода/вывода (см.Байт состояния в следующем разделе).
Операция требует только загрузки значения 01 в регистр AH.
AH = 02: Чтение секторов
--------------------------
Данная операция выполняет чтение в память определенного числа
секторов на одной дорожке. Число секторов обычно 1, 8 или 9. Адрес памяти
для области ввода должен быть загружен в регистр BX, причем следует
помнить, что реальный адрес зависит от содержимого регистра EX, так как в
данном случае используется регистровая пара ES:BX. В следующем примере
выполняется чтение сектора в область INSECT, которая должна быть
достаточно большой, чтобы вместить все данные:
MOV AH,02 ;Запрос на чтение
MOV AL,01 ; один сектор
LEA BX,INSERT ;Буфер ввода в ES:BX
MOV CH,05 ;Дорожка 05
MOV CL,03 ;Сектор 03
MOV DH,00 ;Сторона (головка) 00
MOV DL,01 ;Дисковод 01 (B)
INT 13H ;Вызов BIOS
Число действительно прочитанных секторов возвращается в регистре AL.
Регистры DS, BX, CX и DX сохраняют свои значения.
В большинстве случаев программа указывает только один сектор или все
сектора на дорожке. Для последовательного чтения секторов программа должна
увеличивать содержимое регистров CH и CL. Заметьте, что когда номер
сектора достигает максимального значения, его необходимо сбросить в 01, а
номер дорожки увеличить на 1 или изменить сторону 0 на 1 (для
двухсторонних дискет).
AH = 03: Запись секторов
--------------------------
Данная операция записывает данные из указанной области памяти (обычно
512 байтов или кратное 512) в один или несколько определенных секторов.
Управляющая информация загружается в регистры аналогично операции чтения
диска (код 02). Операция записи возвращает в регистре AL число секторов,
которые действительно были записаны. Регистры DX, BX, CX и DX сохраняют
свои значения.
AH = 04: Верификация сектора
------------------------------
Данная операция проверяет, может ли быть найден указанный сектор, и
выполняет своего рода контроль на четность. Операцию можно использовать
после записи (код 03) для гарантии более надежного вывода, на что
потребуется дополнительное время ввода/вывода. Значения регистров
устанавливаются аналогично операции записи (код 03), за исключением
регистровой пары ES:BX - их инициализация не требуется. Операция
возвращает в регистре AL число обработанных секторов. Регистры DX, BX, CX
и DX сохраняют свои значения.
AH = 05: Форматирование дорожек
---------------------------------
Данная операция используется для форматирования определенного числа
дорожек в соответствии с одним из четырех размеров (стандарт для системы
PC - 512). Операции чтения и записи для локализации требуемого сектора
требуют информацию о формате. Для форматирования регистровая пара ES:BX
должна содержать адрес, который указывает на группу адресных полей для
дорожки. Для каждого сектора на дорожке должен быть четырехбайтовый
элемент в виде T/H/S|B, где
T номер дорожки,
H номер головки,
S номер сектора,
B число байт на секторе, (00-128, 01-256, 02-512, 03-1024).
Например, для форматирования 03 дорожки, на стороне 00 и 512 байтов
на сектор, первый элемент должен иметь значение шест.03000102 и за ним
должны быть описаны элементы для остальных секторов на дорожке.
Техническое руководство по AT содержит ряд дополнительных операций BIOS.
БАЙТ СОСТОЯНИЯ
________________________________________________________________
Для всех рассмотренных выше операций (02, 03, 04 и 05) в случае
нормального завершения флаг CF и регистр AH содержит 0. В случае ошибки
флаг CF устанавливается в 1, а регистр AH содержит код состояния,
идентифицирующий причину ошибки. Код состояния аналогичен значению в
регистре AL после выполнения операции 01.
AH Причина
0000 0001 Ошибка команды для дискеты
0000 0010 Не найден адресный маркер на диске
0000 0011 Попытка записи на защищенный диск
0000 0100 Не найден сектор
0000 1000 Выход за границы DMA (памяти прямого доступа)
0000 1001 Попытка доступа через границу 64K
0001 0000 Чтение сбойный участок на диске
0010 0000 Ошибка контролера дисковода
0100 0000 Ошибка установки (поиска)
1000 0000 Ошибка оборудования
В случае возникновения ошибки, обычным действием является сброс диска
(AH=00) и троекратное повторение операции. Если таким образом ошибка не
устраняется, то на экран выводится соответствующее сообщение и
пользователь может сменить дискету.
ПРОГРАММА: ИСПОЛЬЗОВАНИЕ BIOS ДЛЯ ЧТЕНИЯ СЕКТОРОВ
________________________________________________________________
__________________________________________________________________________
TITLE BIOREAD (COM) Чтение дискового сектора через BIOS
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG
ORG 100H
BEGIN JMP MAIN
; ---------------------------------------------------------
RECDIN DB 512 DUP(' ') ;Область ввода
ENDCDE DB 00
CURADR DW 0304H ;Начало (дорожка/сектор)
ENDADR DW 0501H ;Конец (дорожка/сектор)
READMSG DB '*** Read error ***$'
SIDE DB 00
; ---------------------------------------------------------
MAIN PROC NEAR
MOV AX,0600H ;Функция прокрутки экрана
A20LOOP:
CALL Q10SCR ;Очистить экран
CALL Q20CURS ;Установить курсор
CALL C10ADDR ;Определить адрес на диске
MOV CX,CURADR
MOV DX,ENDADR
CMP CX,DX ;Последний сектор?
JE A90 ; да - выйти
CALL F10READ ;Получить дисковую запись
CMP ENDCDE,00 ;Ошибка чтения?
JNZ A90 ; да - выйти
CALL G10DISP ;Вывести сектор на экран
JMP A20LOOP ;Повторить
A90 RET ;Завершить программу
MAIN ENDP
; Вычислить следующий адрес на диске:
; ----------------------------------
C10ADDR PROC NEAR
MOV CX,CURADR ;Последняя дорожка/сектор
CMP CL,10 ;Последний сектор?
JNE C90 ; нет - выйти
CMP SIDE,00 ;Обойти, если сторона = 0
JE C20
INC CH ;Увеличить номер дорожки
C20:
XOR SIDE,01 ;Сменить сторону
MOV CL,01 ;Установить сектор = 1
MOV CURADR,CX
C90: RET
C10ADDR ENDP
; Чтение дискового сектора:
; ------------------------
F10READ PROC NEAR
MOV AL,01 ;Число секторов
MOV AH,02 ;Функция чтения
LEA BX,RECDIN ;Адрес буфера
MOV CX,CURADR ;Дорожка/сектор
MOV DH,SIDE ;Сторона
MOV DL,01 ;Дисковод B
INT 13H ;Выполнить ввод
CMP AH,00 ;Ошибка чтения?
JZ F90 ; нет - выйти
MOV ENDCDE,01 ; да -
CALL X10ERR ; ошибка чтения
F90:
INC CURADR ;Увеличить номер сектора
RET
F10READ ENDP
; Вывод сектора на экран:
; ----------------------
G10DISP PROC NEAR
MOV AH,40H ;Функция вывода на экран
MOV BX,01 ;Номер устройства
MOV CX,512 ;Длина
LEA DX,RECDIN
INT 21H
RET
G10DISP ENDP
; Очистка экрана:
; --------------
Q10SCR PROC NEAR
MOV AX,0600H ;Полный экран
MOV BH,1EH ;Установить цвет
MOV CX,0000 ;Функция прокрутки
MOV DX,184FH
INT 10H
RET
Q10SCR ENDP
; Установка курсора:
; -----------------
Q20CURS PROC NEAR
MOV AH,02 ;Функция установки
MOV BH,00 ; курсора
MOV DX,0000
INT 10H
RET
Q20CURS ENDP
; Вывод сообщения об ошибке на диске:
; ----------------------------------
X10ERR PROC NEAR
MOV AH,40H ;Функция вывода на экран
MOV BH,01 ;Номер устройства
MOV CX,18 ;Длина сообщения
LEA DX,READMSG
INT 21H
RET
X10ERR ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.18.1. Использование BIOS для чтения дискового файла.
Рассмотрим программу, приведенную на рис.18.1, в которой используется
команда BIOS INT 13H для чтения секторов диска. Программа базируется на
примере, приведенном на рис.16.3, со следующими изменениями:
1. Отсутствует описание FCB и подпрограмма открытия.
2. Программа расчитывает каждый дисковый адрес. После каждого
чтения происходит увеличение номера сектора. При достижении номера
сектора 10 процедура C10ADDR сбрасывает это значение в 01. Если номер
стороны = 1, программа увеличивает номер дорожки; затем меняется
номер стороны: 0 на 1 и 1 на 0.
3. Область CURADR содержит начальные значения номеров дорожки и
сектора (их программа увеличивает), а область ENDADR - конечные
значения. Один из способов улучшения программы - предоставить
пользователю возможность указать начальные и конечные номера дорожки
и сектора с помощью соответствующего запроса.
Выполните данную программу под управлением отладчика DEBUG.
Проделайте трассировку команд, которые инициализируют сегментные регистры,
и установите начальный и конечный номера секторов для файловой таблицы FAT
(расположение таблицы FAT различно в разных версиях операционной системы).
Используя команду G (до) для выполнения ввода с диска и проверки
считанного содержимого таблицы FAT и элементов оглавления.
В качестве альтернативы отладчику DEBUG можно преобразовать
ASCII-символы в области ввода в их шест. эквиваленты и выдать на экран эти
значения, как это делает отладчик DEBUG (см. программу на рис.14.5). Таким
образом можно проверить содержимое любого сектора (в том числе
"спрятанного"), а также предоставить пользователю возможность внести
изменения и записать измененный сектор на диск.
Следует помнить, что при создании файла DOS может вносить записи на
любые доступные сектора, которые не обязательно будут смежными на диске.
Следовательно, с помощью команды BIOS INT 13H нельзя выполнить
последовательное чтение файла.
ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
________________________________________________________________
- Команда BIOS INT 13H обеспечивает прямой доступ к дорожкам и
секторам диска.
- Команда BIOS INT 13H не поддерживает операции с оглавлением,
обнаружение конца файла, блокирование и деблокирование записей.
- Верификация сектора выполняет элементарную проверку записанных
данных, что приводит к увеличению времени обработки.
- Проверяйте байт состояния после каждой дисковой операции через
BIOS.
ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
________________________________________________________________
18.1. Напишите
...Поділитися у соцмережах