На главную Назад
Добро пожаловать, уважаемый посетитель!

Программа DEBUG (отладчик) дает средство обнаружения ошибок при

работе с программой, транслированной в машинный язык.Программа

DEBUG обеспечивает возможность пошагово выполнять программу и

следить за тем, что при этом происходит.Программа DEBUG - это еще

одно программное средство, поставляемое как часть DOS.Вы

загружаете ее так же, как и любую другую программу, и работаете в

диалоге, используя клавиатуру и экран.Когда программа DEBUG

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

она обозначает символом "-".

 

Вместо перечисления всех команд, которые входят в программу

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

составленной программы, приведенной на Фиг. 5.13 и П5.14. На

Фиг. 5.17 приведен соответствующий листинг.

В данном примере сначала вызывается программа DEBUG и

указывается та программа, которую предполагается отлаживать - в

нашем случае программа FIG5=13.EXE. После того, как программа DEBUG

загружена, она производит загрузку отлаживаемой программы.

Управление теперь принадлежит отладчику, и он с помощью символа "-"

показывает, что ожидает ввода. До тех пор, пока вы не введете для

него указаний, с программой ничего происходить не будет.

 

Команда R выводит содержимое всех регистров в момент,

соответствующий загрузке программы FIG5=13 и передаче ей управления.

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

может, значений флагов.Флаг NV указывает на отсутствие

переполнения, флаг UP - флаг направления и т.д.При выводе

содержимого регистров в последней строке приводится следующая

выполняемая команда.В ячейке 04C5:0000 записана команда PUSH DS.

B>A:DEBUGFIG5_13.EXE

-R

 

AX=0000BX=0000CX=0120DX=0000SP=FFF0BP=0000SI=0000DI=0000

DS=2C26ES=2C26SS=2C26CS=2C26IP=0000NV UP DI PL NZ NA PO NC

2C26:00001EPUSH DS

 

-U

 

2C26:00001EPUSH DS

2C26:0001B80000MOV AX,0000

2C26:000450PUSH AX

2C26:0005FCCLD

2C26:00068CC8 MOV AX,CS

2C26:00088ED8 MOV DS,AX

2C26:000A8D361D00LEA SI,[001D]

2C26:000EACLODSB

2C26:000FA24000MOV [0040],AL

2C26:0012E82C00CALL 0041

2C26:0015803E40000ACMP [0040],0A

2C26:001A75F2 JNZ 000E

2C26:001CCBRET Far

2C26:001D9DPOPF

2C26:001EE2A0 LOOP FFC0

2C26:002020AFE0AEAND [BX+AEE0],CH

2C26:0024A3E0A0MOV [A0E0],AX

 

-D2C26:0

 

2C0E:0000CD 20 00 A0 00 9A EE FE 1D F0 ED 04 04 1C 3C 01. ............<.

2C0E:001022 1B EB 04 22 1B 04 1C 01 01 01 00 02 06 FF FF"..."...........

2C0E:0020FF FF FF FF FF FF FF FF FF FF FF FF 08 2C D0 FF.............,..

2C0E:003004 1C 14 00 18 00 0E 2C FF FF FF FF 00 00 00 00.......,........

2C0E:004000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................

2C0E:0050CD 21 CB 00 00 00 00 00 00 00 00 00 00 20 20 20.!...........

2C0E:006020 20 20 20 20 20 20 20 00 00 00 00 00 20 20 20.....

2C0E:007020 20 20 20 20 20 20 20 00 00 00 00 00 00 00 00........

 

-RAX

AX 0000

:1234

 

-E 2C0E:21

2C0E:002169.73.20.61.2020.

 

-G 3C

 

AX=0E54BX=0000CX=003FDX=0000SP=FFEABP=0000SI=001DDI=0000

DS=2C26ES=2C26SS=2C26CS=2C26IP=003CNV UP DI PL NZ NA PO NC

2C26:003C CD10INT10

-T

 

AX=0E54BX=0000CX=003FDX=0000SP=FFEABP=0000SI=001DDI=0000

DS=2C26ES=2C26SS=2C26CS=F000IP=0165NV UP DI PL NZ NA PO NC

