s
Sesiya.ru

4. Первая программа в отладчике. 4.1. Простая программа

Информация о работе

Тема
4. Первая программа в отладчике. 4.1. Простая программа
Тип Лекции
Предмет Информатика
Количество страниц 5
Язык работы Русский язык
Дата загрузки 2014-05-05 12:56:28
Размер файла 19.04 кб
Количество скачиваний 6
Скидка 15%

Поможем подготовить работу любой сложности

Заполнение заявки не обязывает Вас к заказу


Скачать файл с работой

Помогла работа? Поделись ссылкой

4. Первая программа в отладчике.
4.1. Простая программа.
Предположим, мы хотим изучить работу команды сложения двух целых чисел. Первое слагаемое хранится в слове со смещением 200h (в текущем сегменте данных) — оно будет загружено в регистр AX, второе слагаемое — число 2 — будет загружено в регистр BX, сумму требуется разместить в AX. Напишем с этой целью простую программу, содержащую всего три команды.
mov ax,[200h] ; Поместить в аккумулятор содержимое
; слова по адресу DS:200
mov bx,2 ; Поместить в регистр BX число 2 ( BX = 2)
add ax,bx ; Сложить содержимое AX и BX
; и поместить результат в AX (AX = AX + BX)

Комментарии отделены от текста программы точкой с запятой. Рекомендуется каждую фразу комментария начинать с прописной буквы. Если комментарий продолжается на следующей строке, то продолжение фразы начинается со строчной буквы. Следует понимать, что на самом деле эти три команды являются только фрагментом программы на языке ассемблера. Если мы собираемся использовать транслятор (например, MASM или TASM), то к этим командам нужно добавить еще ряд директив. Однако для отладчика этих команд достаточно. Еще заметим, что вместо последних двух команд можно было написать одну: add ax,2.

4.2. Вызов отладчика.
Вызовем отладчик. Для этого в Windows XP выполним команду Пуск → Все программы → Стандартные → Командная строка. В появившемся окне введите команду перехода в каталог prog, а затем вызовите td. (К сожалению, для наших следующих упражнений почему-то нельзя запускать Turbo Debugger из-под оболочки FAR.)
…> cd prog
C:prog>td

4.3. Ассемблирование текста программы.
В отладчике имеется мини-ассемблер. Он переводит мнемонику команд в их машинные коды.
Находясь в панели кода, начнем ввод команд программы. Нажмем букву m (первая буква команды mov ax,[200h]). Появляется окно "Enter instruction to assemble" (введите команду, которую нужно ассемблировать). Завершаем ввод команды и нажимаем Enter. Встроенный мини-ассемблер немедленно преобразует ее в машинный код. Полученный код подвергается обратной операции — дисассемблированию (получению мнемонической записи команд по их коду). Поэтому мы видим не тот текст, который мы ввели mov ax,[200h], а несколько другой: mov ax,[200]. Исчезла буква h, т.к. числа в отладчике — 16-ричные. Позднее мы встретим и более радикальные изменения вводимого текста. Для ввода следующей команды вызываем команду ассемблирования из локального меню нажатием Ctrl+A (или Alt+F10/Assemble...). В появляющемся диалоговом окне мы видим ранее введенную команду mov ax,[200h].Нажимем клавишу (ранее введенная команда становится выделенной). Нажимаем клавишу End (выделение снимается). Редактируем команду, чтобы получить mov bx,2. Аналогично набираем add ax,bx. И добавим еще команду nop (нет операции).
Вы увидите в панели кода
cs:0100►A10002 mov ax,[0200]
cs:0103 BB0200 mov bx,0002
cs:0106 03C3 add ax,bx
cs:0108 90 nop
Черный треугольник показывает команду, адрес которой содержится в CS:IP, т.е. команду, котрая будет выполнена первой при запуске программы на выполнение.
Если какая-либо команда будет введена неправильно, отладчик сообщит об этом. Например, если вы введете команду
mov ax[200] (пропущена запятая),
то последует сообщение: Invalid register combination in address expression (неверная регистровая комбинация в адресном выражении).
Код нашей программы занимает байты с 100-го по 108-й, т.е. девять байтов.
Полученные в результате строки имеют формат:
сегмент:смещение машинный код мнемоника
В кодах команд можно увидеть коды операндов в "перевернутом виде": Расшифруем код A10002. A1 — код пересылки содержимого ячейки памяти в аккумулятор, 00 — младший байт и 02 — старший байт операнда-источника. Аналогично расшифровывается код второй команды. Можно убедиться в том, что машинные коды имеют разную длину: в нашем примере — 1, 2 и 3 байта.

