7.3. Параметры дискеты и защита от копирования
Работа дисковода для гибких дисков частично управляется таблицей,
известной как база дисков или таблица параметров дискеты (терминология
фирмы "ИБМ" пока не устоялась)
База дисков - это таблица, состоящая из одиннадцати байт, которая
содержит ряд параметров, необходимых для работы дисководов, включая и
определенную информацию о формате дискет. В листинге 7.1 можно найти
определение этой таблицы, комментарии к которому описывают назначение
каждого байта.
Как упоминалось в главе 6, один вектор прерывания,- номер 29,
хранящийся в ячейке с адресом 120,- используется для указания
местонахождения этой таблицы. Исходная версия этой таблицы,
использовавшаяся версией ДОС 1.00, находилась в ПЗУ вместе с системой
BIOS, и поэтому ее можно видеть в листинге BIOS, приведенном в
"Техническом руководстве".
Начиная с версии ДОС 1.10 вместо этой таблицы стала использоваться
таблица, размещаемая в оперативной памяти. Такое изменение, кстати, дает
нам одно преимущество. Это позволяет экспериментировать со значениями в
таблице, не прибегая к различным ухищрениям для подмены таблицы в ПЗУ.
Любая программа может установить собственную базу диска, но вот создать ее
таким образом, чтобы эта таблица продолжала использоваться после окончания
программы, довольно сложно. Для достижения это цели необходимо
зарезервировать небольшую область памяти так, чтобы ДОС не использовала
ее. Однако, с тех пор как ДОС стала размещать таблицу базы диска в
оперативной памяти, во всех этих приемах нет необходимости.
По сравнению с версией ДОС 1.00 в версии 1.10 сделано всего два
изменения в таблице базы диска, но они позволили значительно увеличить
скорость использования дискет. Во-первых, они на 25% уменьшили время,
выделенное дисководу для перемещения головки с дорожки на дорожку. Это
время получило название "время шага" (SRT). В версии таблицы, размещаемой
в ПЗУ, которая использовалась в ДОС версии 1.00, время шага равнялось 8
миллисекундам. Новое значение, использующееся начиная с ДОС 1.10,
равняется 6 миллисекундам.
Этот параметр в таблице занимает первый полубайт. Его исходное
значение было 12 (шестнадцатиричное значение C), а новое значение 13
(шестнадцатиричное значение D). Я сначала предположил, что такое изменение
значения означает увеличение времени шага, однако Роберт Бэттен сообщил
мне, что используется инверсное значение этого параметра, так что большее
значение означает меньшее время шага. Время шага управляется приращениями
по 2 миллисекунды, так что изменение времени шага с 12 на 13 в таблице
соответствует уменьшению действительного времени с 8 до 6 миллисекунд.
Второе изменение резко увеличило скорость доступа к дискете. "Время
установления головки", то есть, пауза, необходимая для стабилизации
головок чтения/записи, была уменьшена с 25 миллисекунд до нуля.
Первоначально фирма "ИБМ" чересчур предубежденно относилась к
быстродействию дисководов, так что за счет ликвидации времени установления
удалось добиться сразу большого увеличения быстродействия. Большую часть
параметров этой таблицы изменять нельзя, однако, некоторые из них
предоставляют широкие возможности для экспериментаторов. В девятом байте
хранится значение, которое используется операцией форматирования для
инициализации секторов дискеты. Стандартное значение F6, но Вы можете его
изменить. Некоторые программы проверяют наличие кода F6, чтобы найти
неиспользовавшиеся сектора, так что это значение вряд ли разумно изменять,
если для этого нет веских оснований. Такое изменение целесообразно
применять для защиты от копирования.
Еще один интересный параметр - это байт размера сектора. Он
определяет размер сектора, который должен считываться или записываться.
Это позволяет работать с секторами, размер которых отличается от
стандартного 512-байтного формата ДОС. В других операционных системах
могут использоваться другие размеры секторов за счет изменения этого
байта. Изменение этого значения является наиболее простым способом
организации защиты записи. Для формирования сектора с размером, отличным
от 512 байт, необходимо использовать служебную процедуру форматирования,
описанную в предыдущем разделе. В процессе форматирования размер каждого
сектора определяется отдельно. Однако, чтобы в дальнейшем Ваши программы
могли читать или записывать нестандартные сектора, необходимо изменять
указатель размера сектора в таблице базы диска.
Этот параметр может принимать одно из следующих значений:
Значение Размер сектора в байтах
________ _______________________
0 128
1 256
2 512 (стандартный для ДОС)
3 1024
Листинг программы 7.1 демонстрирует (на Паскале), как осуществляется
доступ к таблице базы диска и как изменяются ее параметры. То же самое
можно сделать на БЕЙСИКе, хотя здесь требуется побайтное извлечение
адресных значений. Ниже приведена программа на БЕЙСИКе, которая находит и
распечатывает таблицу базы диска.
100 REM Программа на БЕЙСИКе для поиска и распечатки
таблицы базы диска
110 REM
120 REM Сначала необходимо установить указатель вектора
прерываний
130 REM
140 DEF SEG=0 'начало памяти
150 OFFSET1=30*4 'смещение до вектора прерывания
160 REM
170 REM Далее нужно определить смещение адреса вектора
180 REM
190 OFFSET2=PEEK(OFFSET1)+256*PEEK(OFFSET1+1)
200 REM
210 REM Теперь нужно определить сегментную часть
адреса вектора
220 REM
230 DEFSEG=PEEK(OFFSET1+2)+256*PEEK(OFFSET1+3)
240 REM
250 REM Теперь можно начинать просмотр таблицы
260 REM
270 PRINT "Ниже следуют данные таблицы базы диска в
шестнадцатиричном виде"
280 FOR I=0 TO 10
290 PRINT " ";
300 IF PEEK(OFFSET2+1)=16 THEN PRINT"0"; 'добавить
ноль для четности
310 PRINT HEX$(PEEK(OFFSET2+1));
320 NEXT I
330 PRINT:PRINT
Если Вам нужны средства для защиты от копирования, мы предоставляем
их Вам в двух формах.
Программы 7.103 и 7.104, имеющиеся на дискете, прилагаемой к этой
книге, предоставляют процедуры на ассемблере и на Паскале, которые
позволят организовать защиту записи и приспособить ее к Вашей схеме
защиты. Кроме того, в пакет входит готовая программа защиты, которую можно
вызывать как на БЕЙСИКе, так и на Паскале.
{ Листинг 7.1 -- процедуры на Паскале для доступа к }
{ параметрам "базы диска" }
{ Этот фрагмент программы демонстрирует возможность доступа }
{ к "базе диска" или таблице управления дискетами. Этот }
{ листинг разрабатывался для обеспечения наиболее легкой }
{ настройки на конкретные нужды пользователей перед его }
{ использованием. }
module Листинг 7.1;
type
disk_base_type = array [1..11] of byte;
{ Ниже кратко описаны все 11 байт таблицы : }
{ 1 : время шага; время вывода головки }
{ 2 : время ввода головки; режим ПДП }
{ 3 : время ожидания отключения двигателя }
{ 4 : длина сектора в байтах: 0=128,1=256,2=512,3=1024 }
{ 5 : конец дорожки (номер последнего сектора) }
{ 6 : длина межсекторного промежутка }
{ 7 : длина сегмента данных (когда не задана длина сектора) }
{ 8 : длина промежутка для форматирования }
{ 9 : байт заполнитель для форматирования }
{ 10: время установления головки }
{ 11: время запуска двигателя }
var
disk_base : disk_base_type;
disk_base_pointer : ads of disk_base_type; {сегментированный
адрес}
vector_pointrer : ads of adsmem; {сегментированный адрес}
procedure disk_base_access;
begin
{сначала указатель устанавливается на вектор прерывания базы}
{ диска}
vector_pointer.s := 0; {раздел сегмента 0, начало памяти}
vector_pointer.r := 30 * 4; {смещение для вектора 30}
{далее считывается вектор, чтобы установить местоположение}
{ таблицы}
disk_base_pointer := vector_pointer ^;
{указатель базы диска ("disk_base_pointer") теперь содержит }
{сегментированный адрес, на который указывал указатель }
{вектора ("vector_pointer") -- это означает, что указатель }
{базы диска теперь указывает на адрес фактического }
{местонахождения таблицы }
{Теперь будет выполняться проверка того. находится ли таблица}
{в оперативной памяти. Это можно установить попытавшись }
{изменить значение в таблице и затем проверив, изменилось ли }
{оно на самом деле. Вместо этого мы просто проверим, в каких }
{адресах памяти располагается таблица. }
if disk_base_pointer.s >= #F000 then
begin
{адрес слишком велик - таблица в ПЗУ и изменить ее не удастся}
end
else
begin
{все в порядке - таблица наверняка в ОЗУ}
end;
{Теперь скопируем таблицу в свой буфер }
disk_base := disk_base_pointer ^;
{База диска теперь содержит копию данных таблицы, на которую}
{указывал сегментированный адрес в указателе базы диска }
{Далее, изменим размер на 1024 байта и байт-заполнитель для}
{форматирования на АА. Эти изменения мы выполняем в своей }
{копии, которую затем переносим в реальную таблицу. Впрочем,}
{то же самое изменение можно было бы выполнить и }
{непосредственно в самой таблице.}
disk_base [4] := 3; {установить размер сектора 1024 }
disk_base [9] := #AA {шестнадцатиричное значение AA }
{или десятичное 170 выбрано произвольно}
disk_base_pointer ^ := disk_base; {возвратить таблицу на }
{место}
end;
end. {конец модуля listing_7_1 }
ГЛАВА 8. ВИДЕОДОСТУП, ЧАСТЬ 1 - ТЕКСТОВЫЙ РЕЖИМ
Практически любая программа, выполняемая на персональном компьютере
фирмы IBM выводит информацию на экран видеодисплея. Существует два
принципиально различных вида информации,представляемой на экране дисплея
IBM/PC: текст (т.е. литеры алфавита и другие символы) и графика. В
настоящей и в следующей главах мы рассмотрим все наиболее существенные
аспекты, связанные с доступом к содержимому экрана, рассмотрение начнем с
символьных текстов.
В отличие от остальных глав данной книги, эти главы практически не
содержат сведений, общих для всего семейства компьютеров, использующих
операционную систему MS-DOS. В то же время рассматриваемые материалы
помогут нам установить степень совместимости всего класса персональных
компьютеров с персональным компьютером IBM/PC, поскольку большинство
распространенных программ для IBM/PC зависят от специфики представления
информации на экране.
8.1. Типы экранов видеодисплеев
Существует множество различных типов видеодисплеев, подключаемых к
компьютеру IBM/PC, обладающих различными характеристиками и особенностями
программирования. Для того, чтобы разобраться в этом вопросе, мы опишем