Глава 6. Выборка из ПЗУ
Глава 6. ВЫБОРКА ИЗ ПЗУ
[ Оглавление ]
Программы, размещаемые в пассивном запоминающем
устройстве (ПЗУ ) компьютера IBM/PC, определяют эффективность
работы персонального компьютера в целом. В данной главе мы
излагаем самые общие сведения, касающиеся ПЗУ. Мы рассмотрим
назначение ПЗУ, специфику анализа и декодирования
(реконструкции) хранящейся там информации и, наконец, сравним
между собой две первые версии ПЗУ компьютера IBM/PC. Все эти
материалы являются базой для последующих пяти глав, в которых
функциональные возможности IBM/PC рассматриваются более
детально.
Здесь важно иметь в виду три аспекта. Все о чем пойдет
речь в данной главе в полной мере относится только к IBM/PC
и, вообще говоря, не распространяется на все семейство
компьютеров, работающих под управлением MS-DOS. Для остальных
компьютеров семейства PC эти сведения следует рассматривать
применительно к конкретному компьютеру (поскольку каждой
модели присущи свои особенности). Тем не менее, имеются все
основания считать, что прерывания или вызовы функции
обслуживания для большинства компьютеров совпадают. Поэтому,
несмотря на возможное изменение адресов программ
обслуживания, находящихся в ПЗУ компьютера той или иной
модели материалы настоящей и последующих пяти глав сохраняют
свою актуальность.
6.1. Организация ПЗУ и его использование
Программы, хранящиеся в ПЗУ, представляют собой
чрезвычайно важную компоненту IBM/PC, поскольку являются
основой управляющей программы, делающей ПЭВМ эффективным
инструментом обработки данных. Сам факт их размещения в ПЗУ
превращает эти программы в стабильный и надежный инструмент -
они не могут быть стерты или уничтожены. Кроме того, они
доступны для любой программы, выполняемой на IBM/PC,
независимо от специфики используемой операционной системы.
Большинство программ обслуживания, размещаемых в ПЗУ,
допускают перемещение. Эти программы написаны таким образом,
что при необходимости их можно легко переместить,
соответственно перестроив обращение к ним. Специфика
обращения к программам ПЗУ состоит в том, что их активизация
производится всегда через систему прерываний. Изменив таблицу
векторов прерываний, можно легко изменить точку входа в ту
или иную программу обслуживания. Эти вопросы уже
рассматривались нами при изучении материала главы 3.
Как уже говорилось выше, все пространство памяти ПЗУ
компьютера IBM/PC делится на три части, под которые отводятся
старшие адреса миллионного пространства памяти.
Самые старшие адреса памяти, соответствующие началу
параграфа сегмента с адресом FE20/16, и охватывающие 8Кбайт
до конца памяти отводятся под BIOS, или Базовую Систему
Ввода-Вывода.Базовая Система Ввода-Вывода (BIOS) выполняет
все операции по обслуживанию периферийных устройств IBM/PC,
таких как дисплеи или накопители на гибких магнитных дисках.
Все программы операционой системы, обеспечивающие
функционирование ПЭВМ ориентируются на использование BIOS.
Область памяти ПЗУ, содержащая BIOS, представляет особый
интерес для тех, кто хотел бы в полной мере использовать
возможности IBM/PC. В последующих пяти главах по мере
рассмотрения конкретных функций IBM/PC мы будем детально
обсуждать служебные обращения к BIOS, обеспечивающие
реализацию этих функций.
Справочное руководство по техническому обслуживанию
персонального компьютера содержит полный текст первой версии
BIOS; при этом комментарии хорошо поясняют, что делается и
как делается; вопрос, почему это делается, раскрыт слабо.
Если Вы имеете навыки интерпретации листингов на языке
ассемблера, то при изучении листинга BIOS Вы получите ответы
на любые вопросы о принципах функционирования ПЭВМ.
Вторая часть ПЗУ, соответствует параграфу с
шестнадцатеричным адресом F600 и занимает 32 Кбайт памяти.
Она содержит (хранит) программы интерпретатора языка Бэйсик.
В ПЗУ хранится ядро интерпретатора языка Бэйсик для IBM/PC.
Все кассетные версии языка Бэйсик соответствуют Бэйсик-ПЗУ;
основные функциональные возможности дисковой версии Бэйсика,
а также расширенный Бэйсик (BASICA) фактически реализованы в
ПЗУ. Практически все, что делают две указанные выше версии
Бэйсика - это расширение версии Бэйсик-ПЗУ. Соответственно,
Бэйсик-ПЗУ - это полная версия языка Бэйсик, содержащая
основные программы, требуемые для дисковых версий.
С появлением в справочном руководстве по техническому
обслуживанию текста программ BIOS не имет смысла приводить
текст программ Бэйсик-ПЗУ; однако в ряде случаев мы будем
использовать фрагменты этой программы для иллюстрации методов
исследования содержимого ПЗУ.
Сама по себе область ПЗУ, содержащая Бэйсик, не
представляет особого интереса, однако коль скоро в этой
области расположено множество полезных программ, то почему бы
ими не воспользоваться в своей собственной разработке? Поиск
и декодирование нужных фрагментов Бэйсика с последующим их
тщательным документированием представляет собой весьма
трудоемкую задачу, нами в данной работе не решаемую.
Подпрограмма или функция Бэйсика может быть
непосредственно активизирована из программы пользователя с
помощью механизма прерываний. В главе 11 эти вопросы
рассматриваются с необходимой полнотой.
Третий и последний участок ПЗУ нами здесь не
рассматривается. Фирма IBM оставляет за собой право расширять
состав программ ПЗУ; пользователи также могут встраивать в
ПЗУ свои программы, расширяя таким образом функциональные
возможности IBM/PC. Дополнительные программы можно включать в
любое место миллионного адресного пространства, однако блок,
начинающийся с шестнадчатиричного адреса параграфа F400 и
занимающий 8Кбайт, вплотную прилегающий к участку памяти,
отведенного под Бэйсик специально выделен для таких программ.
Если требуется свыше 8Кбайт памяти, то программу можно
сместить в область памяти с более низкими адресами. Именно
посредством включения в ПЗУ специализированных программ можно
превратить IBM/PC в спкциализированный компьютер. Прежде чем
приступить к более глубокому изучению BIOS мы подемонстрируем
(в двух последующих параграфах) способы исследования
содержимого ПЗУ.
6.2. Анализ содержимого ПЗУ средствами программы DEBUG
В данной главе мы рассмотрим особенности анализа
программ и данных, размещаемых в ПЗУ. Несмотря на то, что
предлагаемая методика ориентируется главным образом на
программы, расположенные в ПЗУ, она может использоваться
также и в случае программ, хранящихся на дискете. Поэтому
все, о чем пойдет здесь речь применимо как к компонентам DOS,
расположенным на дискете, так и к компонентам, входящим в
состав других программ.
Доступ к любому фрагменту ПЗУ может быть осуществлен
также средствами Бэйсика или Паскаля. Методы адресации
объектов памяти, рассмотренные в главе 3, позволяют работая
на Бэйсике или Паскале, обратиться к любой ячейке памяти.
Ниже приводится пример программы на Бэйсике, отображающий
содержимое ПЗУ.
100 REM отображение фрагмента ПЗУ в шестн. формате
110 PARAGRAPH=&HF600
120 DEF SEG=PARAGRAPH
130 PRINT
140 PRINT "Отображение содержимого параграфа",HEX$(PARAGRAPH)
150 PRINT
160 PRINT "Десятичное Шестнадцатеричное"
170 PRINT "Смещение Смещение Содержимое ПЗУ";
180 OFFSET%=0
190 FOR LINES%=1 TO 16
200 PRINT
210 PRINT OFFSET%, HEX$(OFFSET%)
Хотя приведенная программа позволяет нам судить о
содержимом ПЗУ, смысл даных остается "за кадром". Мы, таким
образом, подошли к очень важному и необходимому инструменту,
поставленному в составе DOS - программе DEBUG.
Программа DEBUG позволяет осуществлять три вида действий
вотношении содержимого ПЗУ: выборку произвольного участка
памяти и отображать ее содержимое в двух форматах:
1)шестнадцатеричный / ASCII.
2)формат не связанный с деассемблированием.
Программа DEBUG может быть также использована для
исследования программ, хранящихся на дискете. В последнем
случае, правда, представляется более эффективным использовать
программу Disklook, записанную на дискету, прилагаемую к
данной книге или программу SecMod входящую в состав программ
Norton Utility. Прежде чем двигаться дальше, поясним смысл
термина "деассемблирование".
Программы, представленные на языке машинных команд,
чрезвычайно сложны для восприятия человеком. Даже в случае
компьютеров, имеющих сравнительно простой формат машинных
команд, этот язык весьма сложен для понимания. Микропроцессор
8088 регламенитрует очень сложную структуру языка машинной
команды. Это положение справедливо в отношении большинства
микропроцессоров - их проектировщики жертвуют простотой для
достижения максимальной производительности и компактности
кода. Вследствие этого, требуется приложить значительные
усилия для просмотра и понимания листинга, представленного на
языке машинных команд в шестнадцатеричном коде.
Процесс деассемблирования, реализуемый программой DEBUG,
значительно облегчает поцедуру интерпретации машинного языка.
Деассемблирование - это процесс трансляции или преобразования
инструкций машинного языка, представленных в абсолютном
шестнадцатеричном виде в символическую нотацию языка
ассемблера. Так, например, на языке ассемблера можно записать
INC AX (увеличить содержимое регистра AX на единицу);
ассемблер переведет эту конструкцию в команду на машинном
языке с кодом 40/16. Функция деассемблера состоит в том,
чтобы привести команду машинного языка с кодом 40/16 обратно
к виду INC AX.
Шестнадцатеричный код 40 сравнительно легко может быть
преобразован и вручную, при наличии таблицы кодов команд
микропроцессора 8088. С большинством кодов остальных команд
дело обстоит не так просто, поскольку в ряде случаев смысл
команды изменяется в зависимости от значения кокнретных
битов. В случае использования команды DEBUG все запутанные
случаи декодирования преодолеваются в режимах команды
деассемблирования.
Несмотря на то, что деассемблер может выполнить
преобразование команд машинного языка к более удобным
командам языка ассемблера, целый ряд весьма существенных
компонентов программы, написанной на языке ассемблера
реконструкции не поддается. Так, очевидно, не могут быть
восстановлены весьма полезные комментарии программиста. Кроме
того, не представляется возможным восстановить оригинальные
символические имена адресов памяти.
Таким образом, вместо оригинальной авторской конструкции
типа
IMP FINISH; выполнено, перейти к завершающей процедуре
деассемблер сгенерирует строку вида
IMP OE6C
Пользователь видит перед собой команду перехода, однако
ее смысл остается для него неясным.
Деассемблер, безусловно, не в состоянии полностью
заменить программиста, особенно, в том, что касается смысла
деассемблируемой программы. Но он существенно упрощает
задачу, когда предъявляет пользователю команду, а также
помогает отличить область памяти, содержащую данные от
области памяти, содержащую команды.
Для иллюстрации особенностей исследования программ ПЗУ
возьмем программу Бэйсика и используем ее в качестве объекта
приложения программы DEBUG. Все дополнительные сведения будут
сообщены ниже, либо проясняться в ходе рассмотрения примера.
Для детального изучения программы DEBUG - следует внимательно
прочесть сответствующие разделы руководства по операционной
системе; этот материал не прост для усвоения, однако он
содержит многие важные технические детали.
Для пользователей, не работавших с программой (командой)
DEBUG, сообщим некоторые дополнительные сведения. Подобно
остальным командам, эта команда запускается путем набора на
клавиатуре ее имени. В процессе ее выполнения запосам на ввод
исполнительных операторов предшествуют лишь "тире": обычный
запрос операционной системы (символ "А") в этом случае не
используется.
Большинство действий с программой DEBUG отображаются на
экране дисплея, однако может возникнуть потребность в их
распечатке для последующей работы. Собственно программа DEBUG
не выводит результаты своей работы на принтер.
В этой связи, однако, следует напомнить, что существует
два способа получить твердую копию. Первый способ заключается
в использовании для копирования текущего кадра клавиши PrtSc
(Печатать содержимое экрана); второй - состоит в
использовании принтера для эхо-отображения путем
одновременного нажатия клавиш Ctrl и PrtSc.
Итак, мы приняли решение об исследовании участка ПЗУ,
содержащего Бэйсик; нам также известно, что адрес начала этой
программы соответствует шестнадцатеричному адресу F600. Можно
запускать программу DEBUG и приступать к непосредственной
работе с этой программой.
Предположим теперь, что адрес объекта наших поисков
(F600) нам неизвестен. В этом случае поиск может вестись в
двух направлениях. Первое - это методичное использование
операции D (означающее "дамп" или "отображение") до тех пор,
пока не появится что-нибудь интересное. Второе - более
эффективное направление - состоит в предъявлении программе
DEBUG образца объекта, который, по нашему мнению должен
находиться в памяти.
В качестве образца объекта поиска выберем сообщение об
ошибке, выдаваемое Бэйсиком: "Illegal Function call"
(Неверный вызов функции). На рис 6.1 показана процедура
запуска программы DEBUG и оператор поиска указанного выше
сообщения программы Бэйсик. Предположим, для определенности,
что в качестве начального адреса просмотра (поиска) программе
DEBUG был передан адрес параграфа F000 (лежащий немного ниже
адреса начала Бэйсика), а также размер (длина)
просматриваемого учестка (L) равный 65535 байтам (`FFFF'в
шестнадцатеричной системе счисления). Программа DEBUG
сообщает, что интересующий нас текстовой объект найден. Это
сообщение формируется в форме сегментированного адреса F000:
63F4, означающего, что относительно параграфа F000 берется
шестнадцатеричное смещение 63F4. Выполнив действия над
адресами, мы получим полный 20-байтовый адрес.
F000
+
63F4
_____________
F63F4
A > DEBUG
- S F000 : 0000 L FFFF "Illegal Function call"
F000 : 63F4
Рис. 6.1. Запуск программы DEBUG и поиск сообщения
Значение адреса искомого текстового объкта говорит о
том, что найденное сообщение расположено недалеко от
начального параграфа размещения Бэйсика F600. Если
представить 20-ти битовый адрес F63F4 в сегментированном
виде, используя в качестве базы параграф F600, то будем иметь
адрес F600:03F4. Таким образом, относительное смещение от
начала Бэйсика составляет только 3F4/16 или 1012/16 байтов.
Вводя команду D F600 : 03E0 (вывод на экран содержимого
области памяти, начиная с адреса - т.е. области памяти,
начинающейся несколько раньше найденного сообщения -
относительно базового адреса параграфа F600) можно отобразить
содержимое близлежащего пространства памяти, включающего
область найденного сообщения. На рисунке 6.2. представлен
результат выполнения этой команды. Программа DEBUG выводит на
устройство отображения - в шестнадцатеричном и символьном
(ASCII) форматах - содержимое участка памяти длиной 80 байт,
причем этот участок памяти содержит искомое сообщение. Нам
таким образом представлено искомое сообщение, а также целый
ряд других сообщений об ошибках Бэйсика, т.е. именно то, что
- как предполагалось - должно находиться где-то поблизости.
При необходимости с помощью программы DEBUG можно продолжить
отображение на экране последующих участков памяти; для этого
следует ввести команду D, не указывая адреса начала ячейки.
Рисунок 6.2. иллюстрирует ряд возможных особенностей,
которые следует иметь в виду, используя команду "D" в рамках
программы DEBUG. Одна из этих особенностей состоит в том, что
в левую часть поля вывода помещается шестнадцатеричная
информация, а в правую - информация в коде ASCII. Вторая
особенность заключается в том, что кодовая комбинация не
имеющая символьного представления в коде ASCII изображается в
правой части поля вывода с помощью точки. Отсюда, в
частности, вытекает важное следствие: для того, чтобы
использовать эхо-печать программа DEBUG контролирует
поступающие на ее вход кодовые комбинации, не имеющие
представления в коде ASCII; эти комбинации могут быть
восприняты принтером в качестве управляющего кода. Вследствие
этого, нельзя расчитывать, что правая часть поля вывода
(информация в коде ASCII) будет давать объективную картину.
Все, что может быть приведено к стандартным печатным
символам, или является печатным символом (со старшим битом в
единичном состоянии) будет отпечатано, все остальное будет
преобразовано в точки.(Здесь уместно заметить, что программа
DiskLook, входящая в состав пакета программ, записанного на
дискету, прилагаемую к настоящей книге, отображает в точности
все шестнадцатеричные коды и коды ASCII, поскольку выводит
информацию только на экран и не использует эхо-печать).
До сих пор мы рассматривали способы отображения данных,
или поиска априори известных данных, хранящихся в ПЗУ с
помощью программы DEBUG. Ниже мы будем решать существенно
более сложную задачу - задачу деассемблирования и
интерпретации программного кода на машинном языке.
6.3. Анализ содержимого ПЗУ - метод деассемблирования
Наш следующий шаг в решении задачи исследования
содержимого ПЗУ и использования программы DEBUG состоит в
знакомстве с особенностями процесса деассемблирования.
Команда "U" программы DEBUG - означает "деассемблирование" -
осущеcтвляет преобразование произвольных кодов памяти в
мнемонические коды языка ассемблера. Деассемблер реализует:
перевод абсолютных шестнадцатеричных кодов программ, в коды
команд на языке ассемблера (например: AX или DS). Деассемблер
не делает две вещи.
Первое. Деассемблер не интерпретирует смысл программы и
не обучает пользователя. Для понимания листинга, выдаваемого
деассемблером, необходимо либо знать язык ассемблера, либо
иметь желание покопаться в справочном руководстве и,
установив смысл мнемонических обозначений, постараться понять
суть дела. (Для этой цели могут быть использованы следующие
источники: "Руководство по языку ассемблера фирмы IBM",
справочники по системе команд микропроцессора 8086/8088,
такие как "Учебное пособие по микропроцессору 8086" С.Морса
или "Описание микропроцессора 8086" Ректора и Алекси).
Для понимания программы на языке ассемблера (или
программы, приведенной к языку ассемблера), знания одного
языка Ассемблер недостаточно, необходимо также иметь
некоторое представление о функциональной ориентации
программы.
Постижение пограммы представляет собой занимательное
умственое упражнение, своего рода головоломку. Со временем
эта процедура становится все проще и проще, отчасти потому,
что времени на поиск смыслового описания команды уходит все
меньше и меньше, а отчасти потому, что усваиваются приемы
программирования на ассемблере и способы достижения целей.
Далее мы остановимся на этих вопросах более подробно.
Второе, что не под силу программе деассемблера - это
установка так называемой абсолютной синхронизации. Известно,
что команды машинного языка для микропроцессора INTEL
8086/8088 имеют переменную длину - от одного до шести байтов.
После того как деассемблеру сообщена конкретная позиция
памяти он приступает к процедуре прямого декодирования, не
отличая кодов команд от данных. Достаточно ошибиться в выборе
исходной позиции памяти (например, попасть не на границу
между командами или в область данных) и результат окажется
неверным.
Если начальная точка набора команд известна, то никаких
проблем не возникает. Если какие-либо предварительные
сведения отсутствуют, то следует провести необходимое
исследование. Первое, что необходимо сделать - это выбрать
исходную точку в наборе команд и запустить операцию
деассемблирования. После этого следует предпринять попытку
интерпретировать результат работы деассемблера. Если
осмысленные программные участки отсутствуют (ниже мы приводим
некоторые соображения по их выявлению),то следует повторить
процедуру, сместив начальную точку на один, два или три байта
по отношению к предыдущей попытке. Мы таким образом пытаемся
отыскать точку синхронизации, расположенную на стыке двух
команд, после чего может быть восстановлен оригинальный набор
команд. Если очередная попытка закончилась неудачно, то
следует попробовать еще раз.
Поскольку большинство команд имеют длину один или два
байта, то точку синхронизации отыскать как правило несложно.
Кроме того, необходимо учитывать, что процессу
деассемблирования присущ элемент самосинхронизации. Даже если
в качестве начальной точки для деассемблирования выбрана
точка, расположенная внутри команды, то часто случается, что
процесс деассемблирования при обработке последуюющих команд
самопроизвольно попадает в нужную точку. После этого все идет
гладко, по крайней мере в сторону увеличения адресов. (В
обратную сторону это приходится делать вручную).
Выполняя деассемблирование программы необходимо
внимательно следить за данными (это нечто противоположное
командам), которые деассемблер превращает в причудливые
ассемблерные конструкции. Основной и наиболее быстрый способ
обнаружения данных состоит в использовании команды "D", для
представления информации в шестнадцатеричном коде и коде
ASCII. Здесь в первую очередь следует обращать внимание на
самые очевидные вещи - содержательно осмысленную
последовательность символов ASCII (фразы), такую, например,
как "неверный вызов функции". После этого можно приступать к
выявлению более тонких признаков данных.
В обычных программах (т.е. в программах, размещаемых вне
ПЗУ) наличие полей, заполненных шестнадцатеричными нулями
является признаком рабочей области данных, то есть такой
области, которая будет использоваться в ходе выполнения
программы; в процессе деассемблирования данные этой области
неактуальны. ПЗУ не может использоваться для хранения рабочих
данных, поскольку запись в эту память невозможна. Таким
образом, наличие полей, состоящих из шестнадцатеричных нулей
нетипично для ПЗУ-программ.
Признаком возможного наличия данных являются байты или
двухбайтовые слова, для которых второй или старший байт
содержит 0 или F. Дело в том, что значительное число констант
программ являются малыми числами, положительными (т.е.
начинающихся с 0), либо отрицательными (т.е. начинающихся с
F). Если будет обнаружена последовательность байтов,
удовлетворяющая этим требованиям, то весьма вероятно, что
найдена область памяти, используемая для хранения одного или
двухбайтовых чисел. Эта часть программы не может содержать
команды.
Пытаясь осмыслить структуру листинга, выдаваемого
деассемблером, необходимо иметь в виду следующие положения.
Обычные программы, прошедшие этап редактирования связей,
будут хранить команды в одном месте, а данные в другом. Такой
подход является элементом хорошего стиля программирования;
именно так работает редактор связей дисковой операционной
системы. Описанный принцип характерен для программ всех
типов, однако для программ типа EXE он справедлив в большей
степени чем для программ типа COM. С другой стороны,
ПЗУ-программы, подобные тем, которые рассматривались нами
выше, часто разрабатываются вне концепций технологии
программирования. Данные в этих программах могут следовать
вперемешку с командами.
Если предположительно обнаружен участок программы, в
котором вслед за командами следуют некоторые данные, то
существует по крайней мере один достоверный способ отличить
конец последовательности команд от расположенных вслед за
ними данными, и таким образом избежать необходимости
рассматривать недостоверный протокол деассемблирования.
Последняя команда фактического участка программы должна
представлять собой ту или иную разновидность команды перехода
или ветвления. Команды ветвления включают любые команды
переходов, кроме команд условных переходов. В качестве
общеупотребительной команды завершения программы принято
использовать команду возврата (RET) (возврат из вызванной
ранее подпрограммы).
Могут использоваться также и команды CALL (Вызов) и INT
(Прерывание); хотя их использование в качестве команды
завершения последовательности команд встречается достаточно
редко.
Существует ряд особенностей, на которые следует обращать
внимание при решении вопроса подлинности предъявленного
участка программы после его деассемблирования. В первую
очередь следует обратить внимание на используемые регистры.
Если операции реализуются на регистрах, используемых как
правило для выполнения арифметических операций (AX или AL,
AH;BX или BL, BH; CX или CL, CH; DX или DL, DH), но никакие
действия в отношении результата не предпринимаются, то это
вызывает подозрение. Здесь следует быть более внимательным.
Один из результатов выполнения арифметических операций
состоит в установке флагов - следовательно, естественно
ожидать наличие команд условных переходов по состоянию флага,
таких как JNC (команда перехода по условию отсутствия
установленных битов флага).
Рассмотрим аспект некорректности использования регистров
в реконструируемой программе. Программы не используют
регистры некоторым хаотичным образом - им присуща
определенная дисциплина. Поэтому весьма непривычно, скажем,
видеть загрузку или непосредственную ссылку на сегментные
регистры - особенно сегментный регистр программы (CS) и
сегментный регистр стека памяти (SS). Загрузка сегмента
регистра данных (DS) более вероятна, но также встречается
редко. С другой стороны, дополнительный сегментный регистр
(ES) практически постоянно используется программами, поэтому
его загрузка - дело обычное. Если загрузка регистра CS или SS
все-таки обнаружена, то это должно быть сделано в программной
секции, формирующей операционную структуру выполняемой
программы; в этом случае вероятнее всего, что в одном месте
будет произведена загрузка нескольких сегментных регистров, в
частности, CS, SS и DS.
Попытка реконструировать программу по листингу,
выданному деассемблером или даже просто попытка убедиться в
подлинности предъявленного набора команд, представляет собой
захватывающее умственное упражнение. Для этого,кстати, не
требуется специальная подготовка. Как правило, достаточно
бывает просто здравого смысла. Усвоив все наши рекомендации и
приобретя некоторые практические навыки, Вы, при
необходимости, сможете все это проделать. В следующем
параграфе мы выполним декодирование (реконструкцию) программы
Бэйсик-ПЗУ; читатель, таким образом, получит представление о
том, как это делается и убедится в том, что это не очень
сложно.
6.4. Анализ содержимого ПЗУ - реконструкция
интерпретатора
В качестве примера попробуем деассемблировать фрагмент
Бэйсик-ПЗУ. Начнем с исходного параграфа, т.е. параграфа с
адресом F600(16). На рисунке 6.3 представлен результат
деассемблирования первых 32 байтов. Шестнадцатеричные нули в
конце фрагмента программы (преобразованы деассемблером в
команды ADD (Сложить)) представляют собой данные. Они
"хорошо" иллюстрируют высказанное ранее положение о том, что
нулевые данные нетипичны для ПЗУ-программ. Команда DB
(определить байт), предшествующая полю нулей, появилась как
реакция деассемблера на кодовую комбинацию, которая не может
быть преобразована в команду ассемблера (такая ситуация,
благодаря широкому набору команд, встречается довольно
редко). Итак, являются ли все данные, которым предшествует
команда безусловного перехода собственно осмысленными
командами? Предварительный ответ на этот вопрос может быть
положительным, поскольку для завершения выполнения
подпрограммы используется команда возврата (RET). Пока все
идет хорошо.
Можно ли приписать какие-то осмысленные действия первым
пяти командам деассемблированной программы? Эти команды
выглядят несколько странно, поскольку начинаются с команды
безусловного перехода (JMP). Большинство программ, однако,
первым делом выполняют ряд действий настроечного плана,
обращаясь для этого посредством команд вызова подпрограмм или
переходов, к нужным процедурам. Таким образом, безусловный
переход в начале программы - каким бы причудливым он не
казался - не такая уж бессмыслица. Следующие четыре команды -
две пары обращения к подпрограммам с последующими командами
возврата в процедуру не особенно понятны, но, по крайней
мере, не противоречат друг другу и могут в какой-то степени
служить признаком наличия последовательности команд. Можно,
следовательно, сделать предположение о том, что мы имеем дело
с реальной последовательностью команд.
Из того, чем мы располагаем - даже при том, что на
рисунке 6.3 представлена реальная последовательность команд -
вряд ли можно извлечь какую-то пользу. Только пять команд
почти ничего не совершающих.
И все-таки есть ряд интересных моментов. Если это
действительно реальная последовательность, то нам названы три
адреса, где могут оказаться вещи более интересные. Речь идет
об адресе в команде перехода и адресах двух последующих
каманд обращения к процедуре. Следует ли нам пойти по адресу
перехода? Деассемблер дает нам этот адрес (относительно
начала нашей программы, т.е. адреса F600/16) - FE92/16.
Выполним деассемблирование небольшого участка памяти,
начинающегося с этого адреса (результат приведен на рис 6.4.)
-U F600:0000
F600:0000 E98F7E JMP 7E92
F600:0003 E8A76B CALL 6BAD
F600:0006 CB RET L
F600:0007 E80265 CALL 650C
F600:000A CB RET L
F600:000B C1 DB C1
F600:000C 0000 ADD [BX+SI],AL
F600:000E 0000 ADD [BX+SI],AL
F600:0010 0000 ADD [BX+SI],AL
F600:0012 0000 ADD [BX+SI],AL
F600:0014 0000 ADD [BX+SI],AL
F600:0016 0000 ADD [BX+SI],AL
F600:0018 0000 ADD [BX+SI],AL
F600:001A 0000 ADD [BX+SI],AL
F600:001C 0000 ADD [BX+SI],AL
F600:001E 0000 ADD [BX+SI],AL
Рис. 6.3. Деассемблирование начального участка Бэйсика
Похоже, мы попали в точку. Во-первых, перед нами
совокупность осмысленных команд, не содержащая ни
последовательностей операторов DB, ни последовательностей
операторов ADD.Во-вторых, эти команды весьма напоминают
команды настройки.Об этом говорит прежде всего команда CLI,
(CLI (Clear interrupt flag) - очистка флага прерывания).
Прерывание в микропроцессоре INTEL 8086/8088
воспринимается по завершении выполнения некоторой команды.
Немаскируемое прерывание в общем случае обслуживается
непосредственно после выполнения текущей команды. Прерывание
по вектору воспринимается только тогда, когда разряд IF (флаг
прерывания) в регистре FLAGS имеет значение, равное 1. Для
того, чтобы микропроцессор 8086 воспринял прерывание,
необходимо выполнение следующих трех условий:
1) разряд IF регистра FLAGS должен иметь значение,
равное 1 (для прерываний по вектору);
2) разряд разрешения прерываний в интерфейсе устройства
должен находиться в состоянии "Прерывание разрешено";
3) интерфейс должен зафиксировать некоторое событие,
вызывающее прерывание (например, поступление символа с
клавиатуры, готовность к выводу символа на дисплей,
завершение передачи блока данных с диска и т.п.)
(Прим.перев.)).
которая, как мы видели в главе 3 используется как средство
блокировки прерываний; таким образом вся последовательность
выполнения расположенных ниже команды прервана быть не может.
Именно такая последовательномть команд характерна для
начальных аргументов ответственных программ, поскольку
значения сегментных регистров целесообразно устанавливать
одновременно с обработкой прерываний.
Ниже производятся как раз те действия, о которых мы
говорили выше, а именно: загрузка сегментных регистров. С
помощью четырех команд MOV (команды пересылки данных)
осуществляется загрузка трех сегментных регистров из четырех:
DS, ES и SS. Загрузка этих регистров осуществляется весьма
редко, поэтому естественно это сделать один раз в начале
программы. (Сегментный регистр программы CS к этому моменту
уже загружен ( F600 : 0000, рис. 6.3.).
Вслед за группой, состоящей из четырех команд MOV,
осуществляющих загрузку сегментных регистров, следует две
команды, выполняющие одну логическую операцию. Первая команда
- это команда "исключающего ИЛИ" XOR - заносит в регистр AL
значение "нуль" (поскольку в результате применения
"исключающего ИЛИ" к эквивалентным данным образуется новая
величина), а вторая команда заносит эту величину по
конкретному адресу.
Программа не содержит никаких сведений относительно
содержательной интепретации этих операций, но это вполне
осмысленное сочетание команд, выполняющих конкретную функцию.
Если бы мы располагали более полной информацией об
особенностях работы Бэйсика, то нам, вероятно, было бы
известно, что нулевая величина, пересылаемая в память с
помощью двух двух последовательных команд представляет собой
переключатель предохраняющий защищенные программы. При
загрузке защищенных программ, написанных на языке Бэйсик,
этот переключатель устанавливается с целью предотвращения
выдачи их на печать. Это, однако, никак не следует из
представленного листинга.
Первые семь команд рассматриваемого участка программы,
таким образом, выглядят вполне осмысленно. Они реализуют
рациональные и согласованные между собой действия и
естественным образом распадаются на два класса: команды со
2-й по 5-ю реализуют одну логическую операцию, а с 6-й по 7-ю
- другую. Пред'явленные команды отвечают всем критериям
реального участка программы.
-U F600:7E92
F600:7E93 8A6000 CLI
F600:7E93 8A6000 MOV DX,0060
F600:7E96 8EDA MOV DS,DX
F600:7E98 8EC2 MOV ES,DX
F600:7E9A 8ED2 MOV SS,DX
F600:7E9C 32CO XOR AL,AL
F600:7E9E A26404 MOV [0464],AL
F600:7EA1 B591 MOV CH,91
F600:7EA3 BB0000 MOV BX,0000
F600:7EA6 BA9A06 MOV DX,069A
F600:7EA9 BBF2 MOV SI,DX
F600:7EAB 2E SEG CG
F600:7EAC AC LODSB
F600:7EAD 8807 MOV [BX],AL
F600:7EAF 43 INC BX
F600:7EBO 42 INC DX
F600:7EB1 FECD DEC CH
Рис. 6.4. Второй фрагмент реконструированного Бэйсика
Мы в какой-то мере достигли относительной цели: поиск и
выявление некоторого программного кода, а также некоторое его
осмысление. Это нам вполне удалось. Можно было бы выполнить
декодирование всего Бэйсика, либо наиболее существенных его
участков. Однако мы уже получили представление о том, как это
удается и убедились, что это вполне возможно.
6.5. Две версии BIOS'а
То, что для IBM/PC используется по крайней мере две
различные версии BIOS не является широко известным фактом. В
настоящем параграфе мы кратко рассмотрим имеющиеся между нами
различия и оценим их применительно к своим нуждам.
В состав пакета программ, записанного на дискету и
прилагаемого к настоящей книге, входят две программы
копирующие и анализирующие программы BIOS.
Именно с помощью этих программ впервые было обнаружено
наличие модифицированных версий ПЗУ компьютеров, факт,который
открыто не признавался фирмой IBM. С помощью этих программ
можно проверить свою систему и сопоставить свою версию с
другими.
Из всех программ, используемых для Вашего компьютера
IBM/PC, наиболее совершенными (не содержащими ошибок) должны
быть программы, предназначенные для размещения в ПЗУ. Если,
например, будет выявлена ошибка в какой-либо версии DOS или
VisiCalc, то ее можно устранить путем простой перезаписи
дискеты. С программами, записанными в ПЗУ, дело обстоит
гораздо сложнее. Их можно записывать только путем замены
корпусов микросхем памяти, расположенных на главной плате
компьютера IBM/PC; эта операция не может быть произведена
силами обычного пользователя. Наличие ошибок в программах ПЗУ
представляет собой серьезную проблему для фирмы IBM.
Сама мысль о том, что можно сделать что-либо стоящее,
не совершив при этом ни единой ошибки, представляется
фантастической и программы ПЗУ в этом смысле не исключение. С
момента появления компьютеров IBM/PC, фирма IBM сочла
необходимым внести ряд изменений в программы ПЗУ (речь идет о
серьезных ошибках), что обусловило появление двух версий ПЗУ.
У пользователя может возникнуть вопрос, какой версией оснащен
его компьютер и чем эта версия отличается от другой версии.
В самом конце программы BIOS фирма IBM поместила
временную отметку, так называемый маркер версии. Этот маркер
практически соответствует дате официального завершения
разработки программ ПЗУ. Для его отображения на экране можно
воспользоваться программой DEBUG. После загрузки программы
DEBUG введите команду D F000:FFF5 L 8.
На экране вашего компьютера будет отображена
последовательность символов, обозначающая маркер версии:
04/24/81. Маркер второй версии имеет вид 10/19/81. Если будет
обнаружен маркер версии, отличной от этих двух, это будет
означать, что Вы располагаете версией BIOS-ПЗУ, отличной от
указанных выше.
В приложении 6.1 приведен текст программы, проверяющей
маркер версии BIOS-ПЗУ, и, в зависимости от его значения,
выполняющей те или иные действия. Аналогичные действия на
БэйсикЕ можно представить следующим образом:
10 REM вывод на дисплей маркера версии ПЗУ
20 REM программа отображает маркер, не анализируя его
30 REM и не настраивается на версию ПЗУ
40 PRINT
50 DEF SEG=&HFFFF
60 PRINT "Маркер версии ПЗУ;
70 FOR OFFSET=5 то 12
80 PRINT CHR$(PEEK(OFFSET));
90 NEXT OFFSET
Если Ваш компьютер приобретен позже октября 1981, то это
еще не означает, что он снабжен последней версией BIOS-ПЗУ.
Проверка компьютеров, выпущенных через год после выпуска
второй версии BIOS, показывает, что новый, только что
собранный компьютер, может иметь первую версию BIOS-ПЗУ.
Вы, вероятно, помните, что ПЗУ IBM/PC содержит две
составляющие: Бэйсик-ПЗУ и BIOS-ПЗУ. Первое, что было
обнаружено с помощью разработанной автором программы,
анализа содержимого ПЗУ, это отсутствие различий между
первой и второй версиями Бэйсик-ПЗУ.
Все ошибки, обнаруженные в БейсикЕ, были устранены
только за счет дисковых версий БейсикА. Важно, чтобы
Бэйсик-ПЗУ оставался неизменным, поскольку это может
отразиться на особенностях выполнения широко распространенных
программ, написанных на БэйсикЕ, и никем не поддерживаемых.
Возможна ситуация, когда одни и те же Бейсик-программы будут
по разному работать на различных машинах только из-за
различия в версиях ПЗУ.
Придерживаясь мнения на корректировку исправления
Бэйсик-программ дискетной версии, фирма IBM обеспечила
пользователю возможность отслеживать все изменения, вносимые
в язык. Если каккая-нибуть программа написана в расчете на
оригинальный Бэйсик, то следует лишь установить дискету с
этой версией БэйсикА. Для новых версий БэйсикА программа
может имитировать модификацию содержимого ПЗУ с помощью
методики, описанной в главе 3 при осуждении прерываний.
Все изменения, внесенные в ПЗУ, касались BIOS; ниже мы
перечислим их и Вы сможете оценить степень их важности. Если
вы располагаете первой редакцией "Руководства по техническому
обслуживанию IBM/PC", то можете убедиться в том, что текст
BIOS-ПЗУ, приведенный в приложении А, соответствует первой
версии ПЗУ, о чем свидетельствует также маркер версии на
последней странице: 04/24/81. Вслед за текстом BIOS-ПЗУ
приведены некоторые замечания. Первое, третье и пятое
замечания касаются некоторых ошибок, найденных в BIOS и
исправленных во второй его версии.
Первые три изменения, внесенные в BIOS-ПЗУ, касаются
программ самотестирования, автоматически запускающихся после
включения питания на IBM/PC. Эти программы выполняют
четырнадцать различных тестовых проверок правильности работы
оборудования, прежде чем пользователь натворит "дел" на
неисправном компьютере.
Тест номер три ( входящий в состав этих программ)
осуществляет проверку правильности работы функции таймера
котроллера памяти. Два исправления из трех, внесенных в
тестовые программы, касаются этой процедуры. (Здесь
представляется уместным показать, что программы, подобные
BIOS, работающие непосредственно с аппаратурой, отличаются от
обычных программ. Корректность функционирования программ
тестирования устройств, а также программы BIOS часто зависит
оттонкостей функцмонирования контролируемых устройств.
Временные характеристики управляющих сигналов, а также их
взаимная согласованность могут оказывать решающее воздействие
на факт успешного завершения этих программ. В целом ряде
случаев отладка таких программ производится опытным путем -
одного логического анализа бывает недостаточно. Вот почему,
говоря об изменениях, внесенных в тестовые программы, я не
смог сказать ничего определенного о смысле этих изменений).
Одно из изменений, внесенных в программы тестирования,
затрагивает сразу три программы. Цель изменения: обеспечение
безусловного обновления операций таймера до момента обработки
управляющего прерывания видеомонитора. В первой версии этого
не делалось.
Не следует огорчаться, если Вам непонятно значение
введенных изменений - они практически никак не сказываются на
работоспособности правильно функционирующей системы.
Остальные изменения (описываются ниже) представляют для Вас
большой интерес.
Одно из внесенных изменений представляет интерес прежде
всего для тех, кто использует коммуникационный адаптер. На
программы ПЗУ, обслуживающие коммуникационный адаптер, среди
прочих, возлагаются также функции оповещения в случае
отсутствия на линии связи сигнала отклика. Если по истечении
определенного промежутка времени такой сигнал не появился, то
коммуникационные программы ПЗУ вырабатывают признак
"тайм-аут". /Тайм-аут - интервал времени, когда одна сторона
принимает определенные меры, если в течение заданного времени
она не получит ответа от другой стороны (Прим.перев.)/. К
сожалению, в результате обычной опечатки программы ПЗУ не
вырабатывают признак "тайм-аут". Ошибка возникла из-за
различий в представлении десятичных и шестнадцатеричных чисел
при записи шестнадцатеричного числа 80Н символ "Н" был
потерян и число воспринялось как десятичное (т.е.
шестнадцатеричное 50). В программе это число (константа)
используется для установки в единичное состояние конкретных
битов; таким образом, вместо установки в единичное состояние
одного бита-признака состояние "тайм-аут" были установлены
два других бита-признака "готовности данных" (условие
обратное "тайм-аут") и "ошибка четности" (свидетельствует о
возможной ошибке в данных).
Следствием этой ошибки является возможность неправильной
работы коммуникационной программы. Если она запрограммирована
без учета ошибки BIOS-ПЗУ, то отсутствие ответа в телефонной
линии будет восприниматься как ошибка четности данных (таким
образом нарушается объективность диагностики).
Следующая ошибка, обнаруженная во второй версии
BIOS-ПЗУ, относилась к программам управления принтером.
Проблема, как и прежде, заключалачь в тестированипи состояния
"тайм-аут". При выполнении какой-либо работы для компьютера
принтер может находиться в состоянии "устройство занято";
возможен также такой режим работы, когда принтер сигнал
ответа не вырабатывает. Управляющая программа BIOS-ПЗУ
тестирует эти режимы, ожидая некоторое время поступления
сигнала ответа. К сожалению, это время было выбрано без учета
наиболее длительной операции, выполняемой принтером -
протяжки бумаги на интервал, равный одной одной странице. В
первой редакции BIOS-ПЗУ это время было явно меньше
требуемого, поэтому в новой версии до момента появления
признака "тайм-аут" проходит вдвое большее время.
Вслед за принтером изменения затронули и программы
поддержки накопителя на магнитной ленте кассетного типа.
Здесь была изменена последовательность выполнения нескольких
команд, что привело к небольшому изменению временных
характеристик процесса считывания данных. Поскольку в составе
IBM/PC накопитель кассетного типа используется весьма редко
(т.е. последствия ошибки незначительны), то это изменение
относится к разряду несущественных.
Последнее изменение представляет интерес для тех
пользователей IBM/PC, которые используют цветной графический
адаптер. Не всем известно, что при работе с цветным
графическим адаптером в графическом режиме (в отличие от
работы в текстовом режиме) символы выводятся на экран в
режиме рисования, подобно тому как выводится изображение
любого другого объекта графической природы. (Эти вопросы
подробно рассматриваются в главе 9, посвященной отображению
графических объектов). В ПЗУ предусмотрена специальная
таблица, содержащая графические образы символов ASCII с тем,
чтобы их можно было вывести как элементы алфавита.
При работе цветного графического монитора в текстовом
режиме отображаемые символы генерируются цветным графическим
адаптером схемно; в графическом же режиме символы рисуются на
экране управляющей программой ПЗУ, использующей табличные
образы. Один из этих образов в первой версии BIOS был
закодирован с ошибкой, а именно: символ СНR$(4), обозначающий
сокровища на колодах для игральных карт, имел одну лишнюю
точку снизу. Во второй версии BIOS-ПЗУ эта ошибка устранена.
Ни одна из перечисленных выше ошибок не относится к
разряду катастрофических. Наиболее значимая из них влечет за
собой неправильное формирование признака "тайм-аут" при
работе с асинхронной линией связи , то есть ошибочное
описание ситуации, а не ошибочные действия. Редкий
пользователь IBM/PC cумеет ее распознать, даже, если знает в
чем дело.
Знать о всех изменениях имеет смысл постольку, поскольку
нельзя быть уверенныт в том, что изменения, затрагивающие
особенности работы машинных программ (даже в незначительной
степени) всегда должным образом документируются и открыто
публикуются. Здесь важен прецедент, дающий основание
беспокоиться, что более важные и существенные изменения могут
быть осуществлены без ведома пользователей.
6.6. Механизм выборки информации из ПЗУ
В данном параграфе мы обобщим все аспекты, связанные с
активизацией служебных программ BIOS-ПЗУ. Любой вид
обслуживания обеспечивается через механизм прерываний; по
причинам, котрорые мы подробно рассматривали в главе 3,
прерывания позволяют запускать (выполнять) программы, без
предварительных сведений о их местоположении( при
необходимости можно осуществлять перемещение этих программ).
Ниже приведена таблица прерываний, используемых для
активизации программ BIOS-ПЗУ, а также программ, имеющих к
ним непосредственное отношение.
____________________________________________________________
Номер Шестнадцатиричный Назначение
код
____________________________________________________________
5 5 Операция печати
содержимого экрана
16 10 Операции ввода/вы-
вода на экран дисп-
лея
17 11 Контроль оборудова-
ния; используется
для определения
подключенного обо-
оборудования
18 12 Проверка памяти;ис-
пользуется для оп-
ределения объема
памяти
19 13 Операции ввода/вы-
вода с накопителей
на дискете; различ-
ные операции с на-
копителем на диске-
те; различные опе-
рации с дискетой
20 14 Ввод/вывод для
RS-232; операции с
асинхронным комму-
никационным адапте-
ром
21 15 Ввод/вывод для на-
копителя на маг-
нитной ленте кас-
сетного типа
22 16 Ввод/вывод с кла-
виатуры
23 17 Ввод/вывод для
принтера
24 18 Загрузка кассетной
версии Бэйсика
25 19 Перегрузка системы
26 1А Функции даты и вре-
мени
____________________________________________________________
Полный список программ обслуживания значитель шире. При
необходимости каждой отдельной функции обслуживания мог бы
быть присвоен свой собственный номер прерывания или наоборот
- все функции могли бы быть обозначены одним кодом
прерывания, образуя своего рода управляющиее прерывание.
Более продуктивным, однако, представляется подход, когда
с каждым прерыванием связывают один функциональный разрез,
обеспечивая таким образом их логическую группировку. Такой
путь ведет к управляемому числу отдельных прерываний с
обоснованным разделением функций обслуживания.
Несмотря на то, что потребности в каждой функции
различны, существуют некоторые общие положения относительно
особенностей перемещения данных между точкой вызова функции и
собственно функций. Если Вы используете интерфейсные
программы, поставляемые на дискете в качестве дополнения к
данной книге, у Вас не будет возможности ознакомиться с
деталями реализации каждой функции. Знать как они работают
между тем весьма полезно.
За исключением отдельных случаев в рамках одного
прерывания реализуются несколько функций. Для передачи
номера, обозначающего субфункцию используется регистр AH. Для
передачи параметров в обоих направлениях используются
регистры, причем система стремится к их экономному
использованию. Программы обслуживания обеспечивают сохранение
всех регистров, не используемых для передачи параметров;
вызывающая программа таким образом не должна заботиться о
сохранении величин, находящихся в различных регистрах. Если
требуется выделить область памяти для данных, например, для
буфера данных считываемых с дискеты или кассеты, то для
представления сегментированных адресов используются регистры
ES и BX.
Регистры AH, AX мспользуются для передачи программам
обслуживания кода возврата или результирующего сигнала. В
некоторых случаях для индикации ошибки используется флаг
переноса CF, однако как правило флаги не используются.
Регистры общего назначения AX ... DX следует использовать
экономно по мере необходимости, придерживаясь алфавитного
порядка.
В последующих пяти главах мы детально рассмотрим все
перечисленные выше типы прерываний и особенности работы с
регистрами.
6.7. Описание специальных прерываний
Как уже упоминалось в главе 3, три строки в таблице
векторов прерываний используются не по прямому назначению для
хранения адресов программ обслуживания прерываний , а для
хранения адресов базовых таблиц системы (поскольку эти
таблицы размещаются в ПЗУ). Ниже мы поясним назначение этих
таблиц.
Первая таблица (с кодом фиктивного прерывания 29)
содержит адрес таблицы инициализации видеодисплея,
используемой для контроля управляющих кодов для экранов
дисплеев. Таблица размещается в ПЗУ по адресу F000: F0A4 и
включает три подтаблицы с видеопараметрами. Каждая подтаблица
имеет четыре строки по одной строке на каждый из четырех
режимов отображения: монохромный, 40-столбцовый цветной,
текстовой, 80-столбцовый цветной, текстовой и оба графических
режима. Одна из подтаблиц фиксирует размер в байтах буфера
дисплея, соответствующего текущему режиму. (Подробно эти
вопросы рассматриваются в главе 8 и 9).
Еще одна подтаблица фиксирует ширину граф, учитываемую
при автоматическом переходе от одной строки в другую.
Практическая польза от модификации этой таблицы близка к
нулю, поэтому в дальнейшем она рассматривается не будет.
Адрес второй таблицы (соответствует прерыванию 30)
указывает на таблицу параметров дискет. Эта таблица содержит
данные, предназначенные для контроля временных параметров
различных операций, выполняемых с дискетой. Таблица
расположена в ПЗУ по аресу F000 : EFC7. Сразу же после
выпуска компьютера IBM/PC стало ясно, что некоторые временные
характеристики, внесенные в эту таблицу весьма приблизительны
и являются причиной слишком медленной работы дискового
накопителя. Среди многочисленных изменений, внесенных в DOS
версии 1.10 были данные, снижающие время обращения к
дисковому накопителю. Здесь использовался классический метод
- в процессе самонастройки дисковая операционная система
создавала новую версию таблицы в обычной памяти и заменяла ее
адрес в векторе,инициализируцемой по прерыванию 30. Поскольку
при выполнении любой операции с диском производится обращение
к этой таблице, то после замены адреса вектора, активной
становилась новая таблица. В главе 7 (посвященной описанию
дискового накопителя) мы рассмотрим детали, связанные с этой
таблицей и укажем внесенные изменения.
Адрес третьей таблицы, получаемой по фиктивному
прерыванию 31, указывает на область генератора графических
символов, используемых при формировании на дисплее символов
CH$(128), ..., CHR$(255) в любом из двух графических
режимов. Стандартной таблицы этого типа попросту не
существует. Если две предыдущие таблицы всегда находятся в
ПЗУ, то данная таблица в ПЗУ отсутствует. А коль скоро это
так, то вектор прерывания будет содержать нулевое значение
(является признаком отсутствия таблицы) до тех пор, пока
программа не построит такую таблицу и не занесет
соответствующий адрес в вектор прерывания. При изучении
графического режима работы (глава 9) мы увидим, что
существует много интересных вещей, связанных с таблицей
генерации символов.
Все эти общие положения, касающиеся ПЗУ, образуют ту
основу, опираясь на которую мы перейдем к рассмотрению
широких возможностей отдельных узлов IBM/PC. Этому посвящены
пять следующих глав. Начнем с дисковых накопителей,
рассматривая их до того как программа построит таблицу и
поместит адрес этой таблицы в соответствующий вектор
прерываний.
Приложение 6.1. Текст программы проверки метки
версии ПЗУ (Паскаль).
module Listing_6_1;
type
string8 = string(8);
bios_ptr_type = ads of string8;
var
bios_date : bios_ptr_type;
procedure check_rom_bios_date;
begin
bios_date.s :=#F000;
bios_date.r :=#FFF5;
if bios_date^='04/24/81' then
begin
end
else
begin
end;
end;
end.
[ Оглавление ]