4.4. Заполнение памяти.
Перед выполнением программы нужно занести в слово памяти, расположенное по адресу DS:200, число 1. Можно было добавить это действие в нашу программу в качестве первой команды (чуть позже мы узнаем, как это сделать), но мы воспользуемся средствами отладчика.
Нажатием Sift+Tab перейдем в панель данных.
Перейдем на адрес 200: Alt+F10 → Goto. Появится окно с запросом адреса, на который надо перейти: Enter address to position to. Набираем 200 и нажимаем Enter. В панели данных отображается содержимое байтов, начиная с адреса DS:0200.
Мы можем ввести слово 0001 как два байта 1,0 (Alt+F10, Change или Ctrl+C). А можно ввести именно слово, предварительно отобразив содержимое панели данных как слова (Alt+F10 → Display as → Word или Ctrl+D,W).
В слово можно ввести отрицательное число, например, –16d (испытайте это: введите это число по адресу 204). А вот в байт отрицательное число непосредственно нельзя. Вернитесь к отображению байтов.
Допустим, нам нужно ввести в байт с адресом 208 (в панели данных) десятичное значение –120. Попытка ввода числа –120d приведет к сообщению Syntax error. Но в TD имеется возможность вычислять выражения. Найдем 16-ричный эквивалент –120d. Для этого выберем в главном меню Data → Evaluate/modify (или нажмем Ctrl+F4). Введем в поле Expression число –120d и нажмем Enter. В поле Result прочитаем: word –120 (FF88h). Отбрасывая расширение знакового бита, вводим число 88h.

4.5. Выполнение программы "по шагам".
В этом режиме после каждой команды выполнение будет приостанавливаться. Для этого нажимаем клавишу F7в (Trace — трассировка). Выполняется команда, адрес которой содержится в IP. Выполним первую команду.
Обратите внимание, что изменилось содержимое только двух регистров: AX — в него загружено значение 1, и IP — в нем адрес следующей выполняемой команды. Флаги не изменились.
Вновь нажмите F7. После выполнения второй команды меняется BX и IP. Флаги не изменились.
Только после выполнения команды add ax,bx изменилось содержимое регистра флагов. Правда это коснулось только одного флага PF (в младшем байте результата (03h=00000011b) установлено два бита, то есть четное число битов).

4.6. Выполнение всей программы.
Если нужно вновь прогнать программу по шагам, сначала следует в счетчик команд занести 0100 — адрес первой команды. Для этого переместитесь в панели кода на команду с адресом 100: Alt+F10 → Goto и введите 100. Будет выделена команда с адресом 100. А теперь сделаем так, чтобы IP содержал адрес этой команды: Alt+F10 → New cs:ip. В строке подсказки при выборе этого пункта меню вы увидите: Set the cs:ip to the current location — установить CS:IP в текущее положение курсора. Эквивалентная команда — Ctrl+N. Теперь вновь можно нажимать F7.
Занесите в слово по адресу 200 число –2. Посмотрим, как программа отработает с такими исходными данными. Выполнить программу как единое целое можно так: переместим курсор на команду nop в конце программы (только для этой цели она нам и понадобилась). При этом в IP, разумеется, должен быть стартовый адрес программы. Нажмем клавишу F4 (Here — здесь). Программа будет выполнена. Изучите флаги.

4.7. Сохранение файла с программой на диске.
Сохраним код программы. Для этого, нажимая Shift+Tab, перейдем в панель данных. Вызовем локальное меню: Alt+F10. Выбираем команду Block. Появляется новое меню (на это указывает стрелка, замыкающая название команды Block). Меню показано на рис. 4.1.

Clear...
Move...
Set...
Read...
Write...
Рис. 4.1.

Выбираем команду Write.... Появляется окно с запросом имени файла: "Enter write file name". В поле ввода File Name введем имя файла prg1.com. Имя, разумеется, может быть любым, а вот расширение — только .com, не .exe. Нажимаем Enter.
Появляется новое окно с запросом адреса блока памяти и количества байтов в блоке: Enter memory address, count. Наша программа расположена, начиная с адреса CS:0100. В панели данных подразумевается, что сегментная часть адреса блока находится в регистре DS. Но в панели регистров мы видим, что содержимое сегментных регистров CS и DS совпадает. Поэтому адрес блока можно задать как 100 — только смещение (offset), без указания сегментной части адреса. Количество записываемых байтов: 8h – 00FFh = 9h. Итак, в поле ввода указываем через запятую два числа: 100, 9, и нажимаем Enter.
Заметим, что если бы размер программы составил бы 2Dh, то ввод 100, 2d был бы ошибкой: в файл было бы записано всего два байта, т.к. d — суффикс десятичного числа. В этом случае обязательно надо указывать суффикс шестнадцатеричного числа: 100, 2dh.
Выход из отладчика осуществляем командой Alt+X.
Убедитесь, что в текущем каталоге действительно имеется файл prg1.com размера 9 байтов. Запускать его на выполнение из командной строки бессмысленно по двум причинам:
• программа не отображает результаты работы на экране, проследить ее работу можно только средствами отладчика;
• в программе нет команд, обеспечивающих возврат в DOS, поэтому после наших четырех команд начнет выполняться "мусор" с непредсказуемыми последствиями.

