Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Dos7book

.pdf
Скачиваний:
75
Добавлен:
09.02.2015
Размер:
5.1 Mб
Скачать

Глава 6: Избранные программы для MS-DOS7

6.05DEBUG.EXE – отладчик и мини-ассемблер

Отладчик DEBUG.EXE - это специализированный командный интерпретатор, написанный Тимом Паттерсоном (Tim Patterson) как инструмент для создания той операционной системы, которая позже была куплена фирмой Microsoft и стала называться первой версией MS-DOS. Отладчик DEBUG.EXE помогает искать и исправлять ошибки как в настройке компьютера, так и в кодах программ. Возможности отладчика DEBUG.EXE не ограничены его встроенными командами,

потому что эти команды позволяют ассемблировать и исполнить любой машинный код. Конечно, по части написания сложных программ отладчик - не конкурент языкам высокого уровня. Однако обстоятельства диктуют другие критерии, когда способности известных компиляторов оказываются недостаточны, когда нужно что-либо выяснять или проверять. Если Вы делаете это в реальном режиме с помощью отладчика DEBUG.EXE, то все AT-совместимые компьютеры покорно предоставят себя в Ваше распоряжение. Вы получите прямой доступ к дискам, к портам, к памяти, к данным и к исполняемому коду в файлах.

При вызове отладчика DEBUG.EXE из командной строки после его имени может быть указано имя файла, который сразу будет загружен в память и подготовлен к отлаживанию, например:

DEBUG.EXE Trial.com /B /S

здесь:

Trial.com – пример имени файла, подлежащего отлаживанию. Указанные после имени параметры ( /B /S ) – это параметры не отладчика, а файла Trial.com. Они будут записаны в PSP файла Trial.com так же, как это делает командный интерпретатор COMMAND.COM, когда подготавливает файл к исполнению. Размещение

загружаемого файла в памяти зависит от его суффикса (подробнее - в разделе 6.05-10).

Если подлежащий исполнению файл в командной строке не указан, то он может быть задан и загружен позднее встроенными командами отладчика "N" и "L" (6.05-10, 6.05-12). Отложенная загрузка командами отладчика дает возможность размещать загружаемый код начиная с произвольного стартового адреса, что важно, в частности, при отлаживании драйверов (подробнее - в разделе 6.05-18).

Как и командный интерпретатор COMMAND.COM, отладчик DEBUG.EXE

принимает команды из командной строки и активизирует клавиши редактирования командных строк (1.05). Если в строке вызова указано перенаправление ввода (2.04-02), то вместо команд с клавиатуры DEBUG.EXE будет принимать перенаправляемые команды. Это свойство позволяет записывать

последовательности команд в текстовые командные файлы и затем посылать их отладчику для автоматического исполнения:

– 171 –

Глава 6: Избранные программы для MS-DOS7

Debug.exe < Cmnd_txt.scr

Все спецификации загружаемых и ассемблируемых кодов могут быть включены в такие командные файлы (примеры в разделах 9.02, 9.06, 9.08 и 9.10).

Примечание 1: когда исполняющая программа принимает команды из файла посредством перенаправления, она теряет контакт с клавиатурой через канал STDIN, и тогда ввести данные с клавиатуры посредством прерываний INT 21\AH=01h,06h,07h,08h,0Ah (8.02-02, 8.02-04, 8.02-06) невозможно. По той же причине исполняющая программа "зависает", если в последних строках командного файла

не приняты меры для восстановления взаимодействия с клавиатурой через канал STDIN. В простейшем случае эту роль играет команда завершения сеанса ("Q"). Другой способ

восстановления взаимодействия с клавиатурой без завершения сеанса показан в разделе 9.07-02.

Примечание 2: Пауль Войта (Paul Vojta) разрабатывает усовершенствованный вариант отладчика DEBUG.EXE, который отличается от описываемого здесь отладчика фирмы Microsoft тем, что способен "понимать" команды более современных процессоров. Сейчас, в 2008 году, на сайте http://www.japheth.de/dwnload4.html свободно выложен файл архива Debug113.zip, содержащий версию 1.13 отладчика Пауля Войта. Если специально не оговорено иное, то материал раздела 6.05 в равной мере относится к этому отладчику.