F000:F065 FBSTI

-T

 

Фиг. 5.17 Листинг отладчика для Фиг 5.13 и 4.14 (начало)

AX=0E54BX=0000CX=003FDX=0000SP=FFEABP=0000SI=001DDI=0000

DS=2C26ES=2C26SS=2C26CS=F000IP=0166NV UP DI PL NZ NA PE NC

F000:F066 FCCLD

-G 2C26:3E

 

T

AX=0E54BX=0000CX=003FDX=0000SP=FFEABP=0000SI=001DDI=0000

DS=2C26ES=2C26SS=2C26CS=2C26IP=013ENV UP DI PL NZ NA PO NC

2C26:003ERET

-G

 

Эта программа - тест

 

Program terminated normally

-R

 

AX=0754BX=0000CX=003FDX=0000SP=FFEABP=0000SI=001DDI=0000

DS=2C26ES=2C26SS=2C26CS=2C26IP=003ENV UP DI PL NZ NA PO NC

2C26:003E C3RET

-Q

 

B>

 

Фиг. 5.17 Листинг отладчика для Фиг 5.13 и 4.14 (продолжение)

 

 

Здесь следует немного задержаться и проанализировать

информацию, которая записывается в регистры. Содержимое регистров

соответствует моменту, когда программа FIG5=13 получает управление

от командного процессора. Обратите внимание, что пара регистров

CS:IP указывает на первую команду, определяемую оператором END

программы. Регистры DS и ES указывают на префикс программного

сегмента. И наконец, пара регистров SS:SP указывает на сегмент

STACK. Описанное состояние регистров будет сравниваться позднее с

аналогичным состоянием регистров для файла типа .COM.

 

Чтобы просмотреть большее число команд, надо ввести символ "U"

(дизассемблировать), и на дисплей выводится около двадцати

следующих команд. Это удобно при обладке программы, для которой нет

листинга. Дизассемблирование программы позволяет просмотреть ее

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

программу внесены небольшие изменения. Так как ваш листинг больше

не соответствует той программе, которая находится в памяти, то ее

дизассемблирование позволяет вам узнать правильные адреса для

каждой команды.

 

Однако у дизассемблирования с помощью программы DEBUG имеется

ряд недостатков по сравнению с использованием листинга. Отсутствуют

комментарии (может быть очень важные для понимания программы), и

ячейки памяти идентифицируются только по адресу, а не по имени

переменной. Например, хранящаяся в ячейке 04C5:000E команда имеет,

как показано на Фиг.5.13, следующий вид:

 

MOVOUTPUT_CHARACTER,AL

 

а в дизассемблированном виде

 

MOV[0030],AL

 

Это одна и та же команда. Для программиста, выполняющего

отладку, имя переменной OUTPUT_CHARACTER говорит больше, чем адрес

ячейки [0030]. Однако программе DEBUG не известны имена переменных,

и она вынуждена оперировать фактическими адресами.

 

Кроме того, программа, DEBUG не обеспечивает той же самой

ассемблерной мнемоники, которую воспринимает ассемблер. Это значит,

что некоторые команды будут выглядеть по-разному. Команда из ячейки

04C5:0014 будет при дмзассемблировании иметь вид

 

CMPB,[3000],0A

 

но та же саммая команда на Фиг.5.13 представлена в виде:

 

CMPOUTPUT_CHARACTER,10

 

Программа дизассемблирования как на входе, так и на выходе

работает только с шестнадцатеричными значениями. Этим объясняется

появление значения 0A. Мы уже выяснили, почему получается значение

[0030], вместо имени OUTPUT_CHARACTER. Что же такое символ "B,"?

 

Ассемблер оперирует переменными вполне определенного типа. Это

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

значение: байт, слово или какой-нибудь другой. Таким образом, когда

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

ассемблеру известен размер этой области. На программа DEBUG не

имеет представления о длине переменной, записанной по адресу

[0030]. Однако программе дизассемблирования точно известно, что

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

непосредственно в команде, по адресу [0030]. Таким образом, символ