4.8. Отладка программы, хранящейся в файле.
Мы хотим еще поработать с нашей программой, записанной в файле prg1.com. Начать работу можно двумя способами.
а) Укажем имя файла в командной строке при запуске Turbo Debugger:
C:prog>td prg1.com
На экране появится окно с сообщением: Program has no symbol table (у программы нет таблицы символов). У этой программы действительно нет таблицы символов — информации, помогающей вести отладку. Создавать эту таблицу мы научимся позже. Нажимаем Enter, чтобы закрыть окно с этим сообщением. Теперь можно работать с программой.
б) Вызовем Turbo Debugger
C:prog>td
А теперь загрузим программу с использованием главного меню: F10 → File → Open. В диалоговом окне Load a new program to debug (Загрузить новую программу для отладки) заменяем в поле ввода Program name строку *.exe строкой *.com (т.е. мы будем загружать файл типа .com). Далее щелкаем по кнопке Browse (Обзор). Выбираем из списка файл prg1.com. Его имя появляется в поле ввода. После щелчка по кнопке OK получаем уже знакомое сообщение: Program has no symbol table.

4.9. Перемещение кода программы.
Пример. Предположим, мы набрали программу
cs:0100 mov ax,1
cs:0103 add ax,bx
cs:0105 nop
cs:0106
и обнаружили, что пропустили команду mov bx,2. Перемещаем часть программы со 103 по 105 "подальше". Затем введем недостающую команду и вернем перемещенный фрагмент на новый адрес.
Теперь опишем эту процедуру более детально. Перейдем в панель данных. В локальном меню: Alt+F10 → Block → Move. В нижней части экрана читаем подсказку Copy a block of memory to a new address (копирование блока памяти по новому адресу). Появляется диалоговое окно: Enter source address, destination, count (Введите адрес источника, адрес назначения, количество (байтов)). Вводим через запятую: 103, 400, 20. Мы не стали скрупулезно подсчитывать, сколько байтов занимает копируемый блок памяти, а взяли его «с запасом». Скопировали заодно и «мусор» в памяти, расположенный за нашей программой. Это не страшно. Переходим в панель кода и вводим недостающую команду
cs:0103 mov bx,2
cs:0106
Теперь мы знаем адрес назначения (0106) и перемещаем «хвост» программы. Для этого переходим в панель данных и вновь выбираем в локальном меню: Alt+F10 → Block → Move. Далее вводим: 400, 106, 20.
Заметим, что сегментные регистры CS и DS содержат одинаковые значения. Поэтому в качестве адреса блока достаточно было указать смещение. А вот если бы CS и DS указывали бы на разные сегменты, то пришлось бы указывать адрес блока полностью: cs:103, cs:400, 20. Ведь мы копируем данные.
Этот пример поучителен тем, что с кодами команд мы работаем как с данными.
Упражнение. Разработайте последовательность действий, если нужно удалить часть команд программы. О "перекрытии" области-приемника и области-источника беспокоиться не нужно (проверьте!).

4.10. Как получить текст программы, набранной в TD.
После отладки внесения необходимых изменений в команды программы хотелось бы получить файл с текстом программы, чтобы добавить в него комментарии, распечатать и т.д.
Для получения «мгновенных снимков» содержимого окон предназначено так называемое log-окно (log — это «журнал», куда записываются события, например, судовой журнал).
Можно рекомендовать следующую последовательность действий.
Пусть активной является панель кода. В главном меню: Edit → Dump pane to log (скопировать содержимое панели, отображаемое на экране, в log-окно). Перейдем в log-окно: F10 → View → Log. Мы видим в окне содержимое панели кода. А теперь с помощью локального меню этого окна откроем log-файл (Alt+F10 → Open log file). В диалоговом окне дадим файлу имя prg1.txt. Затем выполним в локальном меню команду: Close log file. Используя редактор FAR, вы можете удалить в файле prg1.txt лишние строки.
В процессе выполнения программы по шагам в log-окно можно отправлять копии содержимого панелей несколько раз. Например, для программы, которую мы только что рассмотрели, можно было после выполнения каждой команды копировать в log-окно содержимое окна с регистрами и окна с флагами (попробуйте!). Если программа работает с памятью, то удобно записывать состояние памяти до и после выполнения программы.

© Copyright 2012-2020, Все права защищены.