6.05-01 Отладчик DEBUG.EXE: команды и адреса

Когда отладчик DEBUG.EXE запущен, он представляет приглашение командной строки в виде знака дефис ( – ). Это означает, что он готов принять к исполнению команду от пользователя.

Команды отладчика DEBUG.EXE имеют однобуквенные или двухбуквенные имена, за которыми могут следовать параметры, отделенные друг от друга запятыми или пробелами. Разделительные знаки можно не указывать, если их отсутствие в конкретной позиции не вызывает неопределенности. DEBUG.EXE воспринимает все цифры в командах как шестнадцатеричные, а строчные и заглавные буквы как эквивалентные; исключением является только сопоставление данных при поиске командой SEARCH (6.05-16).

Первый параметр после имени команды обычно представляет адрес стартовой точки в памяти. Он может быть задан в полной форме как сегментный адрес и смещение (например, 1FA5:0100), или через ссылку на сегментный регистр

– 172 –

Глава 6: Избранные программы для MS-DOS7

(например, CS:0100), или в краткой форме как только смещение (например, 0100). В последнем случае сегментный адрес будет взят по умолчанию: из регистра

CS (Code Segment = кодовый сегмент) – для команд A (Assemble = собрать), G (Go =

исполнить), L (Load = загрузить), P (Proceed = продолжить), T (Trace = отследить), U (Unassemble = разобрать) и W (Write = записать), а для всех других команд из регистра DS (Data Segment = сегмент данных). В спецификации смещения допускается не указывать начальные нули: например, смещение 100 всегда будет интерпретироваться как 0100h.

Начальные установки всех сегментных регистров одинаковые и определяются тем сегментом, который выделила DOS по запросу отладчика DEBUG.EXE для отлаживаемой программы. Начальная установка смещения по умолчанию принимается 0100h (т.е. в десятичной форме 256), она записывается в регистр IP (Instruction Pointer = указатель команд) и выражает смещение первого байта

исполняемого кода отлаживаемой программы относительно начала выделенного ей сегмента. Резервируемый таким образом 256-байтный участок адресного пространства известен как PSP (Program Segment Prefix = префикс сегмента программы, показанный в приложении A.07-1).

Когда действие команды отладчика DEBUG.EXE должно быть направлено на группу байт, эта группа задается своим начальным адресом в любой форме и еще вторым параметром либо длиной, либо смещением конца группы. Параметр, задающий длину, должен начинаться с буквы "L" – например, параметр L20 определяет группу длиной в 20h байт. Сумма начального адреса и длины не должна превосходить FFFFh. Если шестнадцатеричное число в позиции второго параметра спецификации группы байт не начинается с буквы "L", то оно интерпретируется как смещение конца группы, причем указывать сегментный адрес перед этим смещением нельзя. Разумеется, смещение для конца группы должно быть больше, чем смещение для ее первого байта в составе начального адреса.

Закончив набор командной строки, пользователь посылает ее на исполнение нажатием клавиши ENTER (на некоторых клавиатурах она обозначена как CR ).

Наиболее простые команды отладчика DEBUG.EXE представлены всего лишь одним знаком и не нуждаются ни в параметрах, ни в особых комментариях:

Q – ("Quit") – закончить сеанс работы с отладчиком DEBUG.EXE

?показать краткий список команд отладчика DEBUG.EXE.

Показываемый отладчиком список команд, однако, слишком краток, чтобы служить руководством к действию. Необходимые пояснения по пользованию всеми другими командами приведены в следующих статьях раздела 6.05.

Примечание 1: если Вы ошиблись при наборе команды, отладчик DEBUG.EXE выводит в следующей строке сообщение "Error" (= ошибка) и указатель в виде стрелочки вверх ^ (caret), показывающий на то

– 173 –

Глава 6: Избранные программы для MS-DOS7

место в предыдущей строке, которое он не способен "понять". Наиболее вероятно ошибка находится именно в этом месте, но тем не менее нередко ошибка находится раньше, в предшествующей части строки.

Примечание 2: абсолютный адрес в памяти рассчитывается как сумма смещения с сегментным адресом, умноженным на 16. Если сегментный адрес, например, 1FA5h, а смещение 0100h, то абсолютный адрес будет