"B," указывает на то, что непосредственная операция состоит в

пересылке одного байта. Для получения того же самого результата с

помощью ассемблера соответствующая команда должна иметь вид:

 

CMPBYTE PTR [0030],10

 

Вы можете рассматривать символ "B," как сокращение BYTE PTR.

Аналогично символ W используется для WORD PTR,L - для длинного

(far) возврата и т.д.

 

Вместе с командой в дизассемблированном виде вводится и ее

объектный код. Как вы можете заметить, по адресу 04C5:001C записаны

какие-то команды, которых нет на Фиг. 5.13. Эта область данных,

содержащая строку "Это тест". Однако команде, осуществляющей

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

и начинаются данные. Таким образом она все интерпретирует как

команды. (Кстати, именно эта последовательность команд выполнялась

бы, если в вашей программе был сделан переход в рассматриваемую

область данных.)

 

Команда вывода на экран D позволяет просмотреть на дисплее

области данных. Отображение на экране состоит из двух частей.

Вместе с листингом содержимого ячеек памяти в шестнадцатеричном

представлении приводятся символы в коде ASCII, которые

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

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

ясно. Когда вам будет нечем особенно заняться, вы можете

попробовать написать такую программу, команды которой в коде ASCII

соответствуют инициалам вашего имени. С помощью отладчика можно

изменять содержимое регистров и ячеек памяти. Если ввести символ R

(регистр) и затем тип регистра, то на дисплей будет выведено

содержимое этого регистра с возможностью его коррекции. Если нажать

клавишу "возврат", то содержимое регистра останется прежним. Оно

будет изменено, если ввести новое значение.

 

Можно также модифицировать содержимое ячеек памяти. Ввод

символа E (редактирование) позволяет это сделать. При этом

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

после которых следует символ . Вы можете изменить содержимое

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

перейти к следующей ячейке, или - клавишу "возврат", чтобы

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

рассматриваемом примере значения в первых трех ячейках остаются

прежними. Содержимое ячейки 04C5:0024 изменено со значения 61H на

значенее 20H. Так как эта ячейка входит в область данных, то

выводимое сообщение будет отличаться от тог, которое было в

транслированной программе.

 

В любой команде, обращающейся к ячейкам памяти, предполагается,

что адрес является частью команды. Команда E, как и команда

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

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

дизассемблирования. Можно ввести адрес в виде сегмента и смещения,

или только смещения. Если вы указали только смещение, то

соответствующий сегментный регистр будет выбран программой DEBUG. В

случае команды U используется регистр CS, а для команд D и E по

умолчанию сегмент будет определяться регистром DS.

 

Теперь попытаемся выполнить эту программу. Ее можно просто

запустить и посмотреть, что будет происходить. На для этого не

нужна программа DEBUG. Программа DEBUG позволяет задать точки

останова, называемые "точками прерывания" программы. Благодаря

введению в программу таких точек можно возвращать управление

программе DEBUG. Это дает еще одну возможность проверки состояния

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

программы.

 

Команда G, (выполнять) передает управление от программы DEBUG

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

задаваемой парой регистров CS:IP (так же, как в реальном

микропроцессоре). Тестируемая программа продолжает выполняться до

тех пор, пока она не пройдет точку прерывания. В нашем примере мы

задали точку прерывания по адресу 3CH. Так как мы указали только

смещение, то для определения сегмента программа DEBUG использует

содержимое регистра CS. Из листинга, приведенного на Фиг. 5.14,

видно, что смещение 3CH соответствует команде INT 10H. В

рассматриваемом примере программы было выбрано именно это место,

потому что это - та точка, где управление передается подпрограмме

BIOS, вызываемой из ПЗУ. Проверка программы в этой точке

гарантирует, что мя установили регистры в нужное состояние перед

выполнением подпрограммы BIOS.

 

Как только встречается точка прерывания, управление

возвращается программе DEBUG. При этом, так же как и в случае

команды R, на дисплей выводятся содержимое регистров и следующая

выполняемая команда. Так как управление опять передано программе

DEBUG, вы можете использовать любую из команд отладки.

 

Имеются ограничения на использование точек прерывания.

