Страница 31 из 41
5.4.2 Чтение/запись определенных секторов. Чтение или запись определенных секторов диска в основном ис- пользуется при доступе к каталогам диска или его таблице размеще- ния файлов, сектора для которых всегда расположены в одном и том же месте. В то время как чтение секторов достаточно безобидно, запись абсолютного сектора требует чтобы код был тщательно прове- рен перед первым использованием. Ошибка может сделать каталог или таблицу размещения файлов нечитаемыми, что эквивалентно разруше- нию всех данных на диске. Как DOS так и BIOS предоставляют функции для чтения и записи определенных секторов. Однако они указывают сектора по-разному. Для IBM PC, XT и PCjr процедура BIOS требует информации о номере стороны (0 или 1), номере дорожки (0-39) и номере сектора (1-8). Из-за ограничения максимального номера сектора равного 8 этот метод практически бесполезен для этих машин. Однако для AT номер сектора может меняться до 8, 9 или 15, а число дорожек может меняться до 39 или 79. Функции DOS указывают сектор одним номе- ром, который называется логическим номером сектора. Начиная с наружного обода диска, секторам присваиваются последовательно возрастающие номера. Этот метод может быть использован для дисков произвольного размера и типа. Отсчет логисеких секторов начинается со стороны 0 дорожки 0 сектора 1 и продолжается на стороне 1 с дорожки 0, после чего переходит на сторону 0 дорожку 1 и т.д. (На больших фиксированных дисках сначала проходится весь внешний цилиндр.) В зависимости от того как был форматирован диск, при переходе на следующую дорожку логический номер сектора увеличивается на определенную величину. Для дискет емкостью 360K каждая дорожка (с учетом обеих сторон) добавляет к логическому номеру 18. Однако вычисления немного усложняются тем, что отсчет начинается с нуля. Таким образом первый сектор на дорожке 3 стороны 2 должен иметь номер равный 3*18 для дорожек 0-2 плюс 9 для стороны 0 дорожки 3 плюс единица, указывающая на первый сектор дорожки 3 стороны 1. Эта сумма равна 64. Логический номер сектора на 1 меньше этого числа. На рис. 5-4 сравнивается методы указания сектора DOS и BIOS.
Высокий уровень. Бейсик не предоставляет прямого доступа к секторам диска. Надо использовать следующую процедуру на машинном языке. В приложении Г объясняется логика взаимодействия с этой процедурой. В примере читается 9 секторов дорожки 3 стороны 1 дискеты емкостью 360K. Сама процедура размещается в памяти, начиная с адреса сегмента &H1000, а содержимое секторов размещается, начиная с сегментного адреса &H2000 (напоминаем, что абсолютный адрес равен сегментному адресу, умноженному на 16). Для того чтобы записать на диск со- держимое этого буфера надо изменить в данных программы седьмой байт с конца &H25 на &H26. Все остальное остается неизменным.
100 DEFINT A-Z 'все переменные будут целыми 110 DATA &H55, &H8B, &HEC, &H1E, &H8B, &H76, &H0C, &H8B 120 DATA &H04, &H8B, &H76, &H0A, &H8B, &H14, &H8B, &H76
130 DATA &H08, &H8B, &H0C, &H8B, &H76, &H06, &H8A, &H1C 140 DATA &H8E, &HD8, &H8B, &HC3, &H8B, &H00, &H00, &HCD 150 DATA &H25, &H59, &H1F, &H5D, &HCA, &H08, &H00
160 DEF SEG = &H1000 'помещаем процедуру по адресу &H10000 170 FOR N = 0 TO 38 'для каждого байта процедуры 180 READ Q: POKE N,Q 'читаем байт и помещаем его в память 190 NEXT 'следующий байт 200 READSECTOR = 0 'выполняем код, начиная с первого байта 210 BUFFER = &H2000 'буфер для данных имеет адрес &H20000 220 LOGICALNUMBER = 62 'логический номер сектора равен 62 230 NSECTORS = 9 'число считываемых секторов 240 DRIVE = 0 'номер накопителя (0 = A) 250 CALL READSECTOR (BUFFER, LOGICALSECTORS, NSECTORS, DRIVE) 260 'теперь сектора в памяти, начиная с адреса 2000:0000
Средний уровень. BIOS использует функцию 2 прерывания 13H для чтения секторов и функцию 3 прерывания 13H для записи секторов. В обоих случаях DL должен содержать номер накопителя от 0 до 3, где 0 = A, 1 = B и т.д., DH - номер головки (стороны), 0-1. CH должен содержать номер дорожки от 0 до 39, а CL - номер сектора от 0 до 8. AL содержит число секторов, которое необходимо считать. Допускается сразу читать не более восьми секторов, что более чем достаточно для большинства целей. ES:BX должны указывать на начало буфера в памяти, куда будут помещаться данные или откуда они будут брать- ся. При возврате AL будет содержать число прочитанных или запи- санных секторов. Если операция успешна, то флаг переноса будет равен нулю. Если он равен 1, то AH будет содержать байт статуса дисковой операции, описанный в [5.4.8].
;---в сегменте данных BUFFER DB 4000 DUP(?) ;создаем буфер
;---читаем сектора MOV AX,SEG BUFFER ;ES:BX должны указывать на буфер MOV ES,AX ; MOV BX,OFFSET BUFFER ; MOV DL,0 ;номер накопителя MOV DH,0 ;номер головки MOV CH,0 ;номер дорожки MOV CL,1 ;номер сектора MOV AL,1 ;число секторов для чтения MOV AH,2 ;номер функции чтения INT 13H ;
Прерывания DOS 25H и 26H читают и записывают абсолютные секто- ра диска, соответственно. Надо поместить логический номер старто- вого сектора в DX, а DS:BX должны указывать на буфер. CX содержит число секторов для чтения или записи, а AL - номер накопителя, где 0 = A, 1 = B и т.д. Процедуры портят все регистры, кроме
сегментных. При возврате регистр флагов остается на стеке, остав- ляя стек невыровненным. Не забудьте вытолкнуть это значение со стека сразу после возврата (в примере это значение выталкивается в CX).
;---в сегменте данных BUFFER DB DUP 5000(?) ;создаем буфер
;---читаем сектора PUSH DS ;сохраняем регистры MOV AX,SEG BUFFER ;DS:BX должны указывать на буфер MOV DS,AX ; MOV BX,OFFSET BUFFER ; MOV DX,63 ;логический номер сектора MOV CX,9 ;читаем всю дорожку MOV AL,0 ;накопитель A INT 25H ;функция чтения секторов POP CX ;выталкиваем со стека флаги POP DS ;восстанавливаем регистры JNC NO_ERROR ;если нет ошибки, то на продолжение CMP AH,3 ;проверка возможных ошибок . . NO_ERROR: ;продолжение программы
Если при возврате флаг переноса равен 1, то произошла ошибка и в этом случае AH и AL содержат два отдельных байта статуса ошиб- ки. Если AH = 4, то указанный сектор не найден, а если AH = 2, то диск неверно отформатирован. Если AH = 3, то была попытка записи на дискету, защищенную от записи. Все остальные значения AH гово- рят об аппаратной ошибке.
Низкий уровень. Дисковые операции на низком уровне требуют прямого программи- рования микросхем контроллера НГМД и прямого доступа к памяти. Поскольку эти операции взаимосвязаны, то они рассматриваются вместе в разделе [5.4.1].
|