(1FA5h x 10h) + 0100h = 1FB50h.

6.05-02 Отладчик DEBUG.EXE: команда "Assemble"

Команда "Assemble" (= собирать) – переключает отладчик DEBUG.EXE в режим преобразования ассемблерных инструкций в машинный код. Этот код не исполняется сразу, а записывается в память, образуя последовательность машинных команд, которая после выхода из режима ассемблирования может быть исполнена или сохранена в файле. В командной строке отладчика вызов команды

"Assemble" задается буквой "A":

A 0100

После имени команды "A" указан начальный адрес для размещения получаемого машинного кода. Здесь адрес представлен только смещением, но допустимы все формы адреса, перечисленные в разделе 6.05-01. Если сегмент в адресе не указан, то по умолчанию он будет взят из регистра CS:. Можно вообще адрес не указывать, тогда он будет взят из регистров CS:IP.

После получения команды "A" отладчик DEBUG.EXE показывает полный стартовый адрес, выделенный для размещения машинного кода команды, и мигающим курсором предлагает ввести ассемблерную команду, которую предстоит перевести в машинный код. В режиме ассемблирования отладчик DEBUG.EXE не принимает команды, описываемые в разделе 6.05, а принимает только те инструкции и ассемблерные команды, которые детально описаны в главе 7.

Окончание набора каждой ассемблерной команды пользователь подтверждает нажатием клавиши "ENTER". Отладчик DEBUG.EXE сразу переводит команду в машинный код, записывает его в память и показывает следующий полный адрес с приглашением ввести следующую ассемблерную команду.

Чтобы выйти из режима ассемблирования нужно, не вводя очередной ассемблерной команды, просто нажать клавишу "ENTER" при пустой командной строке. Тогда отладчик выйдет в интерактивный режим, выведет на экран свое приглашение в виде знака дефис и снова будет готов принимать команды, описываемые в разделе 6.05. Когда отладчик DEBUG.EXE получает команды из

– 174 –

Глава 6: Избранные программы для MS-DOS7

файла через перенаправление, для выхода из режима ассемблирования нужно оставить в командном файле пустую строку (7.01-04).

6.05-03 Отладчик DEBUG.EXE: команда "Compare"

Команда "Compare" (= сравнить) показывает несовпадающие байты в двух группах последовательно расположенных ячеек памяти. Одинаковые байты при этом пропускаются. В командной строке отладчика вызов команды "Compare" задается буквой "C":

C 113 L8 153

В приведенном примере первый и третий параметры после буквы "C" – это начальные адреса сопоставляемых последовательностей, в данном случае представленные смещениями 0113h и 0153h. Однако допустимы все формы адресов, перечисленные в разделе 6.05-01. Если сегмент в адресе не указан, то по умолчанию он будет взят из регистра DS:. Второй параметр задает либо смещение конечного байта первой группы (если числу не предшествует буква "L"), либо длину интервала сопоставления; в данном случае заявлена длина 8h байт. Все три параметра в этой команде обязательные.

6.05-04 Отладчик DEBUG.EXE: команда "Dump"

Команда "Dump" (= вывалить) показывает в шестнадцатеричной байтовой форме состояние ячеек памяти, и одновременно в правой части экрана показывает содержание, записанное в те же ячейки памяти, знаками кода ASCII.

В командной строке отладчика DEBUG.EXE вызов команды "Dump" задается буквой "D":

D 19A9:02E0 L10

Здесь сразу после имени команды указан пример полного адреса начальной ячейки той группы ячеек памяти, которые надлежит показать. Адрес можно указывать в любой допустимой форме (6.05-01). Если сегмент в адресе не указан, то по умолчанию он будет взят из регистра DS:. Второй параметр задает либо смещение конечной ячейки той же группы (если ему не предшествует буква "L"), либо длину показываемой группы ячеек. В данном случае задана длина 10h (= 16) байт. Если второй параметр в команде "Dump" не задавать, то по умолчанию будет принята длина L80, то есть 128 байт. Если не задавать и адрес тоже, то будут показаны 80h байт, начиная с текущего смещения относительно сегментного регистра DS:. При каждом исполнении команды "Dump" значение текущего смещения увеличивается на длину показанной группы ячеек, так что при каждом

