Интерактивный отладчик TD

Часто бывает так, что программа, успешно пройдя этапы трансляции и компоновки, все же работает не так, как ожидалось или вообще не работает. Это значит, что формально, с точки зрения правил языка программирования, программа написана правильно (в ней нет синтаксических ошибок), однако алгоритм ее в чем-то неверен. Для отладки такой программы следует воспользоваться услугами интерактивного отладчика. Интерактивным он называется потому, что вся работа с ним осуществляется в непрерывном диалоге с пользователем.

Познакомимся с отладчиком TD.EXE из пакета TASM, воспользовавшись программой из первого примера.

Как уже отмечалось, для полного использования возможностей отладчика следует при трансляции программы указать в числе других ключ /zi, а при компоновке - ключ /v:

tasm /z/zi/n p,p,p 
tlink /v p,p 

Кроме того, следует убедиться, что в вашем рабочем каталоге имеется и загрузочный (Р.ЕХЕ) и исходный (P.ASM) файл, поскольку отладчик в своей работе использует оба этих файла. Вызовем отладчик командой

td p

На экране появится кадр отладчика, в котором видны два окна - окно Module с исходным текстом отлаживаемой программы и окно Watches для наблюдения за ходом изменения заданных переменных в процессе выполнения программы (см.рис.).

Окно Watches нам не понадобится, и его можно убрать, щелкнув мышью по маленькому квадратику в левом верхнем углу окна или введя команду Alt+F3, предварительно сделав это окно активным. Переключение (по кругу) между окнами осуществляется клавишей F6.

Верхняя строка кадра отладчика представляет собой главное меню. Для перехода в меню необходимо нажать клавишу Alt и первую (выделенную цветом) букву требуемого пункта. Для выбора затем конкретного действия надо с помощью клавиш со стрелками вверх и вниз- выделить нужный пункт и нажать клавишу Enter.

В нижней строке отладчика приведены его основные команды, вызов которых осуществляется нажатием на функциональные клавиши F1...F10. В действительности команд гораздо больше; некоторые из них можно реализовать только с помощью пунктов главного меню, другие вызываются комбинациями функциональных и управляющих (Alt, Ctrl или Shift) клавиш.

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

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

Нажав одну из клавиш F8 или F7, мы выполним одно предложение программы. Различие этих команд весьма существенно: команда F7 (trace, трассировка) позволяет войти внутрь вызываемых подпрограмм, а также выполнять циклы шаг за шагом. Команда F8 (step, шаг), наоборот, выполняет подпрограммы и циклы как одно неразрывное действие, что заметно ускоряет пошаговую отладку программы, если мы, например, уверены, что вызываемая подпрограмма выполняется правильно.

Можно выполнить сразу и целый фрагмент программы, т. е. несколько предложений. Для этого надо поместить курсор _ перед тем предложением, на котором требуется сделать остановку (или на любой символ внутри него), и нажать клавишу F4 (here, сюда). Выполнятся все строки программы до той, на которой установлен курсор; значок сплошной треугольник переместится на эту строку. Далее можно опять выполнять программу построчно, нажимая на клавишу F8, или, установив в требуемом месте курсор, выполнить следующий фрагмент, нажав F4.

Для повторного выполнения программы ее следует "рестартовать". Для этого надо выбрать в главном меню пункт Run-Program reset или просто нажать Ctrl+F2.

Важнейшим элементом отладки программы является наблюдение значений тех или иных полей данных, особенно тех, которые заполняются программой динамически, т. е. по ходу ее выполнения. Для того чтобы вывести на экран содержимое поля данных, надо поместить курсор на имя этого поля (например, mesg в нашем примере) и выбрать пункт меню Data-Inspect. В появившемся окне ввода переменной (см.рис.) можно скорректировать имя интересующего нас поля данных или ввести новое; если имя правильное, достаточно нажать клавишу Enter.

В кадр отладчика будет выведено окно с характеристиками и содержимым указанной переменной (см.рис.). Отладчик сообщает, что переменная mesg хранится в памяти по адресу 5D82:000, т. е. имеет сегментный адрес 5D82h и смещение OOOOh, и описана как последовательность из 12 байт. Тут же приводятся значения всех байтов нашей строки, включая их начертание на экране, а также десятичное и 16-ричное представление.

