Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Stoneshard |#9| A Million Liches
Stoneshard |#8| Happy return
Stoneshard |#7| Oblivion
Stoneshard |#6| Rotten Willow Tavern

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Питер Нортон Весь текст 546.61 Kb

Программно-аппаратная организация компьютера IBM PC

Предыдущая страница Следующая страница
1 ... 18 19 20 21 22 23 24  25 26 27 28 29 30 31 ... 47
"тире": обычный запрос операционной системы (символ "А") в этом случае  не
используется.
     Большинство  действий  с  программой  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).  Если  будет  обнаружена  последовательность  байтов,
удовлетворяющая этим требованиям, то весьма вероятно, что найдена  область
памяти, используемая для хранения одного или двухбайтовых чисел. Эта часть
программы не может содержать команды.
     Пытаясь  осмыслить  структуру  листинга,  выдаваемого  деассемблером,
необходимо иметь в виду следующие положения. Обычные программы,  прошедшие
этап редактирования связей, будут хранить команды в одном месте, а  данные
в другом. Такой подход является элементом хорошего стиля программирования;
Предыдущая страница Следующая страница
1 ... 18 19 20 21 22 23 24  25 26 27 28 29 30 31 ... 47
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (1)

Реклама