– 175 –

Глава 6: Избранные программы для MS-DOS7

следующем исполнении без указания начального адреса выводится на экран не та же, а следующая группа ячеек памяти.

Примеры пользования командой "Dump" показаны на рис. 8 – 12 (в главе "A").

6.05-05 Отладчик DEBUG.EXE: команда "Enter"

Команда "Enter" (= ввести) записывает новые данные в ячейки памяти начиная с указанного адреса. В командной строке отладчика DEBUG.EXE вызов команды "Enter" задается буквой "E":

E 0211

Здесь после имени команды указан пример адреса той ячейки памяти, начиная с которой следует записывать вводимые данные. Адрес может быть указан в любой допустимой форме (6.05-01), но он должен быть указан обязательно. Если сегмент в адресе не указан, то по умолчанию он будет взят из регистра DS:. Исполняя такую команду, отладчик DEBUG.EXE покажет полный адрес запрошенной ячейки памяти, содержащийся там байт данных и финальную точку. Эту точку надо понимать как приглашение ввести байт данных, который должен заместить прежнее содержимое этой ячейки. При вводе с клавиатуры в ответ на приглашение команды "Enter" данные в знаках кода ASCII не принимаются, их следует вводить в

байтовой форме, по две шестнадцатеричных цифры на байт. По нажатию клавиши "Пробел" ("Spacebar") новый байт, если он введен, будет записан в ячейку, а если строка ввода оставлена пустой, то прежнее содержимое ячейки памяти сохранится. В любом случае потом выводится байт из следующей ячейки, и Вам точно так же предлагается его заменить. Если вместо клавиши "Пробел" нажать клавишу "–" (минус или дефис), то Вы получите возможность вернуться к изменению содержимого предыдущей ячейки. Чтобы закончить процесс ввода данных, достаточно нажать клавишу ENTER.

Команда "Enter" исполняется иначе, без обращения к вводу с клавиатуры, если

после адреса запрашиваемой ячейки в той же командной строке указаны подлежащие вводу данные, например:

E 03E0 'Data error' 0D 0A

Вводимые данные в командной строке могут быть представлены либо побайтно, по две шестнадцатеричных цифры на байт, либо знаками кода ASCII, заключенными с обеих сторон в кавычки или двойные кавычки, причем

допускается чередование обеих форм представления данных в произвольном порядке. Перед записью заключенные в кавычки знаки кода ASCII буква за буквой переводятся в шестнадцатеричную форму, но сами кавычки не переводятся и не записываются. Побайтно вводимые данные допускается представлять одной шестнадцатеричной цифрой на байт, которая будет интерпретирована как младшая

– 176 –

Глава 6: Избранные программы для MS-DOS7

цифра байта, например, цифра "A" будет интерпретирована как 0Ah. В любом

случае запись данных в последовательно расположенные ячейки памяти производится в том порядке, в каком данные указаны в командной строке.

6.05-06 Отладчик DEBUG.EXE: команда "Fill"

Команда "Fill" (= заполнить) заполняет группу ячеек памяти повторяющейся записью одного и того же байта или одной и той же последовательности байтов. В командной строке отладчика DEBUG.EXE вызов команды "Fill" задается буквой

"F":

F 03E0 L2E 0D 0A 'Reserved' 90 90

В приведенном примере первый параметр это адрес первой ячейки из заполняемой группы ячеек, он представлен смещением 03E0h, но здесь допустимы все формы адресов, перечисленные в разделе 6.05-01. Если сегмент в адресе не указан, то по умолчанию он будет взят из регистра DS:. Второй параметр задает либо смещение для конечной ячейки группы (если числу не предшествует буква "L"), либо длину группы ячеек; в данном случае заявлена длина 2Eh байт. Третий и

все последующие параметры в приведенной командной строке представляют ту последовательность данных, которой надлежит заполнять ячейки памяти. Так или иначе длина, начальный адрес и хотя бы один байт данных в команде "F" должны быть заданы обязательно.

