Турбо отладчик (Turbo Debugger) 3.0

         

либо пока CX не становится


       ние, либо пока CX не становится равным нулю, либо пока не обнару-
       жится что операнды равны.  К несчастью, легко перепутать, где ка-
       кой префикс нужно использовать.
                    Ошибки при назначении сегмента строк
       -----------------------------------------------------------------
            Все строковые команды по  умолчанию  используют  в  качестве
       сегмента исходных данных (если он есть) сегмент DS,  а в качестве
       сегмента результирующих данных (если он есть) сегмент  ES.  Легко
       забыть об этом и попытаться,  скажем, выполнить команду STOSB над
       сегментом данных, поскольку все данные, обрабатываемые не строко-
       выми командами, обычно находятся именно в этом сегменте.
                Неправильное преобразование из байта в слово
       -----------------------------------------------------------------

       TDeb 3.0 #2-3               = 142 =
            В общем случае,  для команд обработки строк  желательно  ис-
       пользовать  максимально возможный размер данных (обычно слово,  а
       для процессора 80386 - двойное слово),  поскольку с данными боль-
       шего размера эти команды обычно работают быстрее.
            Однако здесь имеются две ловушки.  Во-первых, преобразование
       из количества байт в количество слов с помощью простой команды:


            shr cx,l
       приведет к потере байта,  если CX имеет нечетное  значение,  пос-
       кольку младший значащий бит будет сдвинут за пределы слова.
            Во-вторых, следует помнить, что команда SHR делит количество
       байт на два.  Использование,  скажем, команды STOSW с количеством
       байт,  а не слов,  может уничтожить другие данные и вызвать самые
       разнообразные ошибки.
                     Использование нескольких префиксов
       -----------------------------------------------------------------
            Команды обработки  строк  с  несколькими префиксами работают
       ненадежно, и их следует по возможности избегать.

ются только для задания размера


             Необязательные операнды в командах обработки строк
       -----------------------------------------------------------------
            Необязательные операнды в командах обработки строк использу-
       ются только для задания размера данных и изменения сегмента  и не
       гарантируют фактический доступ к данной области памяти.
               Уничтожение содержимого регистра при умножении
       -----------------------------------------------------------------
            Умножение (8 на 8 бит,  16 на 16 бит,  либо 32 на  32  бита)
       всегда уничтожает содержимое как минимум одного регистра,  не яв-
       ляющегося накапливающим регистром, который используется в качест-
       ве исходного операнда.

       TDeb 3.0 #2-3               = 143 =
            Ошибки, связанные с изменением содержимого регистров
       -----------------------------------------------------------------
            Команды обработки строк,  такие как MOVS, STOS, LODS, CMPS и
       SCAS,  могут  влиять  на  состояние некоторых флагов и содержимое
       трех регистров при выполнении единственной команды. При использо-
       вании команд обработки строк следует помнить,  что содержимое од-
       ного из регистров SI или DI (или обоих  сразу)  получает  положи-
       тельное  или отрицательное приращение (в зависимости от состояния
       флага направления) при каждом выполнении команды обработки строк.
       Содержимое  регистра  CX  также получает отрицательное приращение
       как минимум один раз и,  возможно, уменьшается до нуля при каждом
       использовании команды обработки строк с префиксом REP.
                     Изменение состояния флага переноса
       -----------------------------------------------------------------
            В то время как одни команды неожиданно для программиста вли-
       яют на состояние регистров и флагов, другие команды не влияют да-
       же на те флаги, состояние которых было бы желательно изменить.

Состояние флагов  сохраняется до тех


                    Программист долго не использует флаги
       -----------------------------------------------------------------
            Состояние флагов  сохраняется до тех пор,  пока не будет вы-
       полнена следующая команда,  которая его изменяет, что обычно про-
       исходит достаточно быстро.  Поэтому рекомендуется после установки
       флагов выполнять действия над ними как можно быстрее, чтобы избе-
       жать самых разнообразных ошибок,  связанных с неверной установкой
       флагов.
          Смешение операндов в памяти и непосредственных операндов
       -----------------------------------------------------------------
            Программа на языке Ассемблера может обращаться либо к смеще-
       нию области памяти,  в которой хранится переменная, либо к значе-
       нию этой переменной. К сожалению, в языке Ассемблера нет ни инту-
       итивных,  ни строгих способов, позволяющих различить эти два вида
       обращений,  и  в результате программисты часто путают обращения к
       смещению и обращения к значению.
               Ошибки, связанные с возвратом в начало сегмента
       -----------------------------------------------------------------
            Один из  самых  сложных моментов в программировании для мик-
       ропроцессора 8086 состоит в том,  что к памяти нельзя  обращаться
       как к  одному большому массиву байт.  Вместо этого память делится
       на части (сегменты) размером 64К (килобайт),  и доступ к ним осу-
       ществляется  через сегментные регистры.  Сегментация памяти может
       вызвать труднообнаруживаемые ошибки, поскольку если программа пы-
       тается  обратиться к адресу,  который находится за границами сег-
       мента, в действительности вместо этого происходит возврат в нача-
       ло того же сегмента.

       TDeb 3.0 #2-3               = 144 =
          Сохранение содержимого регистров при обработке прерываний
       -----------------------------------------------------------------

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


            Каждый обработчик прерываний  должен  обязательно  сохранять
       содержимое всех регистров.  Хотя и допускается сохранять содержи-
       мое только тех регистров,  которое изменяется данным обработчиком
       прерываний,  для  надежности работы все же рекомендуется заносить
       содержимое всех регистров в стек при входе в обработчик  прерыва-
       ний и извлекать его из стека при выходе.
              Игнорирование групп в таблицах операндов и данных
       -----------------------------------------------------------------
            Использование сегментных групп позволяет программисту  логи-
       чески  разбивать данные на несколько областей,  исключая при этом
       необходимость загружать сегментный регистр каждый раз,  когда не-
       обходимо  перейти  от одной из таких логических областей данных к
       другой.
            К сожалению,  тот способ, который используется для обработки
       сегментных  групп в макроассемблере фирмы Microsoft (MASM), может
       вызвать некоторые проблемы, и пока не появился язык Турбо Ассемб-
       лер, сегментные группы доставляли программистам много неприятнос-
       тей.  И хотя этих неприятностей практически невозможно было избе-
       жать, сегментные группы были нужны для связи ассемблерного кода с
       языками высокого уровня, такими как Си.
            В режиме Quirks языка MASM Турбо Ассемблер эмулирует MASM, и
       это  означает,  что в этом режиме он имеет те же проблемы,  что и
       MASM.Если вы не собираетесь использовать режим Quirks языка MASM,
       можете  больше ничего о нем не читать,  однако если вы планируете
       работать с этим режимом, вам следует обратиться за дополнительной
       информацией  к "Руководству пользователя по Турбо Ассемблеру".

       TDeb 3.0 #2-3               = 145 =
                                  Проверка
       -----------------------------------------------------------------
            Создание программы с допустимыми входными данными составляет