В окне Inspecting можно изменить значение отображаемого поля данных. Для этого надо, сделав это окно активным и поместив курсор на отображение конкретного элемента нашего символьного массива, например элемента с индексом 12 (знак "!"), ввести команду Alt+F10. Эта команда для любого активного окна открывает его внутреннее меню с дополнительными возможностями. В данном случае внутреннее меню будет иметь вид, показанный на нижнем рисунке.

Нас будет интересовать пункт Change (изменение). Выбрав этот пункт, мы получим окно, в котором можно ввести требуемое значение изменяемого данного. На следующем рисунке показано это окно с введенным символом '>', которым будет заменен восклицательный знак. Можно было вместо символа в одинарных кавычках ввести его 16-ричный код ASCII, если он известен (число ЗЕ для знака >). Допустим ввод и десятичного кода, если завершить его буквой d F2d).

Если теперь, не выходя из отладчика, выполнить программу до конца, на экран вместо ! будет выведен >.

Для того чтобы, находясь в отладчике, увидеть результат работы программы, надо ввести команду Alt+F5 (или выбрать пункт Window-User screen главного меню). Возврат в кадр отладчика осуществляется нажатием любой клавиши.

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

Начальное окно отладчика дает недостаточно информации для серьезной работы с программой. При отладке программы на уровне языка ассемблера необходимо контролировать все регистры процессора, включая регистр флагов, а также во многих случаях поля данных вне программы (например, векторы прерываний или системные таблицы). Для этого надо командой Alt+V, С (пункт главного меню View-CPU) открыть "окно процессора" (см.рис.).

Окно процессора состоит, в свою очередь, из пяти внутренних окон для наблюдения текста программы на языке ассемблера и в машинных кодах, регистров процессора, флагов, стека и содержимого памяти. С помощью этих окон можно полностью контролировать работу процессора при выполнении отлаживаемой программы. Для того чтобы можно было работать с конкретным окном, надо сделать его активным, щелкнув по нему мышью. Переходить из окна в окно можно также (по кругу), нажимая клавишу Tab. Для управления ходом программы используются функциональные клавиши, перечисленные в нижней строке кадра (F7 или F8 для пошагового выполнения, F4 для выполнения до курсора и т. д.). Курсор во всех внутренних окнах окна процессора выглядит в виде синей ленточки. Добавим еще, что, щелкнув мышью по значку стрелки вверх в правом верхнем углу окна процессора, можно увеличить это окно до размеров кадра отладчика.

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

Выполните программу до первой команды int 21h (предложение 7) и просмотрите содержимое регистров процессора. Вы увидите, что в старшей половине регистра АХ находится число 09h - номер вызываемой функции DOS. Младшая половина регистра АХ заполнена "мусором" - остатком от выполнения последней операции с регистром АХ. В регистре DX будет OOOOh - относительный адрес первого байта строки mesg в сегменте команд. Изменим этот относительный адрес. Для этого надо перейти в окно регистров, поместить курсор на строку, отображающую содержимое регистра DX, и ввести команду Alt+F10, открывающую внутреннее меню окна регистров (см.рис.).

Как видно из рисунка, меню окна регистров предоставляет возможность выполнить увеличение содержимого регистра на 1 (Increment), уменьшить его на 1 (Decrement), обнулить (Zero) и заменить на любое заданное значение (Change). Выбрав пункт Change, занесем в регистр DX число 5 (см.рис.).

Теперь, если выполнить очередную команду (int 21h), DOS выведет на экран строку, начало которой расположено в байте 5 сегмента данных. В нашей фразе "Hello, world!" байт 5 приходится на запятую (нумерация байтов в строке, естественно, начинается с нуля). В результате на экран будет выведена строка

, world!

Еще одной полезной операцией является вывод содержимого области памяти, начиная с заданного адреса (дамп памяти). Таким образом можно изучать не только поля данных программы, но и содержимое вообще любых участков памяти компьютера, в частности системных таблиц. Посмотрим, например, как выглядит в памяти блок окружения программы.

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

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

PROMPT= $p$g 
PATH=C:\DOS; C:\TOOLS; C:\NC;

Здесь PROMPT и PATH - переменные окружения, а справа от знака равенства указаны их конкретные значения, которое могут быть и другими. Переменная PROMPT определяет форму системного запроса, выводимого командным процессором на экран после завершения любой текущей программы, а переменная PATH - пути к программным файлам, которые будут вызываться на выполнение просто по именам, без указания полной спецификации.

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

Hosted by uCoz