Данные в командной строке могут быть представлены либо побайтно, по две шестнадцатеричных цифры на байт, либо знаками кода ASCII, заключенными с обеих сторон в кавычки или двойные кавычки, причем допускается чередование обеих форм представления данных в произвольном порядке. Заключенные в кавычки знаки кода ASCII буква за буквой переводятся в шестнадцатеричную форму, но сами кавычки не переводятся и не записываются. Если после записи всех данных из командной строки не все ячейки в группе оказались заполнены, то процесс повторяется: следующие ячейки заполняются теми же данными. Напротив, если группа ячеек не вмещает записываемую последовательность данных целиком,

то процесс заполнения прекращается на последней ячейке без выдачи сообщения об ошибке.

6.05-07 Отладчик DEBUG.EXE: команда "Go"

Команда "Go" (= пошел!) запускает на исполнение весь заранее подготовленный код отлаживаемой программы или его часть. В командной строке отладчика DEBUG.EXE вызов команды "Go" задается буквой "G":

G =100 143

– 177 –

Глава 6: Избранные программы для MS-DOS7

Необязательные параметры после имени команды "G" – это адреса. Первый адрес, которому предшествует знак равенства, указывает на первый байт машинной команды, с которой следует начать исполнение. Этот адрес может быть задан в любой из допустимых форм (6.05-01). Если сегмент в адресе не указан, то по умолчанию он будет взят из регистра CS:. Если среди приведенных адресов не будет ни одного с предшествующим знаком равенства, то стартовый адрес будет взят из регистров CS:IP.

Адреса без предшествующего знака равенства это точки остановки (breakpoints), их можно указывать до 10 штук, чтобы хватило на каждую ветвь отлаживаемой программы. В точках остановки отладчик DEBUG.EXE замещает байты кода программы кодом "CCh" прерывания INT 03 (8.01-04). При исполнении прерывание INT 03 возвращает управление отладчику, и тогда он восстанавливает во всех точках остановки байты исходного кода отлаживаемой программы, а также сохраняет состояния регистров и флагов для продолжения отладки. Чтобы процесс завершился безошибочно, должны быть выполнены два условия. Во-первых, адреса точек остановки должны соответствовать первым байтам кода машинных команд, иначе код "CCh" будет воспринят не как прерывание INT 03, а как составная часть предыдущей машинной команды. Во-вторых, прекращение исполнения не должно произойти как-либо помимо точек остановки, потому что тогда отладчик не сохранит состояния регистров и флагов, не восстановит замещенные байты кода отлаживаемой программы, и ее придется перезагружать (командой "Load", 6.05-10).

Нужно иметь ввиду, что возможны еще два варианта завершения исполнения. Если в ходе исполнения произойдет вызов INT 21\AH=4Ch (8.02-55), то сеанс работы с отладчиком DEBUG.EXE закончится, управление будет возвращено к DOS. Если в ходе исполнения произойдет вызов INT 20 (8.02-01) или если при исходном состоянии стека будет выполнена команда RET (7.03-73), то управление будет передано от отлаживаемой программы к отладчику DEBUG.EXE, и он станет ожидать поступления следующих команд с клавиатуры или с перенаправления смотря по тому, как он был первоначально запущен. Когда последний вариант завершения (командой RET или вызовом INT 20) предусмотрен намеренно, тогда точки остановки после команды "G" указывать не нужно, и код отлаживаемой программы перезагружать обычно не приходится, однако состояния регистров и флагов не будут сохранены.

6.05-08 Отладчик DEBUG.EXE: команда "Hexadecimal"

Команда "Hexadecimal" (= шестнадцатеричный) рассчитывает и показывает на экране сумму и разность двух четырехзначных шестнадцатеричных чисел. В командной строке отладчика DEBUG.EXE вызов команды "Hexadecimal" задается буквой "H":

– 178 –

Глава 6: Избранные программы для MS-DOS7

H 12BA 00AE

В показанном примере два параметра представляют те числа, сумму и разность которых надлежит рассчитать. Если любое из них состоит менее чем из четырех цифр, то оно будет интерпретировано как содержащее нули в старших разрядах. Наличие обоих параметров в командной строке обязательно.

6.05-09 Отладчик DEBUG.EXE: команда "Input".

Команда "Input" (= ввод) считывает байт из указанного порта и показывает его на экране. Считанный байт никуда не записывается. В командной строке отладчика DEBUG.EXE вызов команды "Input" задается буквой "I":