прежде чем можно будет сделать


       только  часть функций проверки.  В следующих разделах обсуждаются
       некоторые важные случаи  проверки,  которым  должны  подвергаться
       каждая программа,  прежде чем можно будет сделать вывод о ее пра-
       вильной работе.
               Проверка граничных условий и случаи ограничения
       -----------------------------------------------------------------
            Если вы считаете,  что подпрограмма должна работать с данны-
       ми,  принимающими значение в определенном  диапазоне,  вы  должны
       подвергнуть эту подпрограмму проверке с данными, принимающим раз-
       личные значение в этом диапазоне.  Например,  если в вас  имеется
       подпрограмма, выводящая на экран список длиной от 1 до 20 элемен-
       тов,  вы должны убедиться,  что она ведет себя правильно и в  том
       случае,  когда в списке имеется ровно 1 элемент,  и в том случае,
       когда в списке 20 элементов  (здесь  могут  скрываться  различные
       ошибки,  в частности, ошибка типа "столбы и забор", описанная ра-
       нее).
                            Ввод ошибочных данных
       -----------------------------------------------------------------
            Когда вы убедитесь, что программа работает во всем диапазоне
       допустимых данных, следует убедиться, что она ведет себя коррект-
       но,  когда вы задаете недопустимые входные данные. Например, убе-
       дившись,  что предыдущая программа воспринимает значения в диапа-
       зоне от 1 до 20,  нужно также убедиться, что 0 или 21 значение ей
       отвергаются.
                          Отсутствие входных данных
       -----------------------------------------------------------------
            Этот момент  при проверке и создании программы часто упуска-
       ют.  Если вы пишете программу,  которая правильно себя ведет  при
       отсутствии входных данных, работа с ней значительно упростится.
               Отладка, как часть процесса создание программы

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


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

       TDeb 3.0 #2-3               = 146 =
       отлаживать,  поскольку до возникновения опасной ситуации подпрог-
       раммы сами сообщают вам о недопустимых входных данных.
            Можно также реализовать программу, в которой выполняется ма-
       ло проверок на допустимость входных и выходных данных  или  такие
       проверки  совсем  отсутствуют.  Такая  программа будет меньшей по
       объему и будет быстрее выполняться,  но неверные  входные  данные
       или  маленькая  ошибка  могут привести к аварийному завершению ее
       работы.  Такой тип программ обычно труднее всего отлаживать,  так
       как  небольшая  ошибка  может  проявиться  при выполнении намного
       позднее.  Это затрудняет выявление  того  места,  где  содержится
       ошибка.
            Большинство создаваемых  программ  сочетают  в себе оба этих
       метода.  Данные,  воспринимаемые из внешних источников (например,
       вводимые пользователем или считываемые из файла на диске) подвер-
       гаются обычно более тщательной проверке, чем данные, передаваемые
       при вызове от одной подпрограммы к другой.

       TDeb 3.0 #2-3               = 147 =
                            Пример сеанса отладки
       -----------------------------------------------------------------

В примере сеанса отладки используются


            В примере сеанса отладки используются те методы,  о  которых
       мы  рассказывали  в  предыдущих разделах.  Отлаживаемая программа
       представляет собой вариант демонстрационной программы,  использо-
       ванной в Главе 3 (BCDEMO.C или TPDEMO.PAS),  только в нее предна-
       меренно внесены некоторые ошибки.
            Убедитесь, что  в вашем текущем каталоге содержатся два фай-
       ла,  необходимые для демонстрации отладки.  Если  вы  отлаживаете
       программу  на Турбо Паскале,  вам понадобятся файлы TPDEMOB.PAS и
       TPDEMOB.EXE. Если вы работаете на языке Си, вам потребуются файлы
       BCDEMOB.C и BCDEMOB.EXE.  (Буква B в конце имен файлов, означает,
       что в эту версию внесена ошибка.)
                     Сеанс отладки программы на языке Си
       -----------------------------------------------------------------
            В данном разделе в качестве примера  используется  программа
       на языке Си.  Если вы программируете на Паскале,  см. ниже пример
       сеанса отладки с использованием программы Турбо Паскаля.
                                Поиск ошибок
       -----------------------------------------------------------------
            До того,  как начать сеанс отладки, давайте запустим демонс-
       трационную программу с ошибкой и посмотрим, что она делает непра-
       вильно. Для запуска программы наберите:
               BCDEMOB
            Вам выведется подсказка для ввода строк текста. Введите  две
       строки текста:
               one two three
               four five six
            Последняя пустая строка  завершает  ваш  ввод.  После  этого
       программа  BCDEMOB  выводит  результаты  анализа  введенных  вами
       строк:
            Arguments:                                              (1)
            Enter a line (empty line to end): one two three         (2)
            Enter a line (empty line to end): fou five six
            Enter a line (empty line to end):

Average number of words per


            Total number of letters = 7                             (3)
            Total number of lines = 6                               (4)
            Total word count = 2                                    (5)
            Average number of words per line = 0.3333333            (6)
            'E' orrurs 1 times, 0 times at start of a word          (7)
            'F' occurs 1 times, 1 times at start of a word
            'N' occurs 1 times, 0 times at start of a word

       TDeb 3.0 #2-3               = 148 =
            'O' occurs 2 times, 1 times at start of a word
            'R' occurs 1 times, 0 times at start of a word
            'U' occurs 1 times, 0 times at start of a word
            There is one word 3 characters long                     (8)
            There is one word 4 characters long                     (9)
            1 -  аргументы;  2 - введите строку (пустая строка завершает
       ввод);  3 - общее число букв;  4 - общее число строк;  5 -  общее
       число слов; 6 - среднее число слов на строке; 7 - 'E' встречается
       1 раз,  0 раз в начале слова; 8 - имеется одно слово длиной в три
       символа; 9 - имеется одно слово длиной в 4 символа.
            Заметим, что в общем числе слов и букв имеется ошибка. Позд-
       нее окажется, что таблицы частот букв и слов основываются на оши-
       бочном  значении  счетчика букв и слов.  Такая ситуация,  когда в
       программе сразу несколько неверных мест,  довольно  типична.  Это
       часто встречается на начальном этапе отладки.
                          Разработка плана действий
       -----------------------------------------------------------------
            Первая задача состоит в том,  чтобы решить,  с какой ошибкой
       нужно разобраться в первую очередь.  Хорошим правилом здесь явля-
       ется следующее правило:  начинайте с  ошибки,  которая  произошла
       "первой".  В  данной программе каждая вводимая строка разбивается
       на слова,  после чего анализируется, наконец, когда будут введены

все строки выводятся таблицы. Так


       все строки выводятся таблицы. Так как счетчики букв и слов, как и
       таблицы, неверны, можно предположить, что что-то делается неверно
       при начальной разбивке и подсчете.
            Теперь, после того, как вы немного обдумали проблему и наме-
       тили  в  общих  чертах пути решения,  пора начать отладку.  Здесь
       стратегия будет состоять  в  том,  чтобы  проверить  подпрограмму
       makeintowords и посмотреть,  правильно ли она разбивает строку на
       завершающиеся нулевым символом слова,  а затем  посмотреть,  пра-
       вильно  ли подпрограмма analyzewords выполняет подсчет для анали-
       зируемой строки.
                           Запуск Турбо отладчика
       -----------------------------------------------------------------
            Чтобы запустить пример сеанса отладки, наберите:
               TD BCDEMOB
            При этом Турбо отладчик загрузит демонстрационную программу,
       в которой содержится ошибка,  и выведет начальный экран.  Если вы
       хотите выйти из сеанса отладки и вернуться в DOS, нажмите клавиши
       Alt-X  (это  можно  сделать  в любой момент).  Если вы безнадежно
       "заблудились", можно в любое время перезагрузить демонстрационную
       программу, нажав клавиши Ctrl-F2, и начать сначала (при этом точ-
       ки останова и выражения просмотра очищены не будут).

       TDeb 3.0 #2-3               = 149 =
            Поскольку первое,  что нам нужно сделать - это проверка пра-
       вильности работы   подпрограммы  makeintowords,  нужно  выполнить
       программу до выполнения этой подпрограммы, а затем проверить все,
       что требуется.  В этом случае можно использовать два подхода:  вы
       можете выполнить шаг программы,  выполнив makeintowords и убедив-
       шись,что она делает все правильно, или можно остановить программу
       после выполнения подпрограммы makeintowords,  и проверить ее  ре-
       зультаты.
            Убедиться в правильности работы  подпрограммы  makeintowords

Для этого можно проверить формируемый


       довольно просто.  Для этого можно проверить формируемый ей выход-
       ной буфер.  Давайте выберем второй подход. Чтобы сделать это, пе-
       реместите  курсор  на  строку  42 и нажмите клавишу F4,  выполнив
       программу до этой строки.  Появится экран программы,  после  чего
       вам нужно ввести:
               one two three
       и нажать клавишу Enter.
                                  Проверка
       -----------------------------------------------------------------
            Итак, вы остановились на строке исходного кода  после вызова
       функции makeintowords. Взгляните на содержимое буфера и посмотри-
       те,  все ли правильно.  Переместите курсор на одну строку вверх и
       поместите его под словом buffer. После этого нажмите Alt-F10 (для
       вывода окна Inspector (Проверка)).  В окне проверки выведется со-
       держимое буфера buffer.  Для просмотре элементов массива  исполь-
       зуйте   клавиши  стрелок.  Обратите  внимание,  что  подпрограмма
       makeintowords действительно поместила в конце каждого слова нуле-
       вой  символ (0).  Это означает,  что вам нужно просмотреть другую
       часть программы и проверить,  правильно ли работает  подпрограмма
       analyzewords. Для этого сначала удалите окно проверки, нажав кла-
       вишу Esc. Затем дважды нажмите клавишу F7 для выполнения програм-
       мы до начала работы analyzewords.
            Проверьте, что analyzewords была вызвана с корректным указа-
       телем  в буфере.  Для этого переместите курсор под bufp и нажмите
       Alt-F10 I. Вы увидите, что bufp действительно указывает на завер-
       шающуюся  нулевым  символом строку 'one'.  Для удаления окна про-
       верки нажмите клавишу Esc.  Поскольку ошибка возникает, очевидно,
       при  подсчете символов и слов,  давайте поместим точку останова в
       то место,  где подсчитываются слова и символы.
            1. Переместите  курсор  на  строку  93 и нажмите клавишу F2,