Фактически точка прерывания реализуется кодом операции 0CCH.

Соответствующая этому коду команда вызывает прерывание INT 3.

Данное математическое прерывание возвращает управление программе

DEBUG. Если какая-то команда возвращает управление отладчику, то

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

точка прерывания выбрана где-то в другом месте, то управление не

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

программы, которая предполагалась. Например, если бы было задано

"=G 3D", то по адресу 3CH была бы команда INT 0CCH, и дальнейшее

выполнение программы предсказать трудно.

 

Если точка прерывания выбрана осмотрительно, то никаких

осложнений не будет. Командв "G" позволяет задать до десяти точек

прерывания. После прохождения любой из них происходит

восстановление исходных значений точек прерывания. Выполнение

команды отладки "G" без указания точек прерывания никогда не выйдет

ни на какую из ранее заданных точек прерывания, потому что все они

были удалены. Если вы запустили программу, и произошел ее останов и

она зациклилась, то возможно, что вернуть управление, которое

передано программе, удастся только с помощью клавиши системного

сброса Ctrl=Alt=Del, т.е. вам придется начать все с начала.

Запуская незнакомую программу, следует быть осторожным.

 

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

воспользуйтесь командой E для изменения значения первого байта

команды на значение 0CCH. Эта точка прерывания будет там постоянно

или, по крайней мере, до тех пор, пока вы ее не измените. Возможно

вы захотите использовать это прерывание в точке входа в

подпрограмму обработки ошибки и проанализируете возникающие ошибки

более тщательно, чем при передаче их обработки программе.

 

Существует еще одно обстоятельство, связанное с точками

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

точку прерывания в области, относящейся к ПЗУ, то ничего не

получится. Так как вы не можете менять содержимое ПЗУ, то команда

0CCH никогда туда не запишется.

 

Рассмотрим следующую команду отладчика - команда трассировки T.

Данная команда инициирует выполнение одной команды отлаженной

программы. В нашем примере команда T выполнена несколько раз. Как

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

вызванной по прерыванию INT 10H. Подпрограмма BIOS, естественно,

находится в ПЗУ. Команда трассировки позволяет "приостановить"

программу при ее выполнении в ПЗУ.

 

Перед передачей управления пользовательской программе команда

трассировки выставляет в регистре флагов соответствующий бит

трассировки. Этот бит инициирует прерывание INT 1 после выполнения

каждой команды. Вектор прерывания INT 1 возвращает управление

программе DEBUG. Выполнение прерывания INT 1 автоматически

сбрасывает бит трассировки в исходное состояние. Это значит, что

программа DEBUG не прерывается после выполнения каждой ее команды.

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

трудный участок программы. При этом программа DEBUG выводит на

экран каждую команду вместе с содержимым регистров как раз в

момент, предшествующий выполнению этой команды. Так как в данном

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

то можно выполнять трассировку даже программ ПЗУ.

 

Вернемся к нашему примеру. Команда =G 4C5:3E обеспечивает

полное выполнение подпрограммы BIOS. Обратите внимание, что

программа вывела на дисплей символ "Э". Вызванная по прерыванию 10H

подпрограмма BIOS выводит символы на дисплей. В данном случае это

первый символ выводимого сообщения. Так как теперь можно быть

уверенными, что наша программа выполняется правильно, то, введя

символ "G", мы обеспечим выполнение программы до конца без точек

прерывания.

 

В данном примере рассматривался файл типа .EXE, и потому для

возврата управления системе DOS мы не могли использовать прерывание

INT 20H. Вместо этого программа записала в стек состояние регистра

DS и значение 0. Управление передается обратно системе DOS в конце

основной программы с помощью команды возврата типа FAR. Программа

DEBUG распознает это и фиксирует состояние машины в конце

тестируемой программы. Если бы это был файл типа .EXE, то

прерывание INT 20H аналогичным образом вернуло бы управление

программе DEBUG. Теперь, уделив достаточно времени этому примеру,

мы можем выйти из программы DEBUG и вернуться в систему DOS с

помощью команды завершения Q.


 

Mail.ru