I 03f8

Единственный обязательный параметр при команде "Input" – адрес порта, задаваемый четырехзначным шестнадцатеричным числом, в котором нули в старших разрядах можно опустить. Сегментный адрес перед адресом порта не имеет смысла и не допускается. Адреса некоторых портов приведены в приложении

A.14-1.

6.05-10 Отладчик DEBUG.EXE: команда "Load"

Команда "Load" (= загрузить) считывает код с диска и загружает его в память компьютера, начиная с указанного адреса. Допускаются две формы задания того, откуда именно нужно считывать код: по имени файла или по номеру сектора на логическом диске. В командной строке отладчика DEBUG.EXE вызов команды "Load" задается буквой "L". Вот пример вызова этой команды для считывания файла:

L 0100

Здесь единственный параметр адрес ячейки памяти, начиная с которой будет размещен в памяти код считываемого файла. Адрес может быть задан в любой из допустимых форм (6.05-01). Если указано только смещение, то по умолчанию сегментный адрес будет взят из регистра CS:.

Предполагается, что имя файла, который надлежит загрузить, заранее записано в PSP (A.07-1) командой "Name" (6.05-12) или автоматически перенесено туда из командной строки запуска отладчика DEBUG.EXE. Кроме того, предполагается, что сегментный адрес в регистре DS:, относительно которого адресуются данные в PSP, не изменился с момента внесения имени файла в PSP.

Если адрес после имени команды "L" не указан, то по умолчанию загрузка производится начиная с адреса CS:0100, за исключением загрузки файлов с суффиксами *.EXE и *.HEX, спецификации загрузки которых содержатся в их

– 179 –

Глава 6: Избранные программы для MS-DOS7

заголовке. Для файлов с суффиксом *.HEX адрес из заголовка суммируется с тем, который приведен в команде "L". Для файлов с суффиксом *.EXE адрес в команде "L" игнорируется, и заголовок файла не загружается. Чтобы увидеть "как есть" файлы, загружаемые без заголовка или вовсе не загружаемые, их суффикс надо заранее заменить (предпочтительно на *.BIN). В любом случае длина файла записывается в регистр CX. Если длина файла превышает 64 килобайта, то старшие разряды длины записываются в регистр BX.

Для загрузки кода из секторов логического диска в командной строке вызова команды "Load" должны быть указаны четыре обязательных параметра, например:

L 0100 2 0 1

Первый параметр, как и в предыдущем примере, – адрес ячейки памяти, начиная с которой будет размещен в памяти считываемый код. Второй параметр интерпретируется как номер логического диска: 0 – диск A:, 1 – диск B:, 2 – диск C: и т.д. Третий параметр номер сектора, четвертый количество считываемых секторов (допускается до 80h секторов). В частности, показанный пример команды задает считывание одного нулевого (загрузочного) сектора с логического диска C: и запись его содержания в ячейки памяти начиная с адреса CS:0100. В отличие от операции загрузки файлов, при считывании данных из секторов длина массива в регистры BX:CX не записывается. Считывание секторов за пределами логических дисков командой "Load" не обеспечивается.

6.05-11 Отладчик DEBUG.EXE: команда "Move"

Команда "Move" (= сдвинуть) копирует блок данных из одного места памяти в другое. В командной строке отладчика DEBUG.EXE вызов команды "Move" задается буквой "M":

M 0100 L20 0180

Здесь первый параметр начальный адрес исходного (копируемого) блока данных. Этот адрес может быть задан в любой из допустимых форм (6.05-01). Если вместо полного адреса задано только смещение, то сегментный адрес по умолчанию будет взят из регистра DS:.

Второй параметр в командной строке конечное смещение того же исходного блока данных (если ему не предшествует буква "L") или его длина; в данном примере длина 20h байт. Третий параметр стартовый адрес размещения копии. Он может быть дан в полной форме, указывающей на иной сегмент. Все три параметра в этой команде обязательны.

Если участки размещения исходного блока данных и копии не перекрываются, то данные в исходном блоке не изменяются. Если участок размещения копии перекрывает блок исходных данных, то они перезаписываются без

– 180 –

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]