установите точку останова на строке


               чтобы установить точку останова.
            2. Переместитесь на строку 97 и установите другую точку  ос-
               танова.
            2. Наконец, установите точку останова на строке 99, благода-
               ря чему вы сможете увидеть  значение  счетчика  символов,

       TDeb 3.0 #2-3               = 150 =
               возвращаемое данной функцией.
            Задание нескольких  точек останова  (как в данном примере) -
       это типичный способ, позволяющий узнать, все ли в программе дела-
       ется правильно, и проверить значения важных данных при каждом ос-
       танове программы на очередной точке останова.

       TDeb 3.0 #2-3               = 151 =
                                 Окно Watch
       -----------------------------------------------------------------
            Запустите программу,  нажав клавишу F9. Программа остановит-
       ся, когда она достигнет точки останова на строке 93. Теперь можно
       просмотреть значение charcount (счетчик символов). Так как вы хо-
       тите проверять его каждый раз, когда встречается данная точка ос-
       танова,  удобно использовать команду Watch (Просмотр),  чтобы по-
       местить  charcount в окно Watches (Просмотр).  Переместите курсор
       под wordcounts (счетчик слов) и нажмите Alt-F10 W.  В окне  прос-
       мотра  в нижней части экрана выводится текущее значение 0.  Чтобы
       убедиться,  что символ подсчитывается правильно,  выполните  одну
       строку, нажав клавишу F7. В окне просмотра (Watches) действитель-
       но выводится, что значение charcount = 1.
                       Диалоговое окно Evaluate/Modify
       ------------------------------------------------------------------
            Снова запустите программу,  нажав клавишу F9. Теперь вы вер-
       нулись  на строку 93 для обработки другого символа.  Снова дважды
       нажмите F9 для считывания последней буквы  слова  и  завершающего
       нуля. Теперь charcount показывает корректное значение 3, а массив

wordcounts будет обновлен для подсчета


       wordcounts будет обновлен для подсчета слов.  Далее все  отлично.
       Нажмите снова F9, чтобы начать обработку следующего слова в буфе-
       ре. Ага! Что-то не так.
            Вы ожидаете,  что программа остановится снова на  строке  93
       (на  точке останова) для обработки другого символа.  Но она этого
       не делает.  Она выполняется дальше  и  возвращается  из  функции.
       Единственным  путем оказаться на строке 99 является истинное зна-
       чение проверяемого в цикле  while  значения.  Это  означает,  что
       *bufp  !=  0  должно  при  вычислении  получать  ложное  значение
       (false).
            Чтобы проверить это,  переместитесь к строке 83  и  отметьте
       все  выражение *bufp != 0,  поместив курсор под *,  нажав клавишу
       Ins,  и переместив курсор на завершающий 0 перед ). Теперь вычис-
       лите это  выражение,  открыв диалоговое окно Data¦Evaluate/Modify
       (Данные¦Вычисление/Модификация) и нажав клавишу  Enter,  а  затем
       выбрав переключатель Eval (Вычисление),  чтобы отмеченное выраже-
       ние было воспринято. Значение в самом деле равно 0. Нажмите дваж-
       ды клавишу Esc для возврата в окно Module (Модуль).
                                   Эврика!
       -----------------------------------------------------------------
            Теперь, чтобы обнаружить ошибку,  нужно сделать некий анали-
       тический скачок. Причина того, что bufp указывает на 0, состоит в
       том, что внутренний цикл while, начинающийся на строке 86, остав-
       ляет его в конце слова.  Для продолжения на  следующем  слове  вы
       должны  увеличить  bufp  и переместить его с 0,  который завершал

       TDeb 3.0 #2-3               = 152 =
       предыдущее слово.  Для этого перед строкой 97 нужно добавить опе-
       ратор "bufp++". Вы можете перекомпилировать свою программу с этим
       оператором, однако Турбо отладчик позволяет вам "вставлять" выра-
       жения, используя для этого особый вид точек останова.

