Страница 14 из 41
5.2.7 Чтение/изменение метки тома. Метка тома для дискеты - это элемент каталога, имеющий спе- циальный атрибут. Метка занимает первые 11 байтов элемента, отно- сящиеся к имени и расширению файла. Байт атрибутов по смещению 11 содержит значение 8 (бит 3 = 1). Поля времени и даты заполняются обычным образом. Одним из свойств этого атрибута является то, что данный элемент не выводится по команде DIR. Метка может занимать любую позицию в каталоге. Она ищется перебором всех байтов атрибутов, пока не будет найдено значение 8. Чтобы стереть метку надо просто поместить E5 в первый байт соответствующего элемента - сам байт атрибутов можно не менять. Чтобы изменить метку надо записать новые 11 символов (остаток надо заполнить пробелами). Чтобы присвоить метку тома диску, который не имел ее, надо найти пустое место в каталоге и записать туда метку и соответствующий атрибут, ничего больше не требуется.
Высокий уровень. Обсуждение в [5.4.2] объясняет как читать и писать абсолютные сектора в Бейсике. Для стандартной двухсторонней дискеты надо использовать номер стороны 0, номер дорожки 0, номер сектора - 6 и число секторов для чтения/записи - 7. После того, как данные записаны в отведенный буфер, примеры, приведенные здесь могут быть использованы для изменения или добавления метки тома. Затем сектора должны быть перезаписаны на диск. Будьте внимательны: ошибка может привести к потере всей информации на диске. Данный пример ищет метку тома и изменяет ее:
100 'сектора загружены, начиная скажем с &H1000 110 DEF SEG = &H1000 120 DIRPTR = 11 'указатель на байт атрибутов 130 FOR N = 1 TO 112 'проверяем все элементы каталога 140 IF PEEK(DIRPTR) = 8 THEN 180 'уход если метка тома 150 DIRPTR = DIRPTR + 32 'указываем на след. элемент 160 NEXT 'проверяем его атрибут 170 PRINT "No volume label found": END 'метки нет 180 INPUT "Enter new volume label", V$ 'запрос метки 190 IF LEN(V$) > 11 THEN BEEP: PRINT "11 chars only": GOTO 180 200 V$ = V$ + STRING$(11-LEN(V$),32) 'дополняем пробелами 210 DIRPTR = DIRPTR - 11 'возвращаемся на начало элемента 220 FOR N = 1 TO LEN(V$) 'помещаем все символы метки 230 POKE N,MID$(V$,N,1) 'в память 240 NEXT ' 250 'теперь осталось перезаписать сектора на диск
Низкий уровень. В нижеприведенном примере предполагается, что Вы создали буфер данных размером 3584 байт, для хранения всех семи секторов ката- лога дискеты емкостью 360K. Буфер называется DIR_AREA. В первом примере метка тома ищется и выводится, или, если она не найдена, то выводится сообщение об ее отсутствии. Для удобства область буфера для секторов отводится в сегменте данных; лучше отвести память для задачи, а затем освободить ее [1.3.1].
;---в сегменте данных VOL_STRING DB 'The volume label is $' NO_LABEL DB 'There is no volume label $' DIR_AREA DB 3584 DUP(?)
;---читаем 7 секторов каталога MOV AX,SEG DIR_AREA ;сегмент буфера MOV ES,AX ; MOV BX,OFFSET DIR_AREA ;смещение буфера MOV DL,0 ;номер накопителя MOV DH,0 ;номер головки MOV CH,0 ;номер дорожки MOV CL,6 ;стартовый сектор
MOV AL,7 ;число секторов каталога MOV AH,2 ;номер функции чтения INT 13H ;читаем каталог в память ;---ищем метку тома, сравнивая байт атрибутов с 8 MOV CX,112 ;число элементов ADD BX,11 ;смещение для атрибутов TRY_AGAIN: MOV AL,[BX] ;берем 1-й элемент CMP AL,8 ;это метка тома? JE GOT_IT ;если да, то уход ADD BX,32 ;иначе на след. элемент LOOP TRY_AGAIN ; ;---выводим сообщение об отсутствии метки тома MOV AH,9 ;функция вывода строки LEA DX,NO_LABEL ;указываем на строку INT 21H ;выводим ее JMP SHORT CONTINUE ;на конец ;---выводим строку, дающую метку тома GOT_IT: MOV AH,9 ;функция вывода строки LEA DX,VOL_STRING ;указываем на строку INT 21H ;выводим ее SUB BX,11 ;указатель на метку MOV CX,11 ;пишем 11 символов MOV AH,2 ;функция вывода символов NEXT_CHAR: MOV DL,[BX] ;символ в DL INT 21H ;выводим символ INC BX ;переходим к следующему LOOP NEXT_CHAR ; CONTINUE:
Чтобы стереть метку поместите следующий код в GOT_IT:
GOT_IT: MOV AL,0E5H ;код отметки пустого элемента SUB BX,11 ;указатель на начало элемента MOV [BX],AL ;меняем первый байт
Чтобы изменить метку тома, надо вместо этого использовать в GOT_IT следующий код. Предполагается, что Вы подготовили где-то 11-байтную строку NEW_LABEL.
GOT_IT: LEA SI,NEW_LABEL ;SI должен указывать на строку SUB BX,11 ;BX указывает на начало метки MOV DI,BX ;помещаем указатель в DI MOV CX,11 ;пересылка 11 символов REP MOVSB ;пересылаем строку
Чтобы создать метку можно использовать тот же самый код, но надо также установить байт атрибутов равный 8 (Вы можете просто добавить ASCII 8 к строке, содержащей новую метку, так как байт атрибутов непосредственно следует за самой меткой). И, наконец, во всех случаях изменения каталога, необходимо записать каталог обратно на диск. Ошибки при этом непростительны.
;---запись измененных секторов назад на диск MOV AX,SEG DIR_AREA ;регистры как и при чтении MOV ES,AX ; MOV BX,OFFSET DIR_AREA ; MOV DL,0 ; MOV DH,0 ; MOV CH,0 ; MOV CL,6 ; MOV AL,7 ; MOV AH,3 ;номер функции записи секторов INT 13H ;
|