Для этого нужно сначала перезагрузить


            Для этого нужно сначала перезагрузить программу,  нажав кла-
       виши Ctrl-F2 (после этого вы можете начать проверку, сбросив сос-
       тояние программы). Теперь удалите все точки останова, которые бы-
       ли вами установлены в предыдущем сеансе отладки, для чего нажмите
       клавиши Alt-B D.  Вернитесь к строке 97 и снова установите  точку
       останова, нажав  клавишу  F2.  Теперь  откройте  окно Breakpoints
       (Точки останова), нажав клавиши ALt-V B. Установите эту точку ос-
       танова,  чтобы  выполнять выражение bufp++ каждый раз,  когда оно
       встречается. Для этого сделайте следующее:
            1. Выберите команду View¦Breakpoint (Обзор¦Точка останова).
            2. Откройте окно Breakpoints (Точки останова), нажав клавиши
               Alt-F10.
            3. Выберите  команду  Set  Option (Установить параметры) для
               открытия диалогового окна Breakpoint  Options  (Параметры
               точки останова.
            4. Установите селективный переключатель Action  (Действие) в
               значение Execute (Выполнение).
            5. Для вывода подсказки Action Expression  (Выражение  дейс-
               твия) нажмите клавишу Tab.
            6. Введите bufp++ в ответ на подсказку.
            7. Нажмите  клавишу  Esc,  чтобы закрыть диалоговое окно,  и
               клавиши Alt-F3 для возврата в окно Module (Модуль).
            Теперь запустите программу,  нажав клавишу F9.  Введите  две
       входных строки:
               one two three
               four five six
            В ответ на третью подсказку нажмите клавишу Enter,  а  когда
       программа завершит работу,  нажмите клавиши Alt-F5, чтобы увидеть
       ее экран (экран пользователя).
            Вы можете заметить, что ситуация существенно улучшилась. Об-
       щее число строк и слов выглядит неверным,  но таблица  правильна.
       Остановитесь на начале подпрограммы printstatistics и посмотрите,
       передается ли ей для вывода корректное значение.

чтобы выполнить программу до этой


Для этого снача-
       ла  перезагрузите программу (чтобы начать проверку заново), нажав
       клавиши Ctrl-F2.  Затем  перейдите к строке 104 и нажмите клавишу
       F4,  чтобы выполнить программу до этой строки. Переместите курсор
       на  аргумент nlines и нажмите Alt-F10 I,  чтобы посмотреть на его

       TDeb 3.0 #2-3               = 153 =
       значение.  Вы видите значение 6, хотя должно быть значение 2.
            Теперь вернитесь назад,  туда,  где эта подпрограмма вызыва-
       лась из основной программы, и посмотрите на значение nlines (чис-
       ло строк) там.  Переместите курсор на строку 36 и  поместите  его
       под nlines.  Нажмите клавиши Alt-F10 I для вывода его значения. В
       основной программе значение nlines равно 2, а это правильно. Если
       вы перейдете в них к строке 46,  то увидите,  что два аргумента -
       nwords и nlines - переставлены местами. Компилятор здесь не может
       определить,  какой именно порядок вы имели в виду.  Он использует
       то, что указано.
            Если вы исправите эти две ошибки,  программа будет  работать
       правильно.  Если  вы достаточно любопытны,  то можете попробовать
       запустить исправленную версию программы BCDEMO.EXE.
             Сеанс отладки с использованием программы на Паскале
       -----------------------------------------------------------------
            Остальная часть  данной главы посвящена описанию примера се-
       анса отладки программы,  написанной на Турбо Паскале. Если вы ра-
       ботаете с Borland C++, то просмотрите предыдущие разделы, в кото-
       рых описывается сеанс отладки программы на языке Си.

       TDeb 3.0 #2-3               = 154 =
                                Поиск ошибок
       -----------------------------------------------------------------
            Перед началом сеанса отладки давайте запустим демонстрацион-
       ную программу на Паскале,  в которой содержится ошибка, и посмот-
       рим,  что она делает неверно.  Скомпилированная версия этой прог-

раммы уже содержится на дистрибутивном


       раммы уже содержится на дистрибутивном диске.
            Для запуска  программы  наберите ее имя и передайте ей в ко-
       мандной строке три аргумента:
               TPDEMOB first second third
            Вам будет выведена подсказка для ввода строк текста. Введите
       две строки текста следующим образом:
               ABC DEF GHI
               abc def ghi
            Ввод завершает последняя пустая строка.  После этого TPDEMOB
       выводит анализ введенного текста:
        9 letter(s) in 3 words in 2 lines(s)                         (1)
        Average of 0.67 words per line                               (2)
        Word length:   1  2  3  4  5  6  7  8  9  10                 (3)
        Frequency:     0  0  3  0  0  0  0  0  0  0                  (4)
        Letter:        M                                             (5)
        Frequency:     1  1  1  1  1  1  1  1  1  1  1  0  0  0  0   (6)
        Word starts:   1  0  0  1  0  0  1  0  0  0  0  0  0  0  0   (7)
        Letter:        Z
        Frequency:     0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
        Word starts:   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
        Program name: C:\td\tpdemob.exe                              (8)
        Command line parameters: firs# secon% third                  (9)
            1 - 9 букв в 3 словах;  2 - в среднем 0.67 слов на строке; 3
       - длина слова;  4 - частота; 5 - буква; 6 - частота; 7 - начинает
       слово; 8 - имя программы; 9 - параметры командной строки.
            В этой выходной информации содержится пять различных ошибок:
            1. Число слов сообщается неверно (3 вместо 6).
            2. Число слов на строку неверно (0.67 вместо 3).
            3. В заголовках второй и третьей таблиц выводится  только по
               одной букве (вместо A..M, N..Z).
            4. Вы ввели две строки,  каждая из которых содержит буквы от

       TDeb 3.0 #2-3               = 155 =
               A до I, но в таблицах частоты букв показан только счетчик

и на экран выводится случайный


               со значение 1 для этих букв.
            5. Последний  символ  каждого параметра командной строки был
               потерян,  и на экран выводится случайный символ (хотя па-
               раметры введены правильно).
                        Выбор стратегии поиска ошибок
       -----------------------------------------------------------------
            Первая задача состоит в том,  чтобы решить с какой из ошибок
       разбираться в первую очередь. Здесь можно предложить хорошее пра-
       вило:  начинайте с той ошибки, которая появилась первой. В данной
       программе,  после  того,  как  данные инициализируются процедурой
       Init, ввод с клавиатуры считывается функцией GetLine, а затем об-
       рабатывается процедурой ProcessLine,  пока пользователь не введет
       пустую строку.  ProcessLine просматривает каждую строку  ввода  и
       обновляет глобальные счетчики. После этого процедурой ShowResults
       выводятся результаты.  Наконец, полностью независимая подпрограм-
       ма -  процедура  ParmsOnHeap - строит связанный список параметров
       командной строки в динамически распределяемой области  памяти,  а
       затем выводит этот список в конце программы.
            Среднее число   слов   на   строку   вычисляется  процедурой
       ShowResults на основе числа строки и слов. Так как значение счет-
       чика неверно, очевидно стоит взглянуть на процедуру ProcessLine и
       посмотреть,  как изменяется значение переменной  NumWords  (число
       слов).  Даже  если  значение  NumWords верно,  число 0.67 слов на
       строку не имеет смысла. Тогда ошибка возможно содержится в вычис-
       лениях процедуры ShowResults,  на что также стоит обратить внима-
       ние.
            Заголовки для всех таблиц выводятся в результате обращения к
       процедуре ShowResults. Перед отслеживанием второй и третьей ошиб-
       ки следует подождать завершения работы основного цикла.  Так  как
       счетчики слов и букв содержат неверные значения,  вероятно что-то

когда вы закончите исследовать части


       упущено в процедуре ProcessLine (это относиться к первой  и  чет-
       вертой ошибке).
            Наконец, когда вы закончите исследовать части программы, от-
       носящиеся к работе со счетчиками слов и букв,  для поиска и  исп-
       равления    последней   (пятой)   ошибки   займитесь   процедурой
       ParmsOnHeap.
            Теперь, после того, как обдумали проблему и наметили план ее
       решения, пришло время непосредственно начать отладку.
                           Запуск Турбо отладчика
       -----------------------------------------------------------------
            Для того, чтобы начать отладку нашего примера, загрузите от-
       ладчик и укажите те же параметры командной строки:

       TDeb 3.0 #2-3               = 156 =
               TD TPDEMOB first second third
            Турбо отладчик  загрузит  версию демонстрационной программы,
       содержащую ошибку, и выведет начальный экран, меню и т.д. Если вы
       хотите выйти из сеанса отладки и вернуться в DOS, нажмите клавиши
       Alt-X (это можно сделать в  любой  момент).  Если  вы  безнадежно
       "заблудились", можно в любое время перезагрузить демонстрационную
       программу, нажав клавиши Ctrl-F2, и начать сначала (при этом точ-
       ки останова и выражения просмотра очищены не будут).
            Для отладки таких подпрограмм,  как ProcessLine, можно пред-
       ложить два подхода. Вы можете либо выполнять ее построчно (по ша-
       гам),  убедившись,  что она все делает правильно, либо остановить
       программу непосредственно после выполнения  процедуры ProcessLine
       и посмотреть,  верны ли результаты. Так как оба счетчика содержат
       неверные значения,  лучше внимательно проанализировать  процедуру
       ProcessLine и посмотреть, как обрабатываются символы.

       TDeb 3.0 #2-3               = 157 =
                          Перемещение по программе
       -----------------------------------------------------------------

цедуру ProcessLine. Сделать это можно


            Итак, вы  собираетесь запустить программу и исследовать про-
       цедуру ProcessLine. Сделать это можно несколькими способами. Мож-
       но нажать четыре раза клавишу F8 (для пропуска вызовов процедур и
       функций),  затем  нажать  один  раз  F7  (для  трассировки вызова
       ProcessLine).  Можно переместить курсор на строку 231,  нажать F4
       (команда  Go  to Cursor - Выполнение до курсора),  а затем нажать
       один  раз  F7  для  того,  чтобы  начать   выполнение   процедуры
       ProcessLine (трассировка вглубь).
            Можно привести и другие способы,  однако используем  следую-
       щий. Нажмите клавиши Alt-F9.  При этом  вам  выведется  подсказка
       (диалоговое окно)  для  ввода адреса кода,  до которого вы хотите
       выполнить  программу.  Наберите  ProcessLine  и  нажмите  клавишу
       Enter.  Программа будет выполнена до того места, когда управление
       получает процедура ProcessLine. Когда вам выведется подсказка для
       ввода строки,  введите те же данные,  что и раньше (то есть,  ABC
       DEF GHI).
            Здесь есть несколько циклов. Во внешнем цикле просматривает-
       ся  вся  строка.  Внутри  данного цикла имеется цикл для пропуска
       символов,  отличных от букв,  а второй цикл обрабатывает слова  и
       буквы.  Переместите  курсор к циклу while на строке 133 и нажмите
       клавишу F4 (Выполнение до курсора).
            Данный цикл будет  выполняться,  пока он не достигнет  конца
       строки, или не будет найдена буква. Последнее условие проверяется
       с помощью вызова  булевской  функции  IsLetter.  Для  трассировки
       функции IsLetter нажмите клавишу F7.  IsLetter представляет собой
       вложенную функцию,  которая воспринимает значение символа и возв-
       ращает значение True (истинное значение),  если это буква, и зна-
       чение False в противном случае.  При поверхностном анализе оказы-
       вается,   что  она  проверяет  только  прописные  буквы  (верхний

А она должна проверять символы


       регистр).  А она должна проверять символы в диапазоне 'A'...'Z' и
       'a'...'z'  или перед выполнением проверки преобразовывать символы
       в верхний регистр.
            Еще один ключ к поиску ошибки дает  анализ  обеих  введенных
       строк.  Вы ввели буквы верхнего и нижнего регистра от 'A' до 'I',
       но в общем итоге выведена только половина  букв.  Теперь  вы  уже
       знаете, почему.
            Давайте вернемся   назад  к  строке,  в  которой  вызывается
       IsLetter, с помощью еще одного метода перемещения: нажмите клави-
       ши  Alt-F8,  по  которым  программа будет выполнена до последнего
       оператора процедуры или функции.  Так как вторая введенная строка
       содержит только буквы нижнего регистра, каждый символ обрабатыва-
       ется, как пробел, и пропускается. Это приводит к неверному значе-
       нию счетчиков слов и букв и выявляет причину ошибок 1 и 4.

       TDeb 3.0 #2-3               = 158 =
                       Диалоговое окно Evaluate/Modify
       -----------------------------------------------------------------
            Кстати, существует еще один прекрасный способ выявить непра-
       вильное поведение IsLetter.  Нажав клавиши Alt-D E, выведите диа-
       логовое окно Evaluate/Modify (Вычисление/Модификация)  и  введите
       следующее выражение:
               IsLetter('a') = IsLetter('A')
            И тот,  и  другой параметр (a и A) являются буквами,  но ре-
       зультат вычисления False подтверждает,  то  они  интерпретируются
       функцией IsLetter по-разному.  (Окна вычисления и просмотра можно
       использовать для вычисления выражений,  выполнения  присваиваний,
       или,  как в данном случае, вызовов процедур и функций. Более под-
       робно об этом рассказывается в Главе 6.)
                                  Проверка
       -----------------------------------------------------------------
            Итак, две  ошибки выявлены,  остались три.  Ошибку 2 гораздо

вишу F4, чтобы выполнить программу


       проще  найти,  чем  предыдущие.  Нажмите  Alt-F8  для  вызова  из
       ProcessLine, затем переместите курсор к строке 234 и нажмите кла-
       вишу F4, чтобы выполнить программу до этой позиции курсора.
            Программа TPDEMOB выведет вам подсказку  для  ввода  строки.
       Наберите abc def ghi и нажмите Enter.  В ответ на повторный вывод
       подсказки просто нажмите клавишу Enter. Теперь нажмите клавишу F7
       для трассировки процедуры ShowResults.
            Вспомните, что  вы  хотите определить,  почему среднее число
       слов в  строке  имеет  некорректное  значение.  В  первой  строке
       ShowResults вычисляется число строк на слово,  а не число слов на
       строке. Ясно, что этот порядок следует изменить на обратный.
            Поскольку вы уже находитесь в данном месте, можно убедиться,
       что  NumLines (число строк) и NumWords (число слов) имеют те зна-
       чения,  которые вы ожидаете. NumLines должно быть равно 2 и, пос-
       кольку вы нашли ошибку в IsLetter,  но не исправили ее,  NumWords
       должно быть равно 3. Переместите курсор к NumLines и нажмите Alt-
       F10 I для проверки значения переменной. Окно Inspector (Проверка)
       показывает,  что значение NumLines действительно равно 2.  Теперь
       вы можете проанализировать NumWords.  Нажмите клавишу Esc,  чтобы
       закрыть  окно  Inspector,  затем  переместите  курсор  дальше  на
       NumWords и снова нажмите Alt-F10 I (можно использовать также сок-
       ращение - клавиши Ctrl-I). NumWords содержит ожидаемое некоррект-
       ное значение 3, поэтому можно следовать дальше.
            Однако стоит ли торопиться? В этих вычислениях есть еще одна
       ошибка,  отсутствующая в нашем списке.  Перед выполнением деления
       значение второй переменной не проверяется на 0. Если вы запустите
       программу сначала и совсем не введете данные (нажав от  ответ  на

       TDeb 3.0 #2-3               = 159 =
       подсказку Enter), то программа аварийно завершит работу (даже ес-

ли вы поменяете местами делимое


       ли вы поменяете местами делимое и делитель).
            Чтобы убедиться в этом,  нажмите  Esc,  чтобы  закрыть  окно
       Inspector, затем нажмите клавиши Alt-R P, чтобы завершить текущий
       сеанс отладки и F9, чтобы запустить программу сначала. В ответ на
       подсказку программу TPDEMOB нажмите клавишу Enter.  Программа за-
       вершит работу и на экран выведется окно ошибки.  Оператор следует
       изменить следующим образом:
               if NumLines <> 0 then
                  AvgWords := NumWords / NumLines
               else
                  AvgWords := 0;
            С ошибкой  2  покончено.  Поскольку  вы  работаете  с  окном
       Inspector  (Проверка),  попробуйте использовать его для просмотра
       структуры данных.  Переместите курсор выше к описанию LetterTable
       на  строке  50.  Поместите  курсор на слово LetterTable и нажмите
       клавиши Alt-F10 I. Вы увидите, что это массив записей длиной в 26
       элементов.  Для  просмотра  каждого  элемента массива используйте
       клавиши перемещения курсора, а для углубления в элемент массива -
       клавишу Enter.  Это очень мощный способ проверки структур данных,
       он будет особенно удобен для последующего исследования связанного
       списка в процедуре HeapOnParms.
                              Выражения просмотра
       -----------------------------------------------------------------
            Теперь давайте исследуем ошибку 3 в процедуре ShowResults (в
       выводе  заголовка таблиц).  Поскольку вы уже завершили программу,
       исследуя ошибку деления на 0,  подготовьте ее для другого сеанса,
       нажав клавиши Alt-P (сброс программы). Затем нажмите клавиши Alt-
       F9, наберите showresults и нажмите Enter. После этого введите уже
       знакомые вам данные ABC DEF GHI и нажмите клавишу Enter. Наконец,
       наберите abc def ghi и дважды нажмите Enter. Теперь нужно остано-
       вить Турбо отладчик на ShowResults.

В ShowResults  для вывода таблиц


            В ShowResults  для вывода таблиц букв используется вложенная
       процедура ShowLetterInfo Переметите курсор на строку 103, нажмите
       клавишу F4, затем F7 для перехода в ShowLetterInfo.
            Здесь имеется три цикла for.  В первом цикле выводится заго-
       ловок таблицы,  а во втором и третьем - значения частот.  Исполь-
       зуйте клавишу F7 для перехода в первый цикл на строке 63. Позици-
       онируйте курсор на переменных FromLet и ToLet и используйте  кла-
       виши  Alt-F10  I  для проверки их значений.  Они выглядят верными
       (первое равно 'A',  а второе - 'M').  Нажмите клавиши Alt-F5  для
       вывода  экрана пользователя.  Для возврата к окно Module (Модуль)
       используйте любую клавишу.
            При выполнении подобного цикла очень удобно использовать ок-

       TDeb 3.0 #2-3               = 160 =
       но  Watch  (Просмотр).  Позиционируйте  курсор  на  ch  и нажмите
       клавиши Ctrl-W.  Теперь для выполнения цикла по шагам используйте
       клавишу  F7.  Как и ожидалось,  мы переходим к оператору Write на
       строке 64.  Однако,  если вы посмотрите на окно Watch (Просмотр),
       то  увидите,  что  значение  ch  уже равно 'M' (уже выполнен весь
       цикл!).  После ключевого слова do имеется лишняя точка с запятой,
       поэтому данный цикл 13 раз выполняется вхолостую.  Когда управле-
       ние переходит к оператору Write на строке 64,  то выводится теку-
       щее значение ch ('M'). Устранение лишней точки с запятой позволя-
       ет избавится от ошибки 3.
                              Следующая ошибка
       -----------------------------------------------------------------
            Теперь настало  время отследить ошибку при выводе параметров
       командной строки.  Вспомним,  что последний символ в каждом пара-
       метре командной строке содержал неверное значение ("мусор"). Воз-
       можно,  неверен байт длины строки,  или строковые данные портятся

Для выявления этого используйте окно


       при последующих присваиваниях.
            Для выявления этого используйте окно Watch (Просмотр).  Наж-
       мите клавиши Alt-F9,  наберите parmonheap,  затем нажмите  Enter.
       Оператор  for  обработает в цикле все параметры командной строки,
       формируя связанный список и копируя каждую строку при ее  поступ-
       лении в динамически распределяемую область памяти. Указатель Head
       указывает на начало списка,  Tale - на последний узел в списке, а
       Temp используется, как временная память для выделения и инициали-
       зации нового узла.  Так как строковые данные  запорчены,  нажмите
       клавиши Ctrl-F7 и добавьте в окно Watch следующее выражение:
               Tail^.Parm^
            Это позволяет  отслеживать  строковые  данные,  хранящиеся в
       последнем узле списка.  Конечно,  до инициализации на строке  207
       это значение будет содержать "мусор".
            Вместо того, чтобы выполнять программу по шагам, просто сле-
       дите за окном Watch в конце каждой итерации.  Переместите  курсор
       на  строку  208 и нажмите клавишу F2,  чтобы установить там точку
       останова.  Теперь,  чтобы выполнить программу до точки  останова,
       нажмите клавишу F9. Если вы используете DOS версии 3.х, то в окне
       просмотра вы увидите полный маршрут доступа  к  TPDEMOB.EXE  (при
       работе  под управлением DOS 2.x вы увидите пустую строку,  в этом
       случае просто нажмите клавишу F9 и работайте дальше). Строка дан-
       ных выглядит, как и требуется.
            Нажмите клавишу  F9,  чтобы  выполнить цикл еще раз.  Данные
       опять выглядят правильно. Теперь вы знаете, что строка копируется
       в динамически распределяемую область памяти правильно.  Можно ис-
       пользовать окно Inspector (Проверка) и посмотреть,  не повреждены
       ли  еще  данные.  Переместите  курсор  к  Head  и нажмите клавиши
       Atl-F10 I.

       TDeb 3.0 #2-3               = 161 =
            Нажав клавишу Enter, посмотрите на значение, на которое ссы-

Вы смотрите на первый элемент


       лается Parm.  Вы смотрите на первый элемент списка, и его строко-
       вые данные уже повреждены.  Если вы нажмете клавишу Esc,  стрелку
       вниз,  а затем снова клавишу Enter, то вы откроете окно Inspector
       (Проверка) для второго узла (элемента)  списка.  Нажмите  клавишу
       Enter, чтобы проверить строковые данные. Они не запорчены, факти-
       чески,  на тот же узел ссылается указатель Tail. Очевидно, что-то
       не так с концом строковых данных.
            Следите за окном Watch,  когда вы используете клавишу F7 для
       выполнения  цикла.  На  строке  199  содержится  вызов  процедуры
       GetMem, перед этим вызовом Tail^.Parm^ равно первому символу. Не-
       посредственно после вызова GetMem последний символ  в Tail^.Parm^
       уничтожается.
            Что происходит?  Для  каждого  параметра  командной строки в
       цикле for сначала выделяется запись,  затем строковые данные, за-
       тем следующая запись и т.д. При вызове GetMem на строке 198 долж-
       но выделяться достаточно памяти для строки, плюс байта длины, но,
       как можно заметить, к Length(s) не прибавляется 1. Хотя на строке
       199 строка успешно копируется,  для нее на самом деле выделено на
       1 байт меньше,  чем она использует.  Таким образом, первый символ
       строки перекрывается первым байтом следующей  записи,  выделенной
       при обращении к процедуре New(Temp).  Последний параметр остается
       незапорченным, так как на ним не следует другая ParmRec.
            Это все известные нам ошибки в программе.  Возможно  при  ее
       выполнении вы найдете какие-то еще. Вы можете исправить эти ошиб-
       ки, а затем перекомпилировать программу (для удобства они отмеча-
       ются  двумя звездочками (**)),  или запустить TPDEMO.EXE - версию
       программу, о которой рассказывалось в Главе 3 и в  которой ошибок
       нет.

       TDeb 3.0 #2-3               = 162 =
       Глава 15. Виртуальная отладка с использованием процессора 80386

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


       -----------------------------------------------------------------
            Турбо отладчик позволяет вам полностью использовать произво-
       дительность систем,  основанных на процессоре 80386.  Виртуальная
       отладка  позволяет отлаживаемым программам полностью использовать
       адресное пространство, превышающее 640К (как при отсутствии в па-
       мяти отладчика), поскольку Турбо отладчик загружается в расширен-
       ную память выше 1Мб..
            Отладка выполняется так же,  как при  обычном  использовании
       Турбо отладчика,  только когда загружается драйвер  TDH386,  ваша
       программа  загружается и выполняется с того же адреса,  как и при
       обычном выполнении (без отладчика). Это может оказаться очень по-
       лезным  как  при отладке больших программ,  так и при обнаружении
       ошибок,  которые исчезают,  если программа загружается в  старшие
       адреса памяти.
            Виртуальная отладка также позволяет вам наблюдать за чтением
       и записью в произвольные ячейки памяти или ввода-вывода, не утра-
       чивая  при этом (или почти не утрачивая) скорости выполнения. Это
       без  дополнительной  оплаты  позволяет  использовать  все  мощные
       средства аппаратной отладки.
            Если у вас имеется процессор 80286,  то с помощью отладчика,
       работающего в защищенном режиме (TD286) вы можете получить в свое
       распоряжение больше памяти,  чем при обычной работе с отладчиком.
       Более подробно об этом рассказывается в Главе 16.
          Аппаратные средства, необходимые для виртуальной отладки
       -----------------------------------------------------------------
            Чтобы можно было использовать виртуальный отладчик,  в вашем
       компьютере должен применяться процессор 80386. Вы должны распола-
       гать также расширенной (extended) памятью объемом не  менее 640К.
       Если  вы используете расширенную память для псевдодисков, буферов
       и т.д., то может потребоваться создание специальных версий файлов

Установка драйвера устройства для виртуального


       CONFIG.SYS или AUTOEXEC.BAT, которые нужно будет использовать при
       виртуальной отладке.
          Установка драйвера устройства для виртуального отладчика
       -----------------------------------------------------------------
            Перед запуском  виртуального отладчика нужно убедиться,  что
       вашем файле CONFIG.SYS установлен драйвер  устройства. Установить
       его можно, включив в данный файл следующую строку:
               DEVICE = TDH386.SYS
            Если драйвер TDH386.SYS содержится у вас не в корневом ката-
       логе, а в другом месте, то нужно указать маршрут доступа.
            Обычно виртуальный отладчик позволяет  вам  использовать  до

       TDeb 3.0 #2-3               = 163 =
       256 байт строк,  задающих параметры операционной среды DOS.  Если
       этого недостаточно,  или вам не нужен такой объем и вы хотите сэ-
       кономить возможно больше памяти,  используйте в файле  CONFIG.SYS
       параметр -e, который задает число байт операционной среды. Напри-
       мер:
               DEVICE = TDH386.SYS -e2000
       резервирует 2000 байт для переменных операционной среды DOS.
                        Запуск виртуального отладчика
       -----------------------------------------------------------------
            Запускается виртуальный отладчик точно  также,  как  обычный
       сеанс работы с Турбо отладчиком командой:
               TD386 [параметры] [программа [параметры_программы]]
            Другими словами,  вместо  TD  указывается просто TD386.  При
       этом будет выполняться поиск выполняемой программы Турбо отладчи-
       ка и загрузка ее в расширенную память.
            Если у вас есть другие программы или драйверы устройств, ис-
       пользующие расширенную память (псевдодиски,  буферы  и  др.),  вы
       должны указать TD386,  сколько памяти занимают эти программы. Это
       можно сделать с помощью параметра командной строки -e, за которым
       указывается объем (в килобайтах) расширенной памяти, используемой

вировать для других программ первые


       другими программами, например:
               TD386 -e512 myprog
            Эта командная строка сообщает TD386,  что вы хотите зарезер-
       вировать для других программ первые 512К расширенной памяти.
            Обычно, если в вашей системе  поддерживается  стандарт  XMS,
       вовсе не  обязательно сообщать TD386,  сколько памяти нужно оста-
       вить для программ в расширенной памяти - программы  уже  передали
       эту информацию  TD386.  Параметр  -e  нужно использовать только с
       программами (такими,  как VDISK),  которые не взаимодействуют  со
       стандартом XMS.
            Поскольку вы,  вероятно,  всегда  резервируете один и тот же
       объем расширенной памяти, TD386 дает вам способ постоянного зада-
       ния  объема резервируемой памяти.  Чтобы сообщить,  что вы хотите
       постоянно установить значение параметра -e  в  выполняемом  файле
       TD386, используйте параметр -w.
            Вам будет выведена подсказка, в ответ на которую нужно ввес-
       ти имя выполняемой программы.  Если вы работаете в DOS версии 3.0
       или старше, в подсказке будет указываться маршрут доступа к ката-
       логу и имя файла,  из которого запущен TD386. Вы можете использо-
       вать это имя, нажав клавишу Enter, или ввести имя нового выполня-
       емого  файла.  Файл  с  этим   именем   должен   существовать   и

       TDeb 3.0 #2-3               = 164 =
       представлять собой копию программы TD386.
            Если вы работаете под управлением DOS версии 2.х,  вам  при-
       дется  указать  полное имя выполняемой программы TD386 (с маршру-
       том).
            Перечислим параметры командной строки TD386.EXE:
       -----------------------------------------------------------------
       -?, -h  Выводит справочную информацию по TD386.
       -b      Позволяет вам прерывать  выполнение  программы с  помощью
               клавиш Ctrl-Break, даже когда запрещены прерывания.
       -e####  Задает, сколько  килобайт расширенной  памяти используют-

данный параметр указывать не требуется,


               ся  другими  программами или отлаживаемой вами программой
               ( данный параметр указывать не требуется, если ваша систе-
               ма поддерживает стандарт XMS).
       -w      Модифицирует TD386.EXE  новым  используемым  по умолчанию
               значением -e или -f.
       -f####  Разрешает эмуляцию EMS с помощью  страничного  обмена  (в
               расширенной памяти) и устанавливает сегмент границы стра-
               ницы в значение #### (шестнадцатиричное).  Последние  три
               цифры  должны  быть равны 000 (например,  E000 или C000).
               Заметим, что данный параметр применяется только к вызовам
               EMS Турбо отладчика.  Если вы не можете загрузить таблицу
               идентификаторов,  попробуйте  использовать  параметр  -f,
               чтобы вынудить TD386 заимствовать из расширенной памяти.
                      Нет EMS:                            -fD000
                      EMS по адресу D000:                 -fE000
                      EMS по адресу E000:                 -fD000
       -f-     Запрещает эмуляцию EMS (отменяет действие предыдущего па-
               раметра командной строки).
       -w      Модифицирует TD386.EXE новым  используемым  по  умолчанию
               значением параметра -e или -f. Вы можете ввести имя ново-
               го выполняемого файла, который  еще  не  существует.  При
               этом TD386 создаст новый выполняемый файл.
       -----------------------------------------------------------------
            Заметим, что  параметры TD386 должны указываться в командной
       строке перед другими параметрами Турбо отладчика или именем прог-
       раммы, например:
               TD386 -e1024 -fD000 -w
       резервирует 1024К  расширенной памяти,  разрешает эмуляцию EMS со
       страничной рамкой D000, и модифицирует TD386.EXE данными значени-
       ями.

       TDeb 3.0 #2-3               = 165 =
            Для вывода  списка  всех командных строк,  которые можно ис-

пользовать для TD386, наберите просто


       пользовать для TD386, наберите просто TD386 ? или TD386 -h и наж-
       мите клавишу Enter.
                  Примечание: Если  вы работаете на компьютере с процес-
             сором 386 и хотите  прочитать  параметры  командной  строки
             TD386.EXE, нужно перезагрузить TDH386.SYS.

       TDeb 3.0 #2-3               = 166 =
                    Отличия обычной и виртуальной отладки
       -----------------------------------------------------------------
            В основном  при  обычной отладке и при виртуальной отладке с
       использованием возможностей процессора 80386 все работает  одина-
       ково. Различия состоят в следующем:
            1. При использовании команды File¦DOS  Shell (Файл¦Командный
               процессор операционной системы DOS) отлаживаемая програм-
               ма никогда не сбрасывается на  диск.  Это  означает,  что
               иногда  вам  может  не  хватить памяти для запуска других
               программ в ответ на подсказку DOS.
            2. Ваша  программа  может  использовать почти все инструкции
               процессора 80386,  за исключением инструкций  защищенного
               режима: CLTS, LMSW, LTR, LGDT, LIDT, LLDT.
            3. Хотя  при  виртуальной отладке вы можете использовать все
               режимы расширенной адресации процессора 80386  и  32-раз-
               рядные регистры, вы не можете обращаться к памяти свыше 1
               Мб. При попытке сделать это будет генерироваться прерыва-
               ние, и управление будет передано отладчику.
            4. Нельзя использовать виртуальную отладку,  если вы уже за-
               пустили программу или  драйвер  устройства,  использующие
               виртуальный и защищенный режимы процессора 80386. Это та-
               кие программы, как:
                       - операционная среда DesqView;
                       - операционная среда Windows-386;
                       - драйвер эмуляции EMS CEMM.SYS Compaq;

Если вы  используете  обычно  одну


                       - драйвер эмуляции EMS QEMM.SYS QuarterDeck;
                       - 386^MAX.
               Если вы  используете  обычно  одну из этих программ,  вам
               придется остановить их или разгрузить перед использовани-
               ем TD386.
            5. Если вы используете виртуальную отладку,  TD386 может пе-
               рехватывать генерируемые вашей программой прерывания. Ес-
               ли  происходит  прерывание,  программа  останавливается и
               TD386 сообщает о том, что произошло прерывание. Выводимое
               сообщение описывает характер прерывания,  а стрелка в об-
               ласти кода окно CPU (ЦП) или в окне Module (Модуль) отме-
               чает инструкцию, которая вызвала прерывание.
            6. Непредвиденных  прерываний возникать не должно.  В случае
               их возникновения обратитесь к следующему разделу  и  про-
               верьте,  упоминаются ли они там.  Если нет, проконсульти-
               руйтесь с представителями фирмы Borland.
                  Замечания относительно возможных проблем
       -----------------------------------------------------------------

       TDeb 3.0 #2-3               = 167 =
            Если вы используете TDH386 и получаете сообщение "Not enouhg
       memory to load symbol table" ("Не  хватает  памяти  для  загрузки
       таблицы идентификаторов"),  то  вам  нужно  разрешить  для TDH386
       эмуляцию EMS.
            Например, чтобы установить для TDH386 EMS в  сегмент 0D000h,
       используйте для запуска TDH386 следующую команду:
            TDH386 -FD000
            Если вы используете HP Vestra и получаете при запуске TDH386
       непредвиденное прерывание 06,  нужно задать параметр в  установке
       CMOS. По  умолчанию  серия Vestra использует в части HP-HILL инс-
       трукцию защищенного режима.  Чтобы обойти это, свяжитесь с фирмой
       Hewlett Packard и узнайте, как обойти данную инструкцию.

Если исключительная ситуация 06 возникает


            Если исключительная ситуация 06 возникает после того, как вы
       некоторое время поработаете в TDH386,  то ваш исходный код будет,
       возможно, модифицирован.  Обычно исключительная ситуация 06 гене-
       рируется процессором 80386,  когда встречается  недопустимый  код
       операции. Типичной  причиной  этой  ошибки является использование
       неинициализированных указателей.
            Исключительные ситуации 06,  13 и 0D могут  возникать,  если
       вы используете старый драйвер "мыши",  сетевой драйвер или другой
       аппаратный драйвер.  Если в TD386 вы получаете данные ошибки, по-
       пытайтесь удалить по очереди аппаратные драйверы, начиная с драй-
       вера "мыши", сетевого драйвера, и так далее, пока не  идентифици-
       руете драйвер, приводящий к такой ситуации. Если для этого  драй-
       вера имеются модификации, то посмотрите,  устранит ли проблему их
       установка. Последняя  возможная  мера  состоит  в полном удалении
       драйвера.
            Если вы  получаете  во  время  загрузки   TDH386   сообщения
       "Processor already in protected mode" ("Процессор уже в  защищен-
       ном режиме"), это означает, что выполняется программа, использую-
       щая виртуальный режим процессора 80386 (например,QEMM). Использо-
       вать одновременно эти программы и TDH386 нельзя.  Если вам  необ-
       ходимо  использовать данные подсистемы управления памятью,  попы-
       тайтесь вместо TDH386 использовать TD286.
                         Сообщения об ошибках TD386
       -----------------------------------------------------------------
            При невозможности начать работу  TD386  генерирует  одно  из
       следующих  сообщений  и  возвращает вас на уровень подсказки DOS.
       Перед тем, как запустить TD386, нужно исправить ситуацию.
            TD386 error: 80386 device driver missing or wrong version
            (нет драйвера 80386 или неправильная версия)

с помощью командной строки DOS


            Перед вызовом TD386 с помощью командной строки DOS нужно ус-

       TDeb 3.0 #2-3               = 168 =
       тановить в файле CONFIG.SYS драйвер TDH386.SYS.
            TD386 error: Can't enable the A20 adress line
            (не могу разрешить адресацию строки A20)
            TDH386 не  может  обратиться  к памяти свыше 1Мб.  Это может
       происходить в том случае, если вы работаете в системе, которая не
       полностью совместима с IBM.
            TD386 error: Can't find TD.EXE
            (невозможно найти TD.EXE)
            TD386 не может найти файл TD.EXE.
            TD386 error: Couldn't execute TD.EXE
            (невозможно выполнить TD.EXE)
            TD386 не может выполнить TD.EXE.
            TD386 error:  Enviroment  too  long;  use -e#### switch with
            TDH386.SYS
            (слишком длинная   строка  операционной  среды,  используйте
            TDH386.SYS с параметром -e####)
            Нужно изменить  параметр  -e,  как было указано в предыдущих
       разделах.
            TD386 error: Not enough Extended Memory avaliable
            (объем доступной расширенной памяти недостаточен)
            TD386 превысил границы памяти.  Нужно использовать машину  с
       памятью  большего объема или освободить память (уменьшив,  напри-
       мер, объем псевдодиска).
            TD386 error: Wrong CPU type (not an 80386)
            (неправильный тип центрального процессора: не 80386)
            Вы работаете на системе,  где используется процессор, отлич-
       ный от 80386.
            Следующие ошибки  могут  произойти,  если  вы модифицировали
       TD386 с помощью параметра -w:
            TD386 error: Cannot open program file
            (невозможно открыть файл программы)
            TD386 error: Cannot read program file
            (невозможно прочитать файл программы)
            TD386 error: Cannot write program file
            (невозможно записать файл программы)
            TD386 error: Program file corrupted or wrong version

программный файл поврежден или неверна



       TDeb 3.0 #2-3               = 169 =
            ( программный файл поврежден или неверна версия)
                       Сообщения об ошибках TDH386.SYS
       -----------------------------------------------------------------
            Может возникнуть  только  две ошибки,  связанных с драйвером
       TDH386.SYS:
            Wrong CPU type: TDH driver not installed
            (неверный тип ЦП: драйвер TDH не установлен)
            Invalid command line: TDH driver not installed
            (недопустимая командная строка: драйвер TDH не установлен)

       TDeb 3.0 #2-3               = 170 =
       Глава 16. Отладка в защищенном режиме с использованием TD386
       -----------------------------------------------------------------
            Отладчик для защищенного режиме TD386 использует преимущест-
       ва процессора 80286 и позволяет освободить больше памяти для  от-
       лаживаемых вами программ. TD386 помещает программу Турбо отладчи-
       ка в расширенную память выше 1Мбайта и оставляет  в  нижних  640К
       памяти сравнительно небольшой загрузчик. Это дает вам больше мес-
       та для программ,  которые вы отлаживаете, и их таблиц идентифика-
       торов.
            Используйте в этом случае Турбо отладчик, как обычно. Единс-
       твенным отличием будет то,  что вашей программа  получит  больший
       объем памяти.
                 Замечание: Если вы работаете на компьютере с  процессо-
            ром  80386 и еще не используете программу защищенного режима
            типа 386^MAX,  то еще большие возможности и экономию  памяти
            вам даст отладчик TD386.  Более подробно об этом рассказыва-
            ется в Главе 15.
          Аппаратура, необходимая для использования отладчика TD286
       -----------------------------------------------------------------
            Чтобы использовать  отладчик  защищенного  режима TD286,  вы
       должны иметь компьютер с процессором 80286 или старше и  не менее

запустить программу конфигурации TD286INS. Это


       640К доступной расширенной памяти.
                 Установка отладчика для защищенного режима
       -----------------------------------------------------------------
            Перед тем,  как в первый раз использовать TD286,  вы  должны
       запустить программу конфигурации TD286INS. Это позволит TD286 оп-
       ределить некоторые характеристики аппаратуры, на которой вы рабо-
       таете. Для   настройки  конфигурации  TD286  запустите  программу
       TD286INS в ответ на подсказку DOS.
            Программа TD286INS после того, как она определит характерис-
       тики аппаратных средств, попросит вас нажать несколько раз клави-
       шу пробела. Если в какой-либо момент ваша система "зависнет" и не
       будет дальше  работать,  то  перезагрузитесь и повторно запустите
       программу конфигурации.  Программа конфигурации знает о том,  что
       возникла проблема, и продолжает выполнять следующую фазу тестиро-
       вания.
            Когда программа TD286INS завершит  выполнение,  можно  будет
       использовать TD286.

       TDeb 3.0 #2-3               = 171 =
                   Запуск отладчика для защищенного режима
       -----------------------------------------------------------------
            Запустить отладчик для защищенного режима  можно  с  помощью
       командной строки со следующим синтаксисом:
               TD286 [параметры] [программа [параметры программы]]
            Параметры TD286  совпадают с параметрами обычного отладчика.
       за исключением параметров -r, -rn, -rp, -rs, -sm, -w, -y, -ye.
       (TD286 не работает с оверлеями, удаленной отладкой и Windows).
         Отличия Турбо отладчика и отладчика для защищенного режима
       -----------------------------------------------------------------
            Есть несколько функций,  которые вы можете выполнять в Турбо
       отладчике, но не можете использовать в отладчике TD286:
            - когда вы используете команду File¦Dos Shell  (Файл¦Команд-

ный процессора DOS) для выполнения


               ный процессора DOS) для выполнения команды DOS, программа,
              которую вы отлаживаете, не сбрасывается на диск. Это озна-
              чает, что вам может не хватить памяти для выполнения прог-
              рамм в ответ на подсказку DOS.
            - вы не можете использовать отладчик TD286 для отладки прог-
              рамм, работающих  в  защищенном  режиме,  или использовать
              расширитель DOS, который приводит к конфликту с TD286.
            Отладка программ, использующих дополнительную память
       -----------------------------------------------------------------
            По умолчанию TD286 будет использовать всю  доступную  расши-
       ренную  память.  Если вы отлаживаете программу,  которая сама ис-
       пользует этот вид памяти (extended memory),  то для использования
       TD286 нужно создать файл конфигурации CONFIG.286 в корневом ката-
       логе текущего дисковода. В этом файле должна быть строка:
            MEGS=#
       где # - это объем расширенной памяти,  которую может использовать
       отладчик.
                     Выполнение TD286 на разных машинах
       -----------------------------------------------------------------
            Отладчику TD286  известны аппаратные характеристики десятков
       машин. Когда вы запускаете  TD286INS,  и  она  сообщает  "Machine
       already in file's database" (машина уже описана в файле базы дан-
       ных), то TD286 уже знает о вашем  компьютере,  и  модификация  не
       требуется.
            Если TD286INS выполнит свои проверки (тестирование),  то ап-
       паратные характеристики вашей машины будут записаны  в  TD286,  и

       TDeb 3.0 #2-3               = 172 =
       будет создан файл с расширением .DB.  Этот файл  следует  послать
       фирме Borland  или  на одну из конференций Compuserve,  благодаря
       чему следующие версии TD286 смогут автоматически поддерживать ха-
       рактеристика вашего компьютера.  TD286 может хранить  характерис-
       тики до 10 компьютеров, отличных от того, на котором он начал ра-
       ботать.