                             Оглавление                                  
 = 1 =

 ВВЕДЕНИЕ........................................................5
 ГЛАВА 1  НАЧАЛО РАБОТЫ.........................................11
   Дистрибутивные дискеты.......................................11
   Файл README..................................................11
   Файл HELPME!.DOC.............................................12
   Утилиты Turbo Debugger.......................................12
   Установка системы Turbo Debugger.............................13
   Аппаратная отладка...........................................14
   Что делать дальше?...........................................15
 ГЛАВА 2  ОТЛАДКА И TURBO DEBUGGER..............................17
   Что такое отладка?...........................................17
   Что может вам дать отладчик Turbo Debugger?..................18
   Преимущества отладчика Turbo Debugger........................21
   "Уроки истории"..............................................27
   Инкрементный поиск соответствия имен.........................28
   Создание макросов............................................29
   Использование окон...........................................29
   Предоставление подсказки пользователю........................41
 ГЛАВА 3  НАЧАЛО РАБОТЫ: КОРОТКИЙ ПРИМЕР........................45
   Примеры программ.............................................45
   Работа с отладчиком Turbo Debugger...........................46
   Отладка примера программы на языке Си........................48
   Отладка примера программы на языке Паскаль...................52
 ГЛАВА 4  ЗАПУСК ОТЛАДЧИКА TURBO DEBUGGER.......................56
   Подготовка программ к отладке................................56
   Запуск программы Turbo Debugger..............................57
   Параметры командной строки...................................59
   Файлы конфигурации...........................................64
   Меню Options.................................................65
   Временный выход в DOS в процессе отладки.....................69
   Возврат в DOS................................................69
 ГЛАВА 5  УПРАВЛЕНИЕ ПРОЦЕССОМ ВЫПОЛНЕНИЯ ПРОГРАММЫ.............70
   Проверка текущего состояния программы........................70
   Меню Run.....................................................77
   Окно Execution History (истории выполнения)..................81
   Прерывание выполнения программы..............................84
   Завершение работы программы..................................85
   Возобновление сеанса отладки.................................85
   Загрузка в отладчик новой программы..........................87
   Изменение аргументов программы...............................87
 ГЛАВА 6  ПРОВЕРКА И МОДИФИКАЦИЯ ДАННЫХ.........................88
   Меню Data....................................................88
   Выбор элементов данных в исходном тексте.....................92
   Окно слежения................................................92
   Окна проверки данных.........................................95
   Локальное меню окна проверки................................102
 ГЛАВА 7  ТОЧКИ ОСТАНОВА.......................................106
   Меню Breakpoints............................................107
   Область действия выражений, заданных для точек останова.....108
   Окно точек останова.........................................109
   Окно регистрации............................................113

 = 2 =

   Простые точки останова......................................115
   Условные точки останова и количество проходов...............116
   Глобальные точки останова...................................116
   Регистрация значений переменных.............................118
   Выполнение выражений........................................118
 ГЛАВА 8  ПРОВЕРКА И МОДИФИКАЦИЯ ФАЙЛОВ........................120
   Проверка исходных файлов программы..........................120
   Проверка других дисковых файлов.............................125
 ГЛАВА 9  ВЫРАЖЕНИЯ............................................129
   Выбор языка для вычисления выражений........................129
   Адреса кода, адреса данных и номера строк...................130
   Доступ к идентификаторам вне текущей области действия.......131
   Последовательности байтов...................................134
   Выражения языка Си..........................................135
   Выражения языка Паскаль.....................................140
   Выражения языка ассемблера..................................143
   Управление форматом.........................................144
 ГЛАВА 10 Отладка программ на С++ и объектно-ориентированном
  Паскале......................................................146
   Окно Hierarchy..............................................146
   Окна Inspector типа объект/класс............................148
   Окна Inspector вхождений объекта............................150
 ГЛАВА 11 Отладка на уровне ассемблера.........................154
   Когда не достаточно отладки на уровне исходного текста......154
   Окно процессора.............................................155
   Подокно кода................................................156
   Подокна Register и Flags....................................162
   Подокно данных..............................................164
   Подокно Stack...............................................170
   Ассемблер...................................................171
   Окно дампа..................................................173
   Окно регистров..............................................173
   Генерация кода для программ на языке Turbo C................174
 ГЛАВА 12 Сопроцессор 80х87 и эмулятор.........................176
   Сравнение сопроцессора 80х87 и его эмулятора................176
   Окно числового процессора...................................176
 ГЛАВА 13  Справочник команд отладчика.........................181
   Активные клавиши............................................181
   Команды главного меню.......................................183
   Команды локальных меню......................................186
   Текстовые подокна...........................................194
   Подокна списков.............................................195
   Команды в блока запроса и списков истории выполнения........195
   Команды перемещения окон....................................196
   Шаблоны для поиска..........................................197
 ГЛАВА 14 Как отлаживать программу.............................198
   Что делать, если программа не работает?.....................198
   Стиль отладки...............................................199
   Виды ошибок.................................................200
     Общие ошибки..............................................200

 = 3 =

     Ошибки, характерные для программирования на Си ...........201
     Ошибки, характерные для программирования на Паскале   ....207
     Ошибки, характерные для программирования на ассемблере....214
   Проверка программы на точность..............................220
   Отладка как стадия разработки программы.....................221
   Пример сеанса отладки.......................................221
   Сеанс отладки си-программы..................................222
   Сеанс отладки паскаль-программы.............................227
 ГЛАВА 15 Виртуальная отладка на машине с процессором 80386....236
   Аппаратные средства, необходимые для виртуальной отладки....236
   Установка драйвера устройства для виртуального отладчика....236
   Запуск виртуального отладчика...............................237
   Различия между обычной и виртуальной отладкой...............239
   Сообщения об ошибках программы TD386........................240
   Сообщения об ошибках драйвера TDH386.SYS....................241
 ГЛАВА 16 Отладка в защищенном режиме при помощи TD286.........242
   Аппаратное обеспечение отладчика защищенного режима.........242
   Установка отладчика защищенного режима......................242
   Запуск отладчика защищенного режима.........................242
   Различия между Turbo Debugger и TD286.......................242
   Запуск TD286 на различных машинах...........................243
 ГЛАВА 17 Отладка резидентных программ и драйверов устройств...244
   Что такое резидентная программа (TSR).......................244
   Что такое драйвер устройства................................248
   Конец сеанса отладки........................................252

 = 4 =

 TURBO DEBUGGER
 Версия 2.0
 -----------------------------------------------------------------

 Руководство пользователя



 Borland International,INC. 1800 GREEN HILLS ROAD
 P.O.BOX 660001,SCOTTS VALLEY,CA 95066-0001


 Авторские права (c) 1988,  1990 принадлежат Borland  Corporation.
 Все права   сохраняются.  Все  продукты  фирмы  Borland  являются
 торговыми марками  или  зарегистрированными   торговыми   марками
 Borland International,  Inc.  Прочие  продукты являются торговыми
 марками или зарегистрированными торговыми марками соответствующих
 держателей.






 = 5 =

                                   ВВЕДЕНИЕ                                    


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

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

      Ниже перечислены лишь  некоторые  свойства  отладчика  Turbo
 Debugger.

      - использование  расширенной  памяти  типа  EMS  для отладки
        больших программ;

      - вычисление любых выражений языка Си, Паскаль и ассемблера;

      - настраиваемое размещение информации на экране;

      - доступ к ассемблеру и процессору по мере необходимости;

      - мощные средства использования  точек  останова  и  журнала
        регистрации;

      - запись нажатий клавиш (макросы);

      - использование  удаленной системы для отладки очень больших
        программ;

      - поддержка процессора 80386 и аппаратных отладчиков;

      - полная поддержка объекто-ориентированного программирования
        на Turbo Pascal 5.0;

      - полная поддержка C++ и Turbo C++;

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

 Требования к аппаратному и программному обеспечению

      Отладчик может  работать  на  компьютерах  семейства IBM PC,
 включая серии XT,  AT и PS/2,  а также  полностью  совместимых  с
 ними.  Компьютер  должен  работать  под  управлением операционной
 системы DOS версии 2.0 или более поздней и иметь как  минимум 384

 = 6 =

 КБ оперативной памяти. Компьютер может быть оснащен любым цветным
 или монохромным монитором,  поддерживающим режим отображения в 80
 столбцов. Мы рекомендуем использовать компьютер с жестким диском,
 хотя отладчик хорошо работает и на машине с двумя накопителями на
 гибких дисках,  но для этого следует использовать дискеты высокой
 плотности.  Можно также работать  с  3.5-дюймовыми  дискетами  по
 720К.  Следует отметить, что программа INSTALL в последнем случае
 неприменима,   и   копирование   файлов    требуется    выполнять
 самостоятельно.

      Turbo Debugger   не  требует  использования  арифметического
 сопроцессора 8087.

      Для того  чтобы   использовать   отладчик   Turbo   Debugger
 совместно   с   другими   продуктами  фирмы  Borland,  вы  должны
 использовать систему Turbo Pascal версии 5.0 или  более  поздней,
 систему  Turbo  C  версии  2.0  или Turbo C++,  или систему Turbo
 Assembler версии 1.0 или  более  поздней.  Прежде  чем  загружать
 программу в отладчик Turbo Debugger, необходимо скомпилировать ее
 исходный текст в исполняемый файл типа EXE в  режиме формирования
 полной отладочной информации.

      При запуске  отладчика  необходимо,  чтобы были доступны как
 исполняемый файл, так и файлы с исходным текстом программы. Turbo
 Debugger   ищет  исходные  файлы  сначала  там,  где  их  находил
 компилятор при компиляции программы, затем в директории, заданной
 командой Options/Path for Source,  затем в текущей директории,  а
 затем в директории, где находится файл типа EXE.

 Замечания по терминологии

      Для удобства  и  краткости  изложения  несколько  терминов в
 данном руководстве  используется  в  более  широком  смысле,  чем
 обычно. К ним относятся термины "модуль", "функция" и "аргумент".

      Термин "модуль"  в  данном руководстве обозначает эквивалент
 модуля (module) Си или ассемблера или (unit) Паскаля.

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

      Термин "аргумент"  используется  в  данном  руководстве  как
 синоним термина "параметр". Он означает как аргументы (параметры)

 = 7 =

 командной  строки,  так  и аргументы (параметры),  передаваемые в
 процедуры и функции.

 Состав данного руководства

      Ниже приведено краткое описание содержания глав и приложений
 данного руководства.

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

      В главе 2 "Отладка и Turbo Debugger" описан пользовательский
 интерфейс  отладчика  Turbo   Debugger,   система   меню,   окна,
 объясняется,  как  отвечать  на  запросы отладчика и сообщения об
 ошибках.

      В главе 3  "Короткий  пример"  рассмотрен  образец  отладки,
 который   проведет   вас   по  всему  сеансу  отладки  программы,
 написанной либо на Си, либо на Паскале, и продемонстрирует многие
 полезные возможности отладчика Turbo Debugger.

      В главе  4 "Запуск отладчика Turbo Debugger" рассказано, как
 запустить отладчик из командной строки DOS, для чего используются
 параметры  командной  строки  и  как  записать часто используемые
 параметры в файл конфигурации.

      В главе  5  "Управление  процессом   выполнения   программы"
 демонстрируются  различные  способы запуска и останова программы,
 показывается,  как начать новый  сеанс  отладки  или  возобновить
 последний сеанс.

      В главе 6 "Проверка и модификация данных" описаны уникальные
 возможности отладчика Turbo Debugger по  проверке  и  модификации
 данных внутри отлаживаемой программы.

      В главе  7  "Точки  останова"  объясняется  концепция "точки
 останова",  охватывающая  функции   отладчика,   которые   обычно
 называют   точками  останова,  точками  слежения  и  контрольными
 точками. Описаны как условные так и безусловные точки останова, а
 также  действия,  которые  могут  выполняться при включении точки
 останова.

      В главе 8  "Проверка  и  модификация  файлов"  описано,  как
 проверять  и  модифицировать  исходные  файлы  программ,  а также
 произвольные дисковые файлы,  содержащие  как  текстовые,  так  и
 двоичные данные.

      В главе   9   "Выражения"   описаны  синтаксические  правила
 построения выражений языков  Си,  Паскаль  и  ассемблер,  которые

 = 8 =

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

      В главе  10 "Отладка С++ и объекто-ориентированного Паскаля"
 рассматриваются специальные   средства   отладчика,   позволяющие
 просматривать объекты программ на языке Turbo Pascal 5.5 и классы
 программ на языке Turbo С++.

      В главе 11 "Отладка на уровне ассемблера"  описывается,  как
 просматривать  содержимое  областей  памяти  в  виде  построчного
 шестнадцатиричного  дампа  и  изменять  его,   как   использовать
 встроенный  ассемблер  и  дизассемблер,  как проверять и изменять
 состояние регистров и флагов процессора.

      В главе 12  "Сопроцессор  80х87  и  эмулятор"  описано,  как
 проверять  и  модифицировать  содержимое регистров сопроцессора и
 состояние его эмулятора.

      В главе 13 "Справочник  команд  отладчика"  приведен  полный
 перечень  всех  команд главного меню и команд локальных меню всех
 видов окон.

      В главе  14  "Как  отлаживать  программу"  описана  методика
 эффективной отладки программ.

      В главе  15  "Виртуальная  отладка  на  машине с процессором
 80386" объясняется,  как  использовать  преимущества  расширенной
 памяти    и   производительности   процессора   80386,   позволяя
 отлаживаемой программе использовать полное  адресное пространство
 ниже 640К, как если бы не был загружен отладчик.

      В главе  16  "Отладка  в защищенном режиме при помощи TD286"
 описано, как использовать TD286  для  запуска  Turbo  Debugger  в
 защищенном режиме6   освобождая   память   для   отладки  больших
 программ.

      В главе  17  "Отладка  резидентных  программ   и   драйверов
 устройств" объясняется,  как отлаживать при помощи Turbo Debugger
 резидентные программы    и    программы,    которые    становятся
 резидентными при загрузке,  а также как загружать вручную таблицу
 символических имен.

      В приложении  А  "Параметры   командной   строки"   приведен
 перечень  всех  параметров  командной  строки,  которые  подробно
 описаны в главе 4.

      В приложении B "Технические  замечания"  приведены  сведения
 для  опытных программистов.  В ней описаны подробности реализации
 отладчика,  которые   объясняют,   как   он   взаимодействует   с
 отлаживаемой программой и операционной системой DOS.

 = 9 =


      В приложении    C   "Зарезервированные   слова   встроенного
 ассемблера" приведены  все  мнемонические  обозначения  команд  и
 специальные  слова,  которые  используются  при  вводе команд для
 процессоров 8086/80286.

      В приложении  D   "Настройка   отладчика   Turbo   Debugger"
 объясняется,  как  использовать  программу  TDINST  для настройки
 экранных цветов и изменения параметров отладчика, используемых по
 умолчанию.


      В приложении E "Удаленная отладка" описано,  как  использать
 утилиту TDREMOTE   для   отладки   при   помощи  Turbo  Debugger,
 находящегося на одной системе,  программы,  находящейся на другой
 системе.

      В приложении  F  "Блоки  диалога  и  сообщения  об  ошибках"
 описаны  все  запросы  и  сообщения  об  ошибках,  которые  можно
 получить  во  время отладки,  приведены рекомендации,  как на них
 отвечать.

      В приложении П "Отладка программ на  разных  языках"  даются
 некоторые  рекомендации  по  отладке программ,  написанных на Си,
 Паскале и ассемблере.

      В "Глоссарии"  приведен  в   алфавитном   порядке   перечень
 терминов,  наиболее  часто  используемых в данном руководстве,  и
 дано их краткое определение.

 Как обратиться за помощью к фирме Borland
 -----------------------------------------------------------------

      Лучший способ  обратиться  к  Borland  состоит в том,  чтобы
 зарегистрировать свою заявку через  сеть  CompuServe:  для  этого
 наберите в  главном меню CompuServe GO BOR и выберите из главного
 меню Borland пункт "Borland Programming Forum  B  (Turbo  Prolog,
 Turbo Assembler,  Turbo Debugger, & Turbo C). Передайте туда ваши
 вопросы и комментарии для последующего их рассмотрения персоналом
 сопровождения фирмы.

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

    Borland International
    Technical Support Department - Turbo Debugger
    1800 GREEN HILLS ROAD
    P.O.BOX 660001
    SCOTTS VALLEY,CA 95066-0001, USA

 408-438-5300 - по этому телефону можно  обратиться  в  наш  отдел

 = 10 =

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

      1. Имя  продукта  и  серийный   номер   вашей   оригинальной
 дистрибутивной дискеты. Этот номер обязателен, иначе мы не сможем
 обслужить вашу заявку.

      2. Номер версии вашего продукта. Номер версии Turbo Debugger
 выводится на дисплей после исходной загрузки программы,  до того,
 как вы нажмете какие-либо клавиши.  Если вы находитесь в  системе
 Turbo Debugger, выберите пункт About из меню System.

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

      4. Название и  номер  версии  операционной  системы.  (Номер
 версии можно определить, введя по приглашению DOS команду VER).

      5. Содержимое вашего файла AUTOEXEC.BAT.

      6. Содержимое вашего файла CONFIG.SYS.

 Рекомендуемая литература
 -----------------------------------------------------------------

      Многие издательства поддерживают  продукты  Borland  широким
 выбором замечательных книг по этим продуктам,  от предназначенных
 для начинающих  пользователей,  и  кончая  предназначенными   для
 опытных специалистов.    Ниже   приводится   несколько   названий
 книг, содержащих дополнительную информацию по Turbo Debugger:

      Ackerman,Charles. Turbo Debugger and Tools:  A Self-Teaching
 Guide, John Wiley and Sons (New York:1990).

      Swan,Tom. Mastering  Turbo Assembler,  Howard W.Sams and Co.
 (Carmel,IN: 1989).

      Swan,Tom. Mastering Turbo Debugger and Tools,  Howard W.Sams
 and Co. (Carmel,IN: 1990).

      Syck,Gary. The  Waite Group's Turbo Assembler Bible,  Howard
 W.Sams and Co. (Carmel,IN: 1990).



 = 11 =

                            ГЛАВА 1  НАЧАЛО РАБОТЫ                             
 -----------------------------------------------------------------

      Пакет Turbo Debugger

      Пакет Turbo Debugger включает три дистрибутивных  дискеты  и
 Руководство   пользователя   по  системе  Turbo  Debugger  (Turbo
 Debugger  User's  Guide).  Дистрибутивные  дискеты  содержат  все
 программы,  файлы  и  утилиты,  необходимые для отладки программ,
 написанных на языках Turbo C,  Turbo Assembler и Turbo Pascal,  а
 также  любых  программ,  созданных  с  помощью компиляторов фирмы
 Microsoft.   Кроме   этого,   пакет   Turbo   Debugger   содержит
 документацию по вопросам, не освещенным в данном руководстве.

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

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

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

      При установке системы  Turbo  Debugger  на  свою  машину  вы
 будете  копировать  дистрибутивные дискеты на рабочие дискеты или
 на  жесткий  диск.  Вы  можете  запустить  специальную  программу
 установки  INSTALL.EXE,  которая  находится  на  одной  из  ваших
 дистрибутивных дискет. Дистрибутивные дискеты отформатированы под
 дисководы  для двухсторонних дискет с двойной плотностью записи и
 могут быть прочитаны на персональном компьютере семейства  IBM PC
 и совместимых с ними.

      Список файлов,  поставленных вам на дистрибутивных дискетах,
 см. в файле README на дискете Installation.

                                                                               
Файл README
 -----------------------------------------------------------------


 = 12 =

      Очень важно,  чтобы прежде  чем  начать  что-либо  делать  в
 системе Turbo Debugger,  вы нашли время ознакомиться с содержимым
 файла README,  который находится  на  дискете  Installation  Disk
 (Установочный диск).  Этот файл содержит самую свежую информацию,
 которой может не быть в данном руководстве.  Кроме  того,  в  нем
 перечислены  все файлы,  имеющиеся на дистрибутивных дискетах,  с
 кратким описанием каждого из них.

      Для того  чтобы  прочитать  содержимое  файла  README,  надо
 вставить  дискету  Installation  Disk  в дисковод A,  сделать его
 текущим,  введя с клавиатуры команду A:  и нажав  клавишу  Enter,
 затем  ввести  с клавиатуры README и нажать Enter еще раз.  После
 того,  как  загрузится  файл   README,   его   содержимое   можно
 прокручивать  на  экране  с  помощью  клавиш  "Стрелка  вверх"  и
 "Стрелка вниз". Для завершения просмотра надо нажать клавишу Esc.
                               Файл HELPME!.DOC                                
 -----------------------------------------------------------------

      На дискете   Installation  Disk  имеется  файл  HELPME!.DOC,
 содержащий  ответы  на  вопросы,  которые   часто   возникают   у
 пользователей.  Обращайтесь к этому файлу,  когда у вас возникнут
 какие-либо затруднения.  Кроме всего  прочего,  файл  HELPME!.DOC
 содержит информацию по следующим вопросам:

      - вывод  на  экран для программ,  работающих в графическом и
        текстовом режимах;

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

      -  прерывание выполнения программы;

      - синтаксические и грамматические  отличия  отладчика  Turbo
        Debugger от языков семейства Turbo;

      - отладка  многоязычных  программ  с помощью отладчика Turbo
        Debugger;

      - Tandy 1000A,  IBM PC  Convertible  или  NEC  MultiSpeed  и
        прочие компьютеры, использующие NMI (немаскируемые
        прерывания).
                            Утилиты Turbo Debugger                             
 -----------------------------------------------------------------

      Пакет Turbo  Debugger  поставляется с несколькими утилитами.
 Подробная информация об этих утилитах находится на дистрибутивных
 дискетах. Доступ к этой информации описан в файле README.

      Ниже приводится краткое описание утилит Turbo Debugger:


 = 13 =

      - Утилита    для преобразования файлов из формата CodeView в
 формат Turbo  Debugger   TDCONVRT.EXE,   позволяющая   отлаживать
 программы на  Си  и  ассемблере,  создаваемые  компиляторами фирмы
 Microsoft.

      - Утилита   для   связи с  файлами  на   удаленной   системе
 TDRF.EXE, работающая  вместе с отладчиком и позволяющая  передавать
 на удаленную систему основные команды управления файлами.

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

      - TDPACK.EXE позволяет упаковывать отладочную информацию.

      - TDMAP.EXE  позволяет  добавлять  в  .MAP-файл   отладочную
 информацию.

      - И наконец,  TDUMP.EXE - это дисассемблер объектных модулей
 и .EXE-файлов.

      - Кроме того, имеется небольшая резидентная программа TDNMI.
 COM, сбрасывающая  защелку  прерывания  при  использовании  платы
 Periscope I.

      Для того,  чтобы получить список опций утилит  TDCONVRT.EXE,
 TDRF.EXE, TDSTRIP.EXE,   TDPACK.EXE,   TDMAP.EXE  или  TDUMP.EXE,
 наберите имя соответствующей команды и нажмите  Enter.  Например,
 для получения опций командной строки утилиты TDMAP.EXE, введите

    TDMAP

                       Установка системы Turbo Debugger                        

      На дискете  Installation Disk имеется программа INSTALL.EXE,
 которая поможет вам установить систему  Turbo  Debugger  на  свою
 машину.

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

      INSTALL копирует все файлы Turbo Debugger на жесткий  диск и
 помещает их в суб-директории. По умолчанию это

      Директория с Turbo Debugger:  C:\TD
      Директория с примерами:       C:\TD

      По умолчанию все файлы с дистрибутивных дискет  помещаются в

 = 14 =

 директорию для   Turbo   Debugger.   Если   вы  хотите  поместить
 демонстрационные файлы  в  отдельную  директорию,  отредактируйте
 путь доступа  к  файлам  примера  до  того,  как  выберете  START
 INSTALLATION.

      После того, как установка Turbo Debugger закончена, прочтите
 файл README,   где   находится   дальнейшая  информация  о  Turbo
 Debugger.

      Список всех опций командной строки можно получить, введя имя
 программы INSTALL.EXE и затем -h

    INSTALL -h

 Разархивирование файлов, содержащих примеры программ

  На дистрибутивных  дискетах  Turbo  Debugger  находится  файл  с
 расширением .ZIP - TDEXAMPL.ZIP.

      Каждый из этих  файлов  содержит  несколько  других  файлов,
 которые  были  упакованы  и  помещены  в  архив.  Эти файлы можно
 разархивировать самостоятельно с помощью утилиты UNZIP.EXE.

      Например, команда

      UNZIP TDEXAMPL

      распакует все файлы,  хранящиеся в  архиве  TDEXAMPL.ZIP,  и
 поместит их в текущую директорию.

      Программа предлагает  два  возможных  варианта:  скопировать
 файлы с расширением .ZIP в неизменном виде,  либо разархивировать
 все  файлы,  находящиеся  в архивах,  и скопировать их на жесткий
 диск в процессе установки.


 Жидкокристаллические и монохромные мониторы

      Если у  вас  возникают  затруднения   при   чтении   текста,
 выдаваемого  на  экран  программой INSTALL,  их можно устранить с
 помощью необязательного параметра командной  строки  /B,  который
 заставляет   программу  INSTALL  работать  в  черно-белом  режиме
 (BW80):

      A:INSTALL /B

      Этот параметр    может   потребоваться   при   использовании
 жидкокристаллического дисплея или системы с  цветным  графическим
 адаптером и монохромным или композитным монитором.
                              Аппаратная отладка                               

 = 15 =

 -----------------------------------------------------------------

      При работе  на  компьютере   с   процессором   80386   можно
 установить драйвер устройства TDH386.SYS,  который поставляется с
 отладчиком Turbo Debugger.  Этот  драйвер  позволяет  существенно
 ускорить работу с точками останова, которые следят за изменениями
 содержимого областей памяти и доступом к порту ввода/вывода.

      Скопируйте этот  файл  в  директорию,  где  у  вас  хранятся
 драйверы   устройств,   и   добавьте  в  файл  CONFIG.SYS  строку
 следующего вида:

      DEVICE=\SYS\TDH386.SYS

      При следующей загрузке системы Turbo Debugger сможет найти и
 использовать этот драйвер устройства.

      Для получения   подробной  информации  об  интерфейсе  этого
 драйвера  устройства   обратитесь   к   поставляемой   на   диске
 документации об аппаратном интерфейсе отладчика.

      Примечание: Если  у  вас  есть  плата для аппаратной отладки
 (например,  Arton,  Periscope,  Purart Trapper и т.д.), вы можете
 использовать  ее совместно с отладчиком Turbo Debugger. Проверьте
 совместимость этой платы с системой Turbo Debugger.
                              Что делать дальше?                               
 -----------------------------------------------------------------

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

 Программисты, изучающие язык семейства Turbo

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


 = 16 =

 Программисты, имеющие опыт работы на языке семейства Turbo

      Если вы уже имеете опыт программирования на одном  из языков
 семейства  Turbo,  вы можете начать с изучения новых особенностей
 пользовательского  интерфейса  системы  Turbo  Debugger,  которые
 описаны  в  главе 2.  Если это покажется вам полезным,  вы можете
 проработать учебное руководство.  Либо вы можете сразу перейти  к
 главе 4 "Запуск отладчика Turbo Debugger". Полный перечень команд
 отладчика приведен в главе 13 "Справочник команд отладчика".



 = 17 =

                                                                               
ГЛАВА 2  ОТЛАДКА И TURBO DEBUGGER

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

      В программировании  ошибки  являются  совершенно  нормальным
 явлением.  Редко  кому  удается с первого раза написать программу
 без ошибок.  В этом нет ничего удивительного,  и этого не следует
 стыдиться.   Однако   появление  ошибки  в  программе  заставляет
 программиста  многократно  проверять  все  с  самого  начала.   В
 программировании это называется отладкой.
                              Что такое отладка?                               
 -----------------------------------------------------------------

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

      Процесс отладки  в  общем  случае  можно разделить на четыре
 этапа:

      1. Обнаружение ошибки

      2. Поиск ее местонахождения

      3. Определение причины ошибки

      4. Исправление ошибки

 Обнаружение ошибки

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

 Нахождение ошибки

      Второй этап иногда является самым трудным.  Он заключается в

 = 18 =

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

 Определение причины ошибки

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

 Исправление ошибки

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

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

      Более подробное рассмотрение процесса отладки см. в главе 14.

      Однако есть  ошибки  гораздо  более  тонкие и коварные,  чем
 синтаксические. Они не проявляются до тех пор, пока вы не введете
 отрицательное  число,  либо  являются настолько неуловимыми,  что
 загоняют вас в тупик.  Здесь-то вам и придет на  помощь  отладчик
 Turbo Debugger.
                  Что может вам дать отладчик Turbo Debugger?                  
 -----------------------------------------------------------------

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

      Добавление такого мощного отладчика  к  компилятору  слишком

 = 19 =

 сильно увеличило бы его размер.

      Turbo Debugger   можно   использовать   для   отладки  любой
 программы на языке  Си,  Паскаль  или  ассемблере,  написанной  с
 помощью   компилятора   семейства   Turbo   фирмы   Borland   или
 компилятора,  разработанного другой фирмой,  если  он  генерирует
 информацию CodeView.

      Однако прежде чем отлаживать программу,  написанную на языке
 фирмы Microsoft,  необходимо использовать  специальную  программу
 преобразования, поставляемую с отладчиком Turbo Debugger.

      Кроме того,  можно  отлаживать любую программу,  созданную с
 помощью компилятора какой-либо другой фирмы, однако в этом случае
 отладка  может  производиться  только  на уровне языка ассемблера
 (если  не  имеется  информация   CodeView).   Тогда   вы   должны
 использовать  утилиту  TDCONVRT,  описание  которой  находится  в
 документации  по  утилитам  Turbo  Debugger   на   дистрибутивных
 дискетах.

      Отладчик Turbo   Debugger  может  помочь  решить  две  самые
 трудные задачи  отладки:  определение  местонахождения  ошибки  и
 выявление причины ошибки.  Turbo Debugger помогает преодолеть эти
 сложности   благодаря   широким   возможностям   приостанавливать
 выполнение  программы  и  проверять  ее  состояние в любой точке.
 Можно даже задавать новые  значения  переменным  и  проверять  их
 влияние  на  выполнение  программы.  Эта  возможность реализуется
 такими функциями отладчика как трассировка, пошаговое выполнение,
 просмотр, проверка, замена и слежение.

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

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

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

      Просмотр       Можно заставить Turbo Debugger открыть
                     специальное окно, в котором будет отображаться
                     различная полезная информация: переменные, их
                     значения, точки останова, содержимое стека,
                     файла регистрации, файла данных, исходного
                     файла, кода процессора, памяти, регистров,
                     сведения об арифметическом сопроцессоре, или

 = 20 =

                     информация, выдаваемая программой.

      Проверка       Можно заставить Turbo Debugger еще глубже
                     проникнуть в программу и проверить содержимое
                     сложных структур данных, таких как массивы.

      Замена         Можно заменить текущее значение переменной
                     (глобально или локально) заданным значением.

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

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

      Turbo Debugger 2.0 усилен возможностью отладки программ на
 С++ и  объектно-ориентированном  Паскале.  Он  умеет  работать   с
 объектами и  классами  и  корректно обрабатывает позднюю привязку
 виртуальных правил или  компонентные  функции,  и  таким  образом
 всегда правильно выполняет и показывает коды программы.

 Чего не может Turbo Debugge

      При всех  мощных  возможностях,  встроенных в отладчик Turbo
 Debugger,  может создаться впечатление,  что он может все.  Но  в
 действительности  это  не  так.  Есть  по  меньшей мере три вещи,
 которые Turbo Debugger не может делать за вас:

      - Turbo   Debugger   не   имеет    встроенного    редактора,
 позволяющего  вносить  изменения  в  исходный текст программы.  У
 большинства  программистов  есть  свой  редактор,   которым   они
 предпочитают пользоваться.  Включение редактора в отладчик заняло
 бы  слишком  много  памяти.  Однако  вы  легко  можете   передать
 управление  своему  текстовому  редактору,  выбрав  команду  Edit
 (редактирование) из локального меню окна  File  (более  подробную
 информацию  см.  в описаниях команд).  Turbo Debugger вызовет тот
 редактор, который вы задали с помощью программы настройки TDINST.
 Если же вы работаете с Turbo С++, вы можете воспользоваться новым
 средством Transfer,  позволяющим запуск Turbo Debugger  прямо  из
 интегрированной среды Turbo.


 = 21 =

      - Turbo   Debugger   не   может   за  вас  перекомпилировать
 программу.  Для этого нужен отдельный компилятор программ,  такой
 как Turbo Pascal или Turbo C.

      - Turbo  Debugger  не  может  за  вас  думать.  При  отладке
 программы ваше главное достоинство состоит в том,  что вы  умеете
 мыслить.  Turbo  Debugger  -  это мощный инструмент,  но если его
 использовать бездумно,  он вряд ли поможет вам сэкономить время и
 усилия.


 Как Turbo Debugger делает это

      Теперь послушайте   хорошую    новость:    Turbo    Debugger
 предоставляет  вам  всю  свою мощь и изощренность,  оставаясь при
 этом простым в использовании.

      Работа отладчика Turbo Debugger является искусным сочетанием
 мощи   и  простоты,  которая  обусловлена  исключительно  удобным
 пользовательским интерфейсом. В следующем разделе рассматриваются
 преимущества    прогрессивного    пользовательского    интерфейса
 отладчика Turbo Debugger.
                     Преимущества отладчика Turbo Debugger                     
 -----------------------------------------------------------------

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

      - Удобная и логичная система глобального меню.

      - Контекстно-зависимые  локальные меню,  которые практически
 делают ненужным запоминание и ввод команд.

      - Диалоговые  блоки,   в   которых   вы   можете   выбирать,
 устанавливать и переключать опции, а также вводить информацию.

      - Когда   вам  надо  ввести  что-либо  с  клавиатуры,  Turbo
 Debugger предоставляет вам сохраненный список текстов, которые вы
 уже  вводили в подобных ситуациях.  Вы можете выбрать любой текст
 из этого списка, отредактировать его или ввести новый текст.

      - Полная поддержка макрокоманд,  позволяющая  ускорить  ввод
 последовательности команд или нажатий клавиш.

      -  Удобное и полное управление окнами.

      - Поддержка устройства "мышь".

 = 22 =


      -  Доступ к нескольким типам интерактивной подсказки.

      - Запись сеанса и выполнение в обратной последовательности.

      В оставшейся   части  данной  главы  рассмотрены  эти  шесть
 особенностей   пользовательского   интерфейса   отладчика   Turbo
 Debugger.

 Меню и блоки диалога

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

      Каждому пункту линейки меню соответствует спускающееся меню.
 Через спускающееся меню можно:

      - Выполнить команду.

      - Открыть разворачивающееся меню.  Такие меню появляются при
 выборе пункта, за которым находится пиктограмма меню (>).

      - Открыть блок диалога.  Блоки диалога появляются при выборе
 пункта меню,  за  которым  находится  пиктограмма  блока  диалога
 (...).

 Использование меню
 ------------------

      Есть три способа вызова меню из полоски главного меню:

      Вход

      - Нажмите клавишу F10,  переместите курсор на  нужный  пункт
 меню и нажмите Enter.

      - Нажмите клавишу F10, а затем нажмите первую букву названия
 пункта меню (пробел, F, V, R, B, D, W, O).

      - Нажмите клавишу Alt и первую букву команды  главного  меню
 (F,  V,  R,  B,  D,  W,  O), чтобы выполнить данную команду меню.
 Например,  нажатие клавиш Alt-F из любого места  системы  вызовет
 меню File. Меню =(System) будет открыто при нажатии Alt-пробел.

      - Нажмите кнопку мыши при указателе, установленном в линейке
 меню.


 = 23 =

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

      Перемещение по меню

      - При   помощи   клавиш-стрелок  "вправо"  и  "влево"  можно
 переходить от одного к  другому  спускающемуся  меню.  (Например,
 если вы  находитесь  в  меню File,  то нажатие -> переведет вас в
 меню View).

      - При  помощи  клавиш-стрелок   "вверх"   и   "вниз"   можно
 переходить между командами конкретного меню.

      - Для   перехода   к   первому   и  последнему  пункту  меню
 используйте соответственно клавиши Home и End.

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

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

      Выход из меню или системы меню выполняется следующим образом.

      Выход

      - Для выхода из меню нижнего уровня и возврата к предыдущему
 нажмите клавишу Esc.

      - Для  выхода  из  системы  меню  и возврата в активное окно
 нажмите клавишу Esc.

      - Для  выхода  из  системы  меню  и возврата в активное окно
 нажмите клавишу F10 на любом уровне меню (но не в блоке диалога).

      - Для  выхода  из  системы  меню  и возврата в активное окно
 нажмите можно нажать кнопку мыши на активном окне.
      -

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

      На рисунке  13  в  главе  13   показана   полная   структура
 спускающихся   меню   системы  Turbo  Debugger.  В  таблице  13.1
 перечислены все активные клавиши. Для получения полной информации
 обо всех командах отладчика Turbo Debugger обратитесь к главе 13.


 = 24 =

 Блоки диалога
 -------------
      Многие опции  команд  Turbo  Debugger позволяют доступ через
 блоки диалога.  Блок диалога содержит один или более из следующих
 элементов:

 Состав блока диалога                                  Таблица 2.1
 -----------------------------------------------------------------
 Элемент            Как выглядит и что делает
 -----------------------------------------------------------------
 Кнопки             Кнопкой называется "затененный" текст (в моно-
                    хромных системах это выглядит как "инверсное"
                    изображение). При выборе кнопки Turbo Debugger
                    немедленно выполняет связанное с данной кноп-
                    кой действие. При выходе из блока диалога нажи-
                    мают кнопку OK, подтверждающую сделанный выбор,
                    либо кнопку Cancel, отменяющую выбор. В диало-
                    говых блоках бывают также кнопки Help, позво-
                    ляющую получить помощь по тому или иному
                    вопросу.

      Клавишей активации для кнопки OK служит Alt-K.

 Блоки переключения Блок переключения представляет  программный
                    двухпозиционный переключатель включено/выклю-
                    чено. Если опция, связанная с данным блоком,
                    включена, то выводится символ X в квадратных
                    скобках: [X].

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

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

 Блок списка        Блок списка содержит список элементов, из которых
                    вы можете   сделать   выбор  (например,  список
                    файлов, которые вы можете открыть).
 -----------------------------------------------------------------

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

      Если у  вас  есть мышь,  то навигация по блокам диалога даже

 = 25 =

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

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



 Контекстно-зависимая работа

      Кроме удобной   системы  спускающихся  меню  фирмы  Borland,
 преимущества  отладчика  Turbo  Debugger  включают  одно   мощное
 свойство,  которое  значительно  облегчает  работу с отладчиком и
 ускоряет процесс его освоения,  уменьшая  количество  необходимых
 для работы меню.

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

      Предположим, в  вашей  паскаль-программе  имеется  следующая
 строка:

      MyCounter[TheGrade] := MyCounter[TheGrade] + 1;

      При работе с отладчиком Turbo Debugger вы быстро обнаружите,
 что  получать  информацию о структурах данных очень просто.  Все,
 что для этого надо сделать,  это нажать клавишу  Ctrl-I,  клавишу
 активации  окна Inspect,  для проверки.  Если курсор находится на
 слове MyCounter,  Turbo Debugger выдаст информацию  о  содержимом
 всего массива. Однако, если вы выберете полное имя массива вместе
 с индексом  (то  есть  выделите  его)  и  затем  нажмете  Ctrl-I,
 отладчик  поймет,  что вы хотите проверить один элемент массива и
 покажет вам только этот элемент.

      Таким путем  можно  "углубляться"  в  структуры   данных   и
 получать  все более подробную информацию о программе.  По нажатию
 клавиш  Ctrl-I  во  время  проверки   массива   отладчик   выдаст
 информацию о его конкретном элементе.

      Контекстная зависимость  такого  рода  делает Turbo Debugger
 исключительно простым  в  использовании.  Для  работы  с  ним  не
 требуется запоминать и вводить с клавиатуры длинные строки команд
 меню  или  параметры  командной  строки.  Достаточно  переместить

 = 26 =

 курсор на тот элемент,  который необходимо проверить (или выбрать
 его с помощью  клавиши  Ins),  а  затем  вызвать  нужную  команду
 (например,  нажатием  клавиш  Ctrl-I - проверку).  Turbo Debugger
 всегда сделает все возможное,  чтобы предоставить  информацию  по
 данному элементу.

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

 Локальные меню
 --------------

      Другой аспект  зависимости  от  контекста   отладчика   Turbo
 Debugger  заключается в использовании локальных меню, специфичных
 для конкретных окон или панелей.

      Локальные меню  в  отладчике  Turbo  Debugger  привязаны   к
 конкретному  окну или панели,  в которой вы находитесь.  Важно не
 путать локальные меню  с  глобальными).  Ниже  показан  составной
 экран,  на котором находятся оба типа меню (при реальной работе в
 Turbo Debugger видеть их одновременно нельзя).

      Сравните приведенные ниже особенности меню этих  двух типов.

      Глобальные меню:

      - Доступ к спускающимся меню осуществляется нажатием клавиши
 F10 и использованием клавиш управления курсором или вводом первой
 буквы названия меню.

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

      -  Их содержимое никогда не изменяется.

      - Некоторым   командам   этих  меню  соответствуют  активные
 клавиши, которые доступны из любого места среды Turbo Debugger.

      Локальные меню:

      - Локальные меню вызывается нажатием клавиш Alt-F10 или Ctrl
 -F10.

      - Положение  на  экране и содержание данного меню зависит от
 того, какой выбран текст и где находится курсор.

      - Содержимое локальных меню может изменяться. (Тем не менее,
 важно понять, что многие локальные команды имеются практически во

 = 27 =

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

      - Каждая  команда  раскрывающегося  меню  имеет  сокращенную
 форму в виде нажатия активных клавиш,  одной из которых  является
 клавиша Ctrl, а другой - первая буква команды.

      Вследствие этого,  одно нажатие активной клавиши,  например,
 Ctrl-S,  может означать одно в данном контексте и совершенно иное
 в другом контексте. (Как было указано выше, тем не менее, имеется
 некоторая совокупность команд,  которая  остается  неизменной  во
 всех раскрывающихся меню и составляет их ядро.  Например, команды
 Goto и Search всегда делают одно и то же,  даже когда  вызываются
 из разных подокон.)

      С точки  зрения  пользователя,   локальные   меню   являются
 исключительно удобным средством.  Все возможные команды,  которые
 связаны с работой в данный момент, находятся у него перед глазами
 в явном виде. Это предохраняет его от попыток выбора неподходящих
 команд и позволяет сделать меню небольшими и понятными.
                                "Уроки истории"                                

      Система меню и контекстная  зависимость  -  это  только  два
 аспекта   удобного  пользовательского  интерфейса  системы  Turbo
 Debugger.  Еще одним его важным свойством является  "исторический
 список".

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

      Например, если  в  тексте  программы  надо  найти  функцию с
 именем ReturnOnInvestment,  обычно для этого требуется  ввести  с
 клавиатуры все это слово или его часть. Теперь предположим, что в
 тексте   программы   необходимо   найти   переменную   с   именем
 MyPercentage.  Когда  в этот раз на экране появится блок запроса,
 вы увидите,  что в нем сохранился текст  ReturnOnInvestment.  При
 следующем  поиске  текста  в блоке запроса будут отображаться обе
 введенные ранее строки.  Этот список будет пополняться при каждом
 использовании команды Search.

      Этот "исторический список"  можно  использовать  для  выбора
 любого  введенного  ранее  текста  с  помощью  клавиш  управления
 курсором и нажать клавишу Enter,  чтобы начать его поиск. Если вы
 используете какой-либо элемент списка в неизменном виде, то после
 выполнения поиска он перемещается в начало списка.

 = 28 =


      Кроме того, можно отредактировать текст (используйте клавиши
 управления  курсором  для  позиционирования курсора на выделенный
 текст и отредактируйте его обычным  способом,  используя  клавиши
 Del и Backspace).  Например,  можно выбрать текст myPercentage и,
 отредактировав его,  получить текст hisPercentage,  вместо  того,
 чтобы вводить с клавиатуры весь текст целиком.  Если вы начинаете
 вводить новый элемент,  когда некоторый элемент  списка  является
 выделенным, вы затираете им выделенный элемент.

      Первым элементом  в списке для поиска всегда является слово,
 на котором в данный момент установлен курсор в окне Module.

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

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

 Автоматическое дополнение имени
 -------------------------------

      Когда вам дается приглашение на ввод текста в  блоке  ввода,
 вы можете  ввести только часть символического имени программы,  а
 затем нажать Ctrl-N.

      Предупреждение! Когда   в   верхнем   правом   углу   экрана
 появляется слово READY...  с тремя точками в конце, это означает,
 что происходит сортировка таблицы символических имен.  Ctrl-N  не
 будет работать  до  тех  пор,  пока  не  исчезнут три точки,  что
 означает готовность таблицы символических  имен  к  использованию
 для автоматического дополнения имен.

      - Если   введено   достаточно   символов   для   однозначной
 идентификации имени, Turbo Debugger дополняет имя.

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

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

      Turbo Debugger  позволяет  выполнять   поиск   элементов   в
 диалоговом блоке  со  списком  файлов  и директорий инкрементено.
 Начните ввод имени файла или директории; если такой файл в списке

 = 29 =

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

                               Создание макросов                               

      Макрос -  это  ни  что иное,  как активная клавиша,  которую
 определяете вы сами.

      Любой последовательности команд отладчика Turbo  Debugger  и
 нажатий  клавиш  можно  поставить  в  соответствие  одну клавишу,
 которая будет "воспроизводить" заданную последовательность.

      Для того чтобы создать макрос,  надо выбрать Options|Macros.
 После   этого  можно  выбрать  одну  из  четырех  команд:  Create
 (создать),  Remove (удалить), Delete All (уничтожить все макросы)
 и  Stop  Recording  (закончить запись).  Выберите команду Create.
 Turbo Debugger запросит клавишу, которой будет назначен следующий
 макрос. Нажмите редко используемую или легко запоминаемую клавишу
 (например,  Shift-F1 для повторного  запуска  программы).  Теперь
 выполните  все  действия  и команды,  которые вы хотите назначить
 этой клавише.

      --------------------
      Create          Alt=
      Stop Recording  Alt-
      Remove
      Delete All
      --------------------

 Для  того чтобы закончить запись:

      - Выберите Options|Macros|Stop recording

      - Нажмите  только  что  определенную макро клавишу (в данном
 примере Shift-F1).

      - Нажмите Alt- (Держа нажатой клавишу  Alt,  нажмите  дефис,
 или знак минус.


      Каждый раз,   когда   вы   будете    выполнять    какую-либо
 последовательность  действий,  задавайте себе вопрос:  "Нельзя ли
 для этой последовательности использовать макрос?".

                              Использование окон                               

      В большинстве  современных программ используются окна,  но в

 = 30 =

 системе Turbo Debugger они сделаны еще лучше.  Всю  информацию  и
 данные Turbo Debugger отображает в меню (локальных и глобальных),
 блоках запроса (в которые информацию  вводит  пользователь)  и  в
 окнах.  Используются  различные  виды окон в зависимости от того,
 какого типа информация в них отображается. Все окна открываются и
 закрываются   с   помощью   команд  меню  (или  активных  клавиш,
 соответствующих этим  командам).  Большая  часть  окон  отладчика
 Turbo  Debugger вызывается из спускающегося меню View (просмотр).
 Из этого меню вызывается 14 видов окон.  Имеется и  окно  другого
 типа,  которое  называется окном проверки (Inspect) и открывается
 выбором пункта Data|Inspect или  пункта  Inspect  из  большинства
 локальных меню.

 Окна, вызываемые из меню View
 -----------------------------------------------------------------

      ---------------------
      Breakpoints
      Stack
      Log
      Watches
      Variables
      Module...          F3
      File...
      CPU
      Dump
      Registers
      Numeric processor
      Execution history
      Hierarchy
      Another
      ---------------------

      Ниже приведено   описание   13  видов  окон,  которые  можно
 открыть,  вызвав соответствующие команды из меню View (просмотр).

      Если вы  открыли  одно  такое  окно  или  более,  вы  можете
 перемещать их,  изменять  размеры,  закрывать  и  управлять этими
 окнами самыми различными способами при помощи команд  меню Window
 и =(System), рассматриваемых в разделе "работа с окнами".


 Окно модуля (Module)
 --------------------

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

      По всей  вероятности,  на  работу  в  этом  окне  вы  будете

 = 31 =

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

      Подробное описание окна модуля  и  его  команд  приведено  в
 главе 8.


 Окно слежения (Watches)
 -----------------------

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

      Подробное описание окна слежения и его  команд  приведено  в
 главе 6.

 Окно точек останова (Breakpoints)
 ---------------------------------

      Отображает точки  останова,  заданные  пользователем.  Точка
 останова задает место в программе,  где что-то должно  произойти,
 то  есть в этой точке выполнение программы приостанавливается,  и
 вы можете проверить ее состояние.  (Turbo  Debugger  поддерживает
 все возможности,  которые обычно закладываются в точки останова.)
 Данное  окно  можно  использовать  для   переноса,   удаления   и
 добавления точек останова.

      Подробное описание  этого  окна  и работы с точками останова
 приведено в главе 7.


 Окно стека (Stack)
 ------------------

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

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

      Высветив имя функции в стеке и нажав Ctrl-L,  вы  тем  самым
 откроете окно Variables, в котором показаны глобальные переменные
 программы, локальные переменные функции и аргументы,  с  которыми
 вызвана функция.

 = 32 =


      Более подробная  информация  об  этом окне приведена в главе
 5.

 Окно регистрации (Log)
 ----------------------

      Отображает содержимое журнала регистрации  сообщений. Журнал
 содержит    прокручиваемый   список   сообщений   и   информацию,
 сформированную при работе с отладчиком  Turbo  Debugger.  В  этом
 журнале хранится такая информация, как причина прекращения работы
 программы,  результаты выполнения программы до точек  останова  и
 значения структур, которые были сохранены в журнале.

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

      Более подробная  информация  об окне регистрации приведена в
 главе 7.


 Окно переменных (Variables)
 ---------------------------

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

      Это окно бывает полезно  в  тех  случаях,  когда  необходимо
 найти некоторую функцию или переменную, про которую известно, что
 она начинается,  скажем,  с символов  "abc",  но  точное  ее  имя
 забыто.  В  этом  случае  можно  просмотреть  содержимое  подокна
 глобальных переменных  и  быстро  найти  то,  что  нужно.

      Более подробно окно переменных описано в главе 5.


 Окно файла (File)
 -----------------

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

      Это бывает   удобно  при  отладке  программы,  работающей  с
 дисковыми файлами, поведение которой желательно изменить, заменив
 содержимое  одного  из ее файлов.  Можно также исправить ошибку в
 файле  или  проверить  файл,  сформированный  программой,   чтобы

 = 33 =

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

      Более подробно окно файла описано в главе 8.


 Окно процессора (CPU)
 ---------------------

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

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

      Turbo Debugger  иногда  открывает  окно  CPU  автоматически,
 когда программа   останавливается   на   команде,  находящейся  в
 середине строки исходного кода.

      В главе 11 описывается окно процессора и отладка  на  уровне
 языка ассемблера.


 Окно дампа (Dump)
 -----------------

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

      Для получения  более  подробной  информации  о  данном  окне
 обратитесь  к  главе  11,  в  которой  рассматривается отладка на
 уровне ассемблера.


 Окно регистров (Registers)
 --------------------------

 = 34 =

      Отображает состояние регистров и флагов процессора. Это окно
 имеет два подокна, которые аналогичны подокнам регистров и флагов
 окна  процессора.  Используйте  это  окно  в  тех случаях,  когда
 необходимо проверить состояние регистров, не заботясь о состоянии
 остальной  части  процессора.  С  помощью  команд локального меню
 можно изменять значения любых регистров и флагов процессора.

      Для получения  более  подробной  информации  о  данном  окне
 обратитесь  к  главе  11,  в  которой  рассматривается отладка на
 уровне ассемблера.


 Окно числового процессора (Numeric Processor)
 ---------------------------------------------

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

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

      Более подробная  информация  об  окне  числового  процессора
 приведена в главе 12.


 Окно истории выполнения (Execution History)
 -------------------------------------------

      Данное окно выводит на дисплей ассемблерный код  и  исходные
 строки вашей программы,  до последней выполненной строки. Верхнее
 подокно содержит  выполненный  ассемблерный  код,  что  позволяет
 двигаться по  программе в обратном направлении;  в нижнем подокне
 выводится информация о том,

 1. происходит ли трассировка или пошаговое выполнение программы;

 2. строка исходного кода для выполняемой команды;

 3. номер строки исходного кода.

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

      Более подробную  информацию об окне Execution History см.  в
 главе 5.

 = 35 =



 Окно иерархии (Hierarchy)
 -------------------------

      Выводит на дисплей иерархическое дерево для всех объектов или
 типах класса,  используемых в текущем модуле.  Это окно имеет два
 подокна: одно для вывода списка объектов/типов класса, а другое -
 для вывода  дерева  объектов/типов  класса.  (Если вы отлаживаете
 программу С++ с множественным  наследованием,  то  открывается  и
 третье подокно,  в  котором показаны "родители" высвеченного типа
 класса).

      Данное окно  показывает  взаимосвязи  между  объектами   или
 типами класса,   используемыми   в   текущем  модуле.  Оно  также
 позволяет рассматривать любой объект  или  тип  класса,  а  также
 соответствующие им  компонентные поля или компонентные данные,  а
 также их правила или компонентные функции,  с использованием  для
 этого локальных меню, принадлежащих меню Hierarchy.

      Более подробную информацию об окне Hierarchy см. в главе 10.


 Окна-дубликаты
 --------------

      ---------------
      Module...
      Dump
      File...
      ---------------

      Вы имеете  возможность  открывать также дубликаты трех типов
 окон - Dump,  File и Module,  выбирая для этого View/Another. Это
 позволяет   следить   одновременно   за  несколькими  различными
 фрагментами    ассемблерного    кода,     различными     файлами,
 обрабатываемыми  или формируемыми программой,  или за несколькими
 разными модулями программы.

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


 Окно экрана пользователя (User Screen)
 --------------------------------------

      Отображает информацию,  выдаваемую   на   экран   программой
 пользователя.  Информация отображается точно в таком же виде, как
 если бы вы запустили программу непосредственно из ДОС,  а  не  из
 отладчика.

 = 36 =


      Это окно можно использовать для проверки того, что программа
 находится в той точке,  в которой предполагается,  или того,  что
 программа выдает на экран правильную информацию. Для вызова этого
 окна выберите Window|User Screen.  Для  того  чтобы  вернуться  к
 экрану  отладчика  после  просмотра экрана пользователя,  нажмите
 любую клавишу.

      Активной клавишей переключения между  интегрированной средой
 и экраном пользователя служит Alt-F5.



 Окно проверки
 -------------

      В окне проверки (Inspector)  отображается  текущее  значение
 выбранной  переменной.  Окна этого типа никогда не разбиваются на
 подокна.  Обычно это окно закрывается по нажатию клавиши Esc  или
 кнопки  мыши.  Если  вы  последовательно  открыли  несколько окон
 проверки,  что часто происходит  при  проверке  сложных  структур
 данных,  вы  можете  закрыть все их сразу нажатием клавиши Alt-F3
 или с помощью команды Window/Close (Окно/Закрыть).

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

      Обратите внимание, что в отличие от окон, вызываемых из меню
 View,  здесь имеется возможность  создавать  дополнительные  окна
 проверки   просто   путем   повторного  выбора  команды  Inspect.
 (Дополнительные окна модуля,  файла и процессора можно  открывать
 только путем выбора пункта View/Another.)

 Активное окно
 -------------

      Несмотря на то,  что  в  отладчике  Turbo  Debugger  имеется
 возможность  иметь  одновременно несколько открытых окон,  только
 одно из них может являться активным. Активное окно можно отличить
 по следующим признакам:

      - Активное окно окружено двойной рамкой, а не одинарной, как
 остальные.

      -  Активным является  окно,  в  котором  находится  курсор  или

 = 37 =

         выделяющая полоса.

      - Если окна перекрывают друг друга,  активное окно находится
 поверх остальных.

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

 Что такое окно
 --------------

      Окно всегда  обладает большинством или всеми описанными ниже
 средствами, позволяющими получить информацию  об  этом  окне  или
 выполнить с ним некоторые действия:

      - Рамка  (двойной линией,  если окно активно,  и одинарной а
 противном случае).

      - Заголовок, расположенный в верхнем левом углу.

      - Линейка или линейка скроллинга в правой или  нижней  части
 окна, если  окно  содержит  больше  информации,  чем  может  быть
 выведено одновременно. С линейками скроллинга работает мышь:

         - Для перемещения изображения в окне на один символ или
           одну строку  нужно  нажать кнопку мыши на стрелке нужного
           направления, которые   находятся   на   концах   линеек
           скроллинга.

         - Для перемещения изображения в окне на одно окно в
           нужном направлении  следует  нажать  кнопку  мыши  на
           середине линейки, отмеченной серым цветом.

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

      - Блок  установки  размера  окна  в нижнем правом углу.  Для
 установки желаемого размера окна нужно выполнить  буксировку  его
 при помощи мыши.

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

      - Блок панорамирования и блок  пиктограммирования  в  правом
 верхнем углу.  Слева  находится  пиктограмма  панорамирования,  а
 справа - пиктограммы пиктограммирования.  Нажмите кнопку мыши  на
 этих пиктограммах  для расширения окна до размера полного экрана,
 восстановления исходного  размера  окна  или   пиктограммирования

 = 38 =

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

      - Блок закрытия в верхнем левом углу. Нажмите кнопку мыши на
 данном блоке для закрытия окна.


 Работа с окнами
 ---------------

      Каждое открываемое вами окно нумеруется  в  верхнем  правом
 углу. Обычно окно Module имеет номер 1, а окно Watches - номер 2.
 Окно, открытое следующим, будет иметь номер 3 и т.д.

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

      Можно также  активизировать  окна  одно  за  другим,  выбрав
 Window|Next  или  последовательно нажимая клавишу F6.  Это бывает
 удобно в том случае,  если номер открытого  окна  закрыт  другими
 окнами и неизвестно, какую клавишу надо нажать, чтобы сделать его
 активным.

      F6 - это активная клавиша команды Window|Next Window.

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

      Чтобы просмотреть  список  всех  открытых окон,  выберите из
 линейки меню Window. Turbo Debugger отобразит в нижней части меню
 Window  список  до  девяти  открытых окон,  одно из которых можно
 выбрать.  Чтобы выбранное из этого списка  окно  стало  активным,
 нажмите клавишу с номером этого окна.

      Если окно  разбито на  несколько подокон  (участков, содержащих
 различные типы данных), можно переходить от одного подокна к другому
 с помощью клавиши Tab, Shift-Tab или команды Window/Next Pane.

      Tab и Shift-Tab - это активные клавиши для Window|Next Pane.

      Подокно можно также выбрать нажатием кнопки мыши.

      Больше всего  подокон  в отладчике Turbo Debugger имеет окно
 процессора. Оно разбито на пять подокон.


 = 39 =

      При переходе из одного подокна в другое можно  заметить, что
 в  некоторых  случаях  в  подокне  появляется мигающий курсор,  в
 других случаях вместо него  появляется  выделяющая  полоса.  Если
 появляется  курсор,  значит  вы  можете  перемещаться по тексту с
 помощью обычных команд  управления  курсором  (например,  клавиши
 PgUp,  Ctrl-Home  и Ctrl-PgUp перемещают курсор соответственно на
 один экран вверх,  в верхнюю часть  подокна  и  в  верхнюю  часть
 списка).   Для   перемещения  курсора  внутри  окна  можно  также
 использовать команды системы WordStar.  Список клавишных  команд,
 которые  можно использовать в подокнах,  приведен в таблице главы
 13.

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

      Когда элемент  выбран  из  списка  (выделен),  можно,  нажав
 клавиши Alt-F10 или клавиши Ctrl-F10,  выбрать относящуюся к нему
 команду  локального меню.  В большинстве списков после того,  как
 элемент выбран,  бывает  достаточно  нажать  клавишу  Enter.  Она
 действует   как   активная   клавиша   одной  из  наиболее  часто
 используемых команд локального меню. Точная функция клавиши Enter
 для  подобных  случаев описана в разделе "Команды локальных меню"
 главы 13.

      И наконец, в некоторых подокнах можно сразу начинать вводить
 новое  значение или строку для поиска без предварительного выбора
 команды.  Это обычно используется для наиболее часто используемой
 команды  подокна или окна,  такой как команда Goto в окне модуля,
 команда Search в окне файла или команда Change в  окне регистров.

 Изменение и сохранение размеров окон
 ------------------------------------

      Когда Turbo  Debugger создает  новое окно,  оно  появляется  на
 экране около  текущего положения  курсора и  имеет установленный  по
 умолчанию размер,  удобный для данного окна. Размер и местоположение
 окна можно изменить с помощью команды меню Window|Size/Move.

      Ctrl-F5 - это активная клавиша команды Window|Size/Move.

      После выбора этой команды рамка  активного  окна  становится

 = 40 =

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

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

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

      - Отбуксируйте линейку заголовка или любую  крайнюю  линейку
 (но не  линейки скроллинга),  чтобы изменить расположение окна на
 экране.

      F5 - это активная клавиша команды Window|Zoom.

      Если необходимо  быстро увеличить  (или уменьшить) размер окна,
 можно выбрать команду Window|Zoom или нажать кнопку мыши на блоке
 панорамирования или пиктограммирования  в  правом  верхнем  углу,
 соответственно.

      И наконец, если вам нужно временно выйти из данного окна без
 его закрытия, активизируйте его, а затем выберите Window|Iconize/
 Restore. При  этом  окно сократится таким образом,  что останется
 только небольшой прямоугольник  (пиктограмма)  с  именем,  блоком
 закрытия, и блоком панорамирования.  Для восстановления исходного
 размера окна   сделайте   его   активным   и    снова    выберите
 Window|Iconize/Restore, либо   нажмите   кнопку   мыши  на  блоке
 панорамирования.

 Закрытие и восстановление окон
 ------------------------------

      При работе   с   окном   вы   можете   закрыть  его,  выбрав
 Window|Close, или  нажав  Alt-F3,  активную  клавишу  для  данной
 команды.

      Alt-F3 - это активная клавиша команды Window|Close.

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

      Если вы закрыли окно ошибочно,  то его  можно  восстановить,
 выбрав Window|Undo  Close  или нажав Alt-F6.  Этот способ годится
 только для последнего закрытого окна.

      Alt-F6 - это активная клавиша команды Window|Undo Close.

      Вы также   можете   восстановить   экран   Turbo    Debugger
 соответственно макету  экрана,  который  действовал  при  входе в

 = 41 =

 программу в первый  раз.  Выберите  для  этого  =(System)|Restore
 Standard.

      И наконец,    если    ваша    программа    заменила    экран
 интегрированной среды отладчика собственным выводом  (из-за того,
 что вы выключили своппинг экрана),  можно очистить и восстановить
 экран при помощи =(System)|Repaint Desktop.

 Сохранение макета экрана
 ------------------------

      Можно также   использовать   команду  Options/Save  Options,
 которая позволяет сохранить выбранные параметры окон  после того,
 как экран настроен пользователем по своему усмотрению.  Для этого
 в  диалоговом  блоке  Save  Configuration  при   помощи   клавиши
 табуляции  выберите  пункт  Layout  и  при помощи клавиши пробела
 переключите  его  во  включенное  состояние.  Теперь  при  каждом
 последующем  запуске  отладчика Turbo Debugger из DOS экран будет
 выглядеть именно так, поскольку его конфигурация была сохранена в
 файле  TDCONFIG.TD.  Это единственный файл конфигурации,  который
 загружается автоматически при запуске отладчика  Turbo  Debugger.
 Другие  файлы конфигурации могут быть загружены с помощью команды
 Options/Restore Options.
                     Предоставление подсказки пользователю                     

      Как видите,  Turbo Debugger делает все,  что возможно, чтобы
 максимально  облегчить  пользователю процесс отладки.  Он требует
 помнить  минимальное  количество  команд,  он  сохраняет   список
 введенных  с клавиатуры текстов на тот случай,  если пользователь
 захочет повторить один из них,  он позволяет определять макросы и
 обеспечивает исключительно удобное управление окнами. Но несмотря
 на все это,  Turbo Debugger остается очень сложной  программой  с
 большим  количеством  функций и команд.  Чтобы избежать возможных
 затруднений,  Turbo Debugger предоставляет пользователю  экранную
 подсказку, имеющую следующие особенности:

      - Текущее   действие,   выполняемое   пользователем,  всегда
 отображается на экране специальным индикатором,  расположенным  в
 верхнем  правом  углу экрана.  Например,  если курсор находится в
 каком-либо  окне,  этот  индикатор  действия   показывает   READY
 (готов);   если  на  экран  вызвано  какое-либо  меню,  индикатор
 показывает MENU (меню);  если курсор находится  в  поле  запроса,
 индикатор  показывает  PROMPT  (запрос).  Если  вы  затрудняетесь
 определить,  что в данный момент  происходит  в  среде  отладчика
 Turbo  Debugger,  используйте в качестве подсказки этот индикатор
 текущего действия.  (Другими возможными "показаниями"  индикатора
 текущего    действия    являются    MOVE/RESIZE,   MOVE,   ERROR,
 RECORDING,WAIT, RUNNING, MENU, HELP, STATUS и PLAYBACK.)

      - Помните,  что активное  окно  всегда  отображается  поверх

 = 42 =

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

      - Нажав клавишу F1, можно получить доступ к обширной системе
 контекстно-зависимой подсказки.

      - В нижней  строке  экрана  всегда  предоставляется  краткий
 перечень  команд,  вызываемых  нажатием  клавиш.  Содержимое этой
 строки изменяется при смене контекста и при нажатии  клавиши  Alt
 или  Ctrl.  Когда вы находитесь в системе меню,  строка состояния
 содержит оперативный комментарий к текущей команде меню.

      Более подробная информация  о  двух  последних  возможностях
 экранной подсказки приведена в следующем разделе.

 Интерактивная подсказка
 -----------------------

      Turbo Debugger,  как и  остальные  продукты  фирмы  Borland,
 предоставляет    пользователю    контекстно-зависимую    экранную
 подсказку,  которая вызывается нажатием одной клавиши.  Подсказка
 доступна в любой момент,  как при работе с меню или окном,  так и
 при выдаче на экран сообщения об ошибке или запроса.

      Нажатие клавиши F1 вызывает на экран окно  подсказки (Help),
 содержащее информацию, связанную с текущим контекстом. Если у вас
 имеется "мышь",  то вы можете получить подсказку, нажав кнопку на
 линейке  состояния.  Некоторые  экраны подсказки имеют выделенные
 ключевые  слова,  которые   позволяют   получать   дополнительную
 подсказку  по  выделенному  элементу.  Для  того чтобы перейти от
 одного ключевого слова к другому,  используйте Tab или Shift-Tab,
 а  затем  нажмите  клавишу  Enter,  чтобы  вызвать  подсказку  по
 выбранному  элементу.  Для  того  чтобы  перейти  к  первому  или
 последнему   ключевому   слову   на  экране,  можно  использовать
 соответственно клавиши Home и End.

      Подсказку можно также получить,  выбрав Help из линейки меню
 (Alt-H).

      ----------------------
      Index         Shift-F1
      Previous topic  Alt-F1
      Help on help
      ----------------------

      Если требуется  вернуться  к  предыдущему  экрану подсказки,
 надо нажать клавиши Alt-F1 или выбрать команду Previous  из  меню
 Help.. Находятся в системе подсказки, можно с помощью клавиши PgUp
 просматривать до 20 последних экранов подсказки.    Клавиша  PgDw
 работает  только  в  том  случае,  если  вы просматриваете экраны
 подсказки,  связанные  с  контекстом.   Чтобы   вызвать   именной
 указатель (Index), надо нажать клавишу Shift-F1 (или , находясь в

 = 43 =

 системе подсказки,  F1),  либо выбрать Index из  меню  Help.  Для
 получения справки по самой системе интерактивной подсказки, нужно
 выбрать  Help|Help  on   Help.   Выход   из   системы   подсказки
 осуществляется по клавише Esc.

      Можно получить  интерактивную  подсказку  по резервированным
 словам при помощи THELP.COM.

      Если вы работаете с Turbo  Pascal  или  Turbo  С  и  желаете
 получить подсказку  по  резервированным  словам или функциям этих
 языков, как это делается в интегрированной  среде соответствующих
 языков при  отладке,  это  можно  сделать  при помощи резидентной
 утилиты THELP.COM,  поставляемой с Turbo Pascal и  Turbo  С.  Для
 этого:

      1. Убедитесь,    что   THELP.COM   и   файл   подсказки   по
 соответствующему языку (TURBO.HLP для Turbo Pascal  и  TCHELP.TCH
 для Turbo  С)  скопированы  в  директорию  с  Turbo  Debugger или
 директорию, определяемую командой PATH.

      2. Наберите THELP и нажмите Enter.

      3. Войдите в Turbo Debugger.

      4.Для того,  чтобы открыть экран подсказки для интересующего
 вас резервированного  слова  или  функции,  установите  курсор  в
 позицию, где  набрано  это  слово,   и   нажмите   цифру   5   на
 вспомогательной числовой  клавиатуре.  (Если нажать 5 на основной
 клавиатуре, THELP.COM не сработает).

      5. Затем интерактивной подсказкой  можно  пользоваться  так
 же, как в отладчике интерактивной среды, причем Alt-F1 служит для
 возврата к предыдущему экрану,  а нажатие Enter  дает  вам  экран
 подсказки по выбранному ключевому слову.

      6. для выхода из экрана Help нажмите Esc.

      Более подробную  информацию  о THELP см.  в файле THELP.DOC,
 поставляемом с используемым вами языком.

 Строка состояния
 ----------------

      В каком  бы  месте среды Turbo Debugger вы не находились,  в
 нижней строке экрана всегда приводится подсказка в  виде  перечня
 команд отладчика.  В этой строке в явном виде перечислены команды
 отладчика и клавиши для их вызова, доступные в текущем контексте.

 Подсказка в окне

      Обычно в  строке состояния перечислены команды,  выполняемые

 = 44 =

 по нажатию функциональных клавиш.

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

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

      Если у  вас  имеется  "мышь",  то вы можете нажать кнопку на
 строке состояния, и будет выполнена команда Alt- или Ctrl.

 Подсказка в меню или блоке диалога

      Когда вы   находитесь  в  меню  или  блоке  диалога,  строка
 состояния выводит однострочный комментарий к выбранному в текущий
 момент пункту меню или блока. Например, если высвечен пункт View|
 Register, то строка состояния будет содержать фразу "Open  a  CPU
 register window" ("Открытие окна регистров процессора").

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




 = 45 =

                    ГЛАВА 3  НАЧАЛО РАБОТЫ: КОРОТКИЙ ПРИМЕР                    

      Если вам  не  терпится  начать  работать  с отладчиком Turbo
 Debugger и вы не из тех людей,  которые прежде чем  приступить  к
 работе  тщательно  проработают все руководство пользователя,  то,
 прочитав  эту  главу,  вы  получите  достаточно   знаний,   чтобы
 отлаживать  свою  первую  программу.  Когда  вы  изучите основные
 принципы работы отладчика,  описанные ниже,  удобный, интуитивный
 пользовательский   интерфейс   и   система   контекстно-зависимой
 подсказки позволят вам  изучать  возможности  отладчика  по  ходу
 работы с ним.

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

      -  запускать и останавливать программу,

      -  проверять значения переменных программы,

      - просматривать  сложные  данные,  такие   как   массивы   и
 структуры,

      -  изменять значения переменных.
                               Примеры программ                                
 -----------------------------------------------------------------

      Примеры программ (TCDEMO.C на Си и  TPDEMO.PAS  на  Паскале)
 познакомят  вас с двумя важными вещами,  которые необходимо знать
 для  того,  чтобы   отлаживать   программу:   как   запускать   и
 останавливать  программу  и  как  проверять значения переменных и
 структур данных программы.  Сами по себе эти  программы  вряд  ли
 могут  оказаться  полезными:  некоторые  их параметры и структуры
 данных созданы исключительно для того,  чтобы  продемонстрировать
 возможности отладчика Turbo Debugger.

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

      Убедитесь в том, что в вашей текущей директории имеются файлы
 примеров   программ,   которые  потребуются  при  чтении  данного
 руководства.  Пример программы на языке Си  включает  два  файла:
 TCDEMO.C   и   TCDEMO.EXE;   пример  на  Паскале  включает  файлы
 TPDEMO.PAS и TPDEMO.EXE.


 = 46 =

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

      TD TCDEMO

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

      TD TPDEMO

      Turbo Debugger   загрузит   демонстрационную   программу   и
 установит курсор в ее начале.

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

      Для того чтобы выйти из отладчика и вернуться в ДОС, в любой
 момент  можно  нажать  клавиши  Alt-X.  Если,  работая  с  данным
 руководством,  вы что-либо безнадежно повредите в программе,  то,
 нажав клавиши Ctrl-F2, можно загрузить ее заново и начать отладку
 с начала. Однако, имейте в виду, что эта команда не удаляет точек
 останова  и отслеживаемых объектов;  если это необходимо сделать,
 используйте клавиши Alt-F O.  (Alt-B D также  удаляет  все  точки
 останова, но  иногда  перезагрузка быстрее выполняется при помощи
 Alt-F O).

      Всякий раз,  когда вам  потребуется  подсказка  по  текущему
 окну,  команде меню,  запросу или сообщению об ошибке,  нажимайте
 клавишу F1.  Работая самостоятельно с системой меню и нажимая  F1
 для  получения  обобщенной  информации  о том,  что делает данная
 команда, можно многому научиться.
                      Работа с отладчиком Turbo Debugger                       
 -----------------------------------------------------------------

      Меню

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

      Сейчас нажмите клавишу F10.  Обратите внимание, что при этом
 курсор  исчезает  из  окна  модуля,  а  пункт  File главного меню
 становится выделенным.  Нижняя строка  экрана  также  изменяется,
 показывая, какие команды содержит меню File.

      С помощью  клавиш  управления курсором можно перемещаться по
 системе  меню,  а  с  помощью  клавиши  "Стрелка  вниз"  вызывать
 спускающиеся  меню,  соответствующие  выделенному пункту главного

 = 47 =

 меню.

      Если у вас имеется "мышь",  то вы можете  нажать  кнопку  на
 пункте меню в линейке этого меню.

      Для возврата  на предыдущий уровень системы меню используйте
 клавишу Esc.  Когда выделенным  является  только  пункт  главного
 меню,  нажатие  клавиши  Esc вернет вас в окно модуля,  а главное
 меню перестанет быть активным.

 Строка подсказки

      В нижней  строке  экрана  указываются  связанные  с  контекстом
 функциональные  клавиши  и  их  функции.

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

      Теперь на секунду нажмите клавишу Ctrl. Команды, указанные в
 нижней строке, являются сокращенной формой команд локального меню
 для текущего подокна (участка окна).  Они меняются в  зависимости
 от вида текущего окна. Более подробно об этом позже.

      При входе в систему меню линейка состояния снова изменяется,
 показывая, что делает тот или иной пункт меню.  Нажмите  F10  для
 перехода к  линейке  меню  и  нажмите клавишу -> для того,  чтобы
 выделить опцию File.  В линейке состояния  будет  написано  "File
 oriented functions" ("Функции для работы с файлами").  При помощи
 "стрелки вниз" спускайтесь по меню File,  и посмотрите, как будет
 изменяться информация в строке состояния.  Нажмите Esc или кнопку
 мыши на окне Module, чтобы выйти из системы меню.

 Окна

      Область окон занимает большую часть экрана.  Эта та область,
 в   которой   вы  проверяете  различные  части  своей  программы,
 просматривая их в разных окнах.

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

      Заметьте, что  окно  модуля  окружено  двойной  рамкой и его
 заголовок  выделен  яркостью.  Это  означает,  что  оно  является

 = 48 =

 активным   окном.   Для   перемещения   внутри   активного   окна
 используются клавиши управления курсором (клавиши  с  изображение
 стрелок, Home, End, PgUp и т.д.). Для того чтобы перейти в другое
 окно,  нажмите клавишу F6.  Сделайте это сейчас.  Активным станет
 окно слежения:  его рамка станет двойной, а заголовок выделенным.

      Для создания  новых окон используется пункт View главного меню.
 Например, для открытия окна Stack выберите View|Stack. Окно Stack
 раскроется в верхней части  окна Module.

      Чтобы удалить   активное   окно,   нажмите  клавишу  Alt-F3.
 Сделайте это сейчас. Окно стека исчезнет.

      Turbo Debugger  запоминает последнее закрытое окно, так что при
 необходимости его  можно  восстановить.  Если  вы  случайно  закрыли
 какое-либо окно,  выберите  Window|Undo  Close.  При  этом  снова
 появится окно Stack.  Для восстановления последнего открытого окна
 также можно нажать Alt-F6.

      Меню Window  содержит   команды,   позволяющие   настраивать
 внешний   вид   окон,   которые  уже  имеются  на  экране.  Можно
 переместить окно в другое место  экрана,  а  также  изменить  его
 размер. (Для этого можно также использовать клавишу Ctrl-F5).

      Выберите Window|Size/Move  и  с  помощью  клавиш  управления
 курсором переместите активное окно (окно стека)  в  другое  место
 экрана.   Держа   нажатой  клавишу  Shift,  с  помощью  клавиш  с
 изображением  стрелок  измените  размер  этого  окна.  Когда   вы
 получите окно,  местоположение и размеры которого вас устраивают,
 нажмите клавишу Enter.

      Теперь, чтобы подготовиться  к  чтению  следующего  раздела,
 удалите с экрана окно стека, нажав Alt-F3. В зависимости от того,
 какую демонстрационную программу вы загрузите в отладчик  (на  Си
 или  на  Паскале),  переходите  либо к следующему разделу (пример
 программы  на  Си),  либо  к  разделу  c  примером  программы  на
 Паскале.
                     Отладка примера программы на языке Си                     
 -----------------------------------------------------------------

      В первом столбце  окна  модуля  высвечивается  стрелка  (>),
 которая  показывает,  на  какой  строке  Turbo Debugger остановил
 выполнение программы.  Поскольку вы еще не  запускали  программу,
 стрелка  стоит  на  ее первой строке.  Нажмите клавишу F7,  чтобы
 выполнить  одну  строку  исходного  текста.  Стрелка   и   курсор
 переместятся на вторую исполняемую строку программы.

      Обратите внимание  на  правое поле заголовка окна модуля.  В
 нем указывается номер  строки,  в  которой  находится  курсор.  С
 помощью  клавиш  управления курсором переместите его вверх-вниз и

 = 49 =

 посмотрите, как меняется номер строки в заголовке окна.

      Из меню Run можно увидеть,  что имеется  несколько  способов
 управления  выполнением  программы.  Допустим,  вы хотите,  чтобы
 выполнение программы было остановлено на строке 39.

      Прежде всего,  позиционируйте курсор на строку 39,  а  затем
 нажмите  клавишу F4.  По этой команде программа будет выполняться
 до (но не включая) строки 39.  Теперь нажмите клавишу F7. По этой
 команде  будет  выполнена одна строка исходного текста;  в данном
 случае будет выполнена строка 38 - вызов функции showargs. Курсор
 моментально перескочит на строку 151,  где начинается определение
 функции  showargs.  Продолжая  нажимать  клавишу  F7,   выполните
 последовательно  все  операторы  этой  функции.  После  этого  вы
 вернетесь на строку,  следующую за  вызовом  функции  showargs  -
 строку 40.  Нажмите Alt-F8 для останова программы при возврате из
 showargs.  Возврат также произойдет на  строку  40.  Эта  команда
 очень полезна для перехода за конец функции.

      Если, находясь  на  строке  39,  вместо  клавиши  F7  нажать
 клавишу F8, курсор сразу же перейдет на строку 40, а не на начало
 функции.  Команда F8, так же, как и F7, выполняет функцию, но без
 входа в нее.

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

 Задание точек останова   ----------------------------------------

      Еще один  способ   указания   места,   на   котором   должна
 остановиться  программа,  заключается  в установке точки останова
 (breakpoint).  Самый  простой  способ  установки  точки  останова
 состоит в использовании клавиши F2.  Переместите курсор на строку
 44 и нажмите клавишу  F2.  Turbo  Debugger  выделит  эту  строку,
 показывая, что на ней установлена точка останова.

      Если у  вас  имеется  "мышь",  то вы можете нажать кнопку на
 первых двух столбцах окна Module,  что  приводит  к  переключению
 точек останова.

      Теперь нажмите   клавишу  F9,  чтобы  продолжить  выполнение
 программы без прерывания.  Экран переключится на вывод программы.
 Теперь демонстрационная программа работает и ожидает ввода строки
 текста.  Введите abc, пробел, def, а затем нажмите клавишу Enter.
 Экран  переключится  обратно на среду отладчика,  и стрелка будет

 = 50 =

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

      Подробное описание  точек  останова,  включая   условные   и
 глобальные точки останова, приведено в главе 7.

 Использование окна слежения   -----------------------------------

      В окне  слежения  (Watches),  расположенном  в  нижней части
 экрана,   отображаются   указанные   пользователем    переменные.
 Например,  для  того  чтобы  проследить  за  значением переменной
 nwords,  позиционируйте курсор на имя этой переменной в строке 42
 и нажмите клавиши Ctrl-W.

      Если у  вас  имеется  "мышь",  то вы можете нажать кнопку на
 Ctrl-W в строке состояния.

      Переменная nwords появится в окне слежения  в  нижней  части
 экрана  вместе  со своим типом (unsigned int - целое без знака) и
 значением.  По мере выполнения программы значение в окне слежения
 будет обновляться, отражая текущее значение переменной.

 Проверка простых объектов данных Си-программы   -----------------

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

      Команды проверки  (в  разных  локальных  меню и в меню Data)
 позволяют проверять любые указанные переменные.  Предположим,  вы
 хотите   проверить  значение  переменной  nlines.  Позиционируйте
 курсор так,  чтобы он находился под одной из букв слова nlines, и
 нажмите  клавиши  Ctrl-I.  На  экране  раскроется  окно  проверки
 (Inspector).

      В заголовке указано имя переменной; во второй строке показан
 ее адрес в памяти.  В третьей строке показано, какого типа данные
 хранятся в переменной nlines (это тип int языка  Си).  Справа  от
 типа данных показано текущее значение переменной.

      Теперь, проверив  переменную,  нажмите  клавишу  Esc,  чтобы
 закрыть окно проверки.  Для удаления окна проверки (как и  любого
 другого окна) можно также использовать клавишу Alt-F3.

      Давайте еще раз повторим то, что было сделано. Нажав клавишу
 Ctrl,  вы  получаете  в  нижней  строке  экрана  перечень  команд
 локального  меню  окна  модуля.  Нажав  клавишу  I,  вы выбираете
 команду Inspect.

 = 51 =


      Для того   чтобы   проверить   элемент    данных,    который
 отображается   в   окне   модуля   в  неудобной  форме,  выберите
 Data|Inspect.  На экране появится блок диалога,  в  которое  надо
 ввести  имя  переменной  для  проверки.  Введите имя letterinfo и
 нажмите  клавишу  Enter.  На  экране  появится   окно   проверки,
 показывающее  значения элементов массива letterinfo.  В заголовке
 окна проверки указано  имя  переменной,  которую  вы  проверяете,
 точно в таком же виде, как она описана в программе. Первая строка
 после заголовка окна  содержит  адрес  первого  элемента  массива
 letterinfo   в  основной  памяти.  С  помощью  клавиш  управления
 курсором можно просмотреть все 26 элементов массива letterinfo. В
 следующем разделе показано, как проверять такие сложные структуры
 данных.

 Проверка составных объектов данных Си-программы  ----------------

      Составные объекты данных,  такие как  массивы  и  структуры,
 состоят из нескольких элементов.  Переместите курсор к четвертому
 элементу массива  letterinfo  (элементу  с  номером  [3]).  Нажав
 клавиши Alt-F10,  вызовите локальное меню окна проверки,  а затем
 нажав клавишу I, выберите из него команду Inspect (проверить). На
 экране  появится  новое  окно  проверки,  показывающее содержимое
 данного  элемента  массива.  В  этом  окне  показано   содержимое
 структуры типа linfo.

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

      Нажмите клавиши  Alt-F3,  чтобы  удалить оба окна проверки и
 вернуться в окно  модуля.  (Это  удобный  способ  удаления  сразу
 нескольких  окон  проверки.  Если  бы  вы нажали клавишу Esc,  то
 удалилось бы только последнее окно проверки.)

 Изменение значений переменных си-программы   --------------------

      До сих пор мы рассматривали только способы  просмотра данных
 в программе. Теперь давайте изменим значение элемента данных.

      С помощью  клавиш  управления курсором перейдите к строке 38
 исходного текста.  Поместите курсор на переменную totalcharacters
 и нажмите клавиши Ctrl-I,  чтобы проверить эту переменную.  После
 того, как откроется окно проверки, нажмите клавиши Alt-F10, чтобы
 вызвать локальное меню окна проверки и выберите опцию Change (или
 нажмите клавишу C).  Появится поле запроса, в которое надо ввести
 новое значение переменной.

      В ответ  на  этот  запрос  вы  можете ввести любое выражение

 = 52 =

 языка Си,  в  котором  вычисляется  некоторое  значение.  Введите
 выражение  totalcharacters+4 и нажмите клавишу Enter.  Значение в
 окне проверки станет равным 10L (0xA).

      Для того чтобы изменить значение элемента данных, который не
 отображается   в   окне  модуля,  выберите  Data|Evaluate/Modify.
 Появится поле запроса,  в которое  надо  ввести  имя  переменной,
 значение которой необходимо изменить.  Введите имя argc и нажмите
 Enter.  Затем дважды нажмите клавишу Tab, чтобы перейти в строку,
 помеченную  как  New Value (новое значение).  Введите число 123 и
 нажмите  Enter.  Целочисленный  результат  (во   второй   строке)
 изменится и станет равным int 123 (0x7B).

      Это было  краткое  введение  в использование отладчика Turbo
 Debugger для отладки программы на  языке  Turbo  C.  В  главе  14
 рассматривается  более  сложный пример сеанса отладки,  в котором
 используется версия данной программы, содержащая ошибку.
                  Отладка примера программы на языке Паскаль                   
 -----------------------------------------------------------------

      В первом  столбце  окна  модуля  высвечивается  стрелка (>),
 которая показывает,  на какой  строке  Turbo  Debugger  остановил
 выполнение  программы.  Поскольку  вы еще не запускали программу,
 стрелка стоит на ее первой  строке.  Нажмите  клавишу  F7,  чтобы
 выполнить   одну   строку  исходного  текста.  Стрелка  и  курсор
 переместятся на вторую исполняемую строку программы.

      Обратите внимание на правое поле заголовка  окна  модуля.  В
 нем  указывается  номер  строки,  в  которой находится курсор.  С
 помощью клавиш управления курсором переместите его вверх и вниз и
 посмотрите, как меняется номер строки в заголовке окна.

      Для того   чтобы   выполнить   программу   до   строки  221,
 позиционируйте  курсор  на  эту  строку  и  нажмите  клавишу  F4.
 Программа  TPDEMO  попросит вас ввести строку.  Введите несколько
 букв и нажмите клавишу Enter.  Теперь, когда курсор установлен на
 строке 221,  нажмите клавишу F7,  чтобы выполнить эту одну строку
 исходного текста.  Поскольку в этой строке содержится  вызов  еще
 одной  процедуры,  стрелка переместится к первой строке процедуры
 ProcessLine.Продолжая нажимать F7,  вы можете пошагово  выполнить
 функцию  ProcessLine  и  вернуться к строке после вызова - строке
 224..  Нажмите  клавиши  Alt-F8,  чтобы   остановить   выполнение
 программы  после  возврата из процедуры ProcessLine.  Эта команда
 очень удобна в том случае,  если желательно сразу перейти в конец
 процедуры или функции.

      Если в строке 221 вместо F7 нажать F8, курсор вместо функции
 перейдет непосредственно в строку 224. F8 аналогична клавише F7 в
 том, что она выполняет функцию, но не по шагам исходного кода.


 = 53 =

      Для того чтобы выполнить программу до  какого-то конкретного
 места,  можно  напрямую указать имя функции или номер строки,  не
 перемещая  курсор  к  этой  строке  исходного  текста,  а   затем
 запустить  программу.  Для  задания метки,  на которой необходимо
 остановить  выполнение  программы,  нажмите  клавиши  Alt-F9.  На
 экране появится поле запроса.  Введите с клавиатуры имя GetLine и
 нажмите Enter.  Программа  начнет  выполняться  и  остановится  в
 начале функции GetLine.

 Задание точек останова   ----------------------------------------

      Еще один   способ   указания   места,   на   котором  должна
 остановиться программа,  заключается в установке  точки  останова
 (breakpoint).  Самый  простой  способ  установки  точки  останова
 состоит в использовании клавиши F2.  Переместите курсор на строку
 121  и  нажмите  клавишу  F2.  Turbo Debugger выделит эту строку,
 показывая, что на ней установлена точка останова.

      Если у вас имеется "мышь",  то вы можете  нажать  кнопку  на
 двух первых столбцах окна Window для переключения точек останова.

      Теперь нажмите   клавишу  F9,  чтобы  продолжить  выполнение
 программы без прерывания.  Экран переключится на вывод программы.
 Теперь демонстрационная программа работает и ожидает ввода строки
 текста.  Введите abc, пробел, def, а затем нажмите клавишу Enter.
 Экран  переключится  обратно на среду отладчика,  и стрелка будет
 находиться на строке 121,  где вы установили точку  останова,  на
 которой  было  остановлено выполнение программы.  Теперь повторно
 нажмите F2 для ее отмены.

      Подробное описание  точек  останова,  включая   условные   и
 глобальные точки останова, приведено в главе 7.

 Использование окна слежения   -----------------------------------

      В окне  слежения  (Watches),  расположенном  в  нижней части
 экрана,   отображаются   указанные   пользователем    переменные.
 Например,  для  того  чтобы  проследить  за  значением переменной
 NumWords,  позиционируйте курсор на имя этой переменной в  строке
 144 и нажмите клавиши Ctrl-W (сокращенная форма команды Alt-F10
 локального меню).

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

      Переменная NumWords  появится в окне слежения в нижней части
 экрана  вместе  со  своим  типом  (word)  и  значением.  По  мере
 выполнения  программы значение в окне слежения будет обновляться,
 отражая текущее значение переменной.

 Проверка простых объектов данных паскаль-программы   ------------

 = 54 =


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

      Команды проверки (в разных локальных меню  и  в  меню  Data)
 позволяют проверять любые указанные переменные.  Предположим,  вы
 хотите проверить  значение  переменной  NumLines.  Позиционируйте
 курсор  на  строку 121 так,  чтобы он находился под одной из букв
 слова NumLines,  и нажмите клавиши Ctrl-I.  На экране  раскроется
 окно проверки (Inspector).

      В первой  строке  окна  указано  имя  переменной;  во второй
 строке - ее адрес в памяти.  В третьей  строке  показано,  какого
 типа  данные  хранятся  в переменной NumLines (это тип word языка
 Паскаль).  Справа  от  типа  данных  показано  текущее   значение
 переменной.

      Теперь, проверив  переменную,  нажмите  клавишу  Esc,  чтобы
 закрыть окно проверки.  Для удаления окна проверки (как и  любого
 другого окна) можно также использовать клавишу Alt-F3.

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

      Для того   чтобы   проверить   элемент    данных,    который
 отображается в окне модуля в неудобной форме, нажмите клавиши Alt
 -D I.  На экране появится поле запроса, в которое надо ввести имя
 переменной  для  проверки.  Введите  имя  LetterTable  и  нажмите
 клавишу Enter.  На экране появится  окно  проверки,  показывающее
 значения   элементов   массива   LetterTable.  С  помощью  клавиш
 управления курсором можно просмотреть все  26  элементов  массива
 LetterTable.  В  заголовке  окна проверки указано имя переменной,
 которую вы проверяете,  точно в таком же виде,  как она описана в
 программе.  В  следующем  разделе  показано,  как проверять такие
 сложные структуры данных.

 Проверка составных объектов данных паскаль-программы   ----------

      Составные объекты данных,  такие как  массивы  и  структуры,
 состоят из нескольких элементов.  Переместите курсор к четвертому
 элементу  массива  LetterTable  (элементу  [D]).  Нажав   клавиши
 Alt-F10,  вызовите  локальное  меню окна проверки,  а затем нажав
 клавишу I,  выберите из  него  команду  Inspect  (проверить).  На
 экране  появится  новое  окно  проверки,  показывающее содержимое
 данного элемента массива.  В этом окне показано содержимое записи
 типа LInfoRec.

 = 55 =


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

      Нажмите клавишу Alt-F3,  чтобы удалить оба окна  проверки  и
 вернуться  в  окно  модуля.  (Это  удобный  способ удаления сразу
 нескольких окон проверки.  Если бы  вы  нажали  клавишу  Esc,  то
 удалилось бы только последнее окно проверки.)

 Изменение значений переменных паскаль-программы    --------------

      До сих пор мы рассматривали только способы  просмотра данных
 в программе. Теперь давайте изменим значение элемента данных.

      С помощью  клавиш управления курсором перейдите к строке 103
 исходного текста.  Поместите курсор на  переменную  NumLetters  и
 нажмите  клавиши  Ctrl-I,  чтобы проверить эту переменную.  После
 того, как откроется окно проверки, нажмите клавиши Alt-F10, чтобы
 вызвать локальное меню окна проверки.  Выберите опцию Change (или
 нажмите клавишу C). (То же можно было сделать, нажав клавиши Ctrl
 -C.) Появится поле запроса,  в которое надо ввести новое значение
 переменной.

      В ответ на этот запрос  вы  можете  ввести  любое  выражение
 языка Паскаль,  в котором вычисляется некоторое значение. Введите
 выражение NumLetters+4 и нажмите клавишу Enter.  Значение в  окне
 проверки станет равным 10.

      Для того чтобы изменить значение элемента данных, который не
 отображается  в  окне  модуля,   выберите   Data|Evaluate/Modify.
 Появится  поле  запроса,  в  которое  надо ввести имя переменной,
 значение которой необходимо  изменить.  Введите  имя  NumLines  и
 нажмите  Enter.  Результат отображается в среднем подокне.  Затем
 дважды нажмите клавишу Tab,  введите число 123 и  нажмите  Enter.
 Значение переменной NumLines станет равным 123.

      Это было  краткое  введение  в использование отладчика Turbo
 Debugger для отладки программы на языке Turbo Pascal.  В главе 14
 рассматривается более сложный пример отладки.




 = 56 =

                                                                               
ГЛАВА 4  ЗАПУСК ОТЛАДЧИКА TURBO DEBUGGER

      В этой  главе  рассказано,  как  подготавливать  программы к
 отладке,  как запускать Turbo Debugger из командной строки DOS  и
 как использовать ее многочисленные параметры командной строки при
 отладке  программ.  Объясняется,  как   сделать   эти   параметры
 постоянными,  используя  файл  конфигурации.  Вы  также научитесь
 запускать  командный  процессор  операционной  системы   DOS   из
 отладчика и возвратиться в DOS после окончания отладки.
                         Подготовка программ к отладке                         
 -----------------------------------------------------------------

      При компиляции и компоновке программы одним  из компиляторов
 семейства   Turbo  фирмы  Borland  необходимо,  чтобы  компилятор
 сформировал  всю  информацию,  требующуюся  для   отладки.   Если
 объектные  модули  программы  уже  были  скомпилированы без такой
 информации, их необходимо перекомпилировать в режиме формирования
 полной  информации для отладки всей программы на уровне исходного
 текста. Можно, конечно, сформировать отладочную информацию только
 для каких-то отдельных модулей, однако позже загрузка модулей, не
 имеющих  отладочной  информации,  может   доставить   вам   много
 неприятностей.  Мы  рекомендуем  вам перекомпилировать все модули.

 Подготовка программ на языке Turbo C

      Если вы  используете  интегрированную  среду Turbo ++C (TC),
 откройте блок  диалога  Debugger  (выберите  Options|Debugger)  и
 установите селективную   клавишу  Source  Debugging  в  положение
 Standalone, прежде чем компилировать исходные модули. Для Turbo С
 2.0 установите Debugg|Source в Standalone.

      Если вы  используете  автономный  компилятор (TCC),  задайте
 параметр -v командной строки.

      Если вы используете автономный компоновщик TLINK,  вы должны
 задать параметр /v, чтобы добавить информацию для отладки в конец
 файла типа EXE.

      Возможно, вы также захотите убедиться в  том,  что  запрещен
 режим  оптимизации  кода.  Не  используйте  опцию  -O или задайте
 параметр -O-  в  файле  конфигурации  TURBOC.CFG  для  выключения
 режима  оптимизации.   Это  предотвратит  ситуации,  когда  Turbo
 Debugger будет  перескакивать  через  несколько  строк  исходного
 текста при пошаговой отладке программы.

 Подготовка программ на языке Turbo Pascal

      Прежде всего,   следует   иметь   в   виду,  что  необходимо
 использовать  версию  5.0  компилятора  Turbo  Pascal  или  более
 позднюю.  В  более  ранних  версиях  не предусмотрена возможность

 = 57 =

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

      Если вы  используете  интегрированную среду (TURBO.EXE),  вы
 должны вызвать меню Debug и установить ключ  Standalone Debugging
 в  состояние  On  (разрешена  автономная  отладка).  Кроме  того,
 установите ключ Options/Compiler/Debug Information в состояние On
 (включен    режим   формирования   отладочной   информации)   или
 используйте директиву компилятора {$L+}.  Если  вы  хотите  иметь
 возможность  ссылаться  на  локальные  идентификаторы  (описанные
 внутри процедур  и  функций),  вы  должны  либо  установить  ключ
 Options/Compiler/Local   Symbols  в  состояние  On  (формирование
 информации о локальных идентификаторах), либо поместить директиву
 компилятора   в   начало   своей  программы.  После  этого  можно
 компилировать программу.

      Следующим образом, без пробелов:

      {$L+}


      Если вы  пользуетесь  версией  компилятора,  вызываемого  из
 командной строки (TPC.EXE),  вы должны скомпилировать  программу,
 задав  параметр  /v командной строки.  В этом режиме по умолчанию
 формируется  как  отладочная  информация,  так  и  информация   о
 локальных   идентификаторах.   Если   это   не  требуется,  можно
 использовать параметр /$, который выключает этот режим.

 Подготовка программ на языке Turbo Assembler

      Если программа написана на языке  Turbo  Assembler,  задайте
 параметр  -zi  командной  строки,  включающий  режим формирования
 полной отладочной информации.

      При компоновке  программы  с  помощью   компоновщика   TLINK
 используйте  параметр  /v  для добавления отладочной информации в
 конец файла типа EXE.

 Подготовка программ на языке фирмы Microsoft

      На дистрибутивных дискетах приведена информация о  том,  как
 использовать     утилиту    TDCONVRT.EXE,    которая    выполняет
 преобразование исполняемых программ,  написанных  для  отладки  в
 системе CodeVeiw, в формат отладчика Turbo Debugger.
                        Запуск программы Turbo Debugger                        
 -----------------------------------------------------------------

      Для того чтобы запустить отладчик Turbo Debugger,  следует в
 ответ на приглашение операционной системы DOS ввести с клавиатуры
 команду TD с необязательным набором аргументов  командной строки,

 = 58 =

 а  затем  нажать  клавишу  Enter.  Turbo  Debugger  загрузит вашу
 программу и выведет ее исходный код таким образом, чтобы вы могли
 последовательно,   оператор   за   оператором,  наблюдать  за  ее
 выполнением.

      В общем виде командная строка для  запуска  отладчика  имеет
 следующий вид:

      TD [параметры] [имя программы [аргументы программы]]

      Элементы, заключенные    в   квадратные   скобки,   являются
 необязательными;   если   вы   будете   использовать   какие-либо
 параметры,  вводите их без квадратных скобок. Имя программы - это
 название  программы,  которую  требуется  отладить.   За   именем
 программы  могут  стоять  ее аргументы.  Ниже приведено несколько
 примеров командной строки.

 ------------------------------------------------------------------
    Команда                       Действие
 ------------------------------------------------------------------
 td -sc prog1 a b    Запускает отладчик с параметром -sc и
                     загружает программу prog1 с двумя аргументами:
                     a и b.
 td prog2 -x         Запускает отладчик с параметрами,
                     установленными по умолчанию, и загружает
                     программу prog2 с одним аргументом -x.
 ------------------------------------------------------------------

      Если просто   ввести  TD  и  нажать  Enter,  Turbo  Debugger
 загрузит и будет использовать параметры,  установленные в нем  по
 умолчанию.

      Заметим, что при запуске отладчика Turbo Debugger необходимо
 иметь  как  файл  типа  EXE,  так  и  исходные  файлы  с  текстом
 программы.  Turbo  Debugger  сначала ищет исходные файлы в той же
 директории,  где  находил  их  компилятор  во  время   компиляции
 программы, затем в директории, заданной командой Options/Path for
 Source (маршрут для исходных файлов), затем в текущей директории,
 а затем в директории, где находится файл типа EXE.

      Прежде чем  использовать отладчик Turbo Debugger, необходимо
 скомпилировать исходный текст программ в исполняемый  файл  (файл
 типа EXE) в режиме формирования полной отладочной информации.

      Для того чтобы отлаживать программу,  написанную на одном из
 языков фирмы Borland, необходимо использовать Turbo Pascal версии
 5.0  или  более  поздней,  Turbo  C версии 2.0 или более поздней,
 Turbo Assembler версии 1.0 или более поздней.

      Если вы запустили программу по приглашению  DOS  и  заметили
 ошибку, нужно выйти из этой программы и загрузить ее в отладчике,

 = 59 =

 что даст вам возможность ее отладки.

                          Параметры командной строки                           
 -----------------------------------------------------------------

      Все параметры командной строки начинаются с символа переноса
 (- ) и отделяются от команды TD и друг от друга как минимум одним
 пробелом.  Для  того чтобы отменить какой-либо параметр командной
 строки,  надо поставить после  него  еще  один  символ  переноса.
 Например,   параметр   -vg-  отменяет  режим  сохранения  полного
 графического образа вывода программы.  Это можно  сделать  в  том
 случае,  если  данный  режим  был  установлен  постоянно  в файле
 конфигурации.  Файл  конфигурации  можно   изменить   с   помощью
 программы TDINST, описанной в приложении D.

      Доступный список  параметров командной строки Turbo Debugger
 приводится в Приложении А.

      Ниже приведено описание всех допустимых параметров командной
 строки.

 Загрузка файла конфигурации (параметр -c)

      Задав этот   параметр,   можно   загрузить   указанный  файл
 конфигурации.  Между параметром -c и именем файла не должно  быть
 пробела.

      Если параметр  -c  не  задан,  загружается файл TDCONFIG.TD,
 если он существует.

      Ниже приведен пример использования этого параметра.

      TD -cMYCONF.TD TCDEMO

      Эта команда загружает файл конфигурации MYCONF.TD и исходный
 текст программы TCDEMO.

 Параметры управления обновлением дисплея (-d)

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

 Параметр -do
 ------------

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

 Параметр -dp
 ------------

 = 60 =


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

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

 Параметры получения помощи -h и -?

      Отображают на экране текст подсказки, описывающий назначение
 и синтаксис параметров командной строки отладчика Turbo Debugger.

 Параметр переключения идентификатора процесса (-i)

      Разрешает переключение    идентификатора    процесса.     Не
 используйте   этот  параметр  при  отладке  в  среде  ДОС  и  при
 использовании системных вызовов ДОС.  Более подробная  информация
 об   этом   параметре  приведена  в  приложении  В.  При  отладке
 большинства программ этот параметр не требуется.

 Параметр записи нажатий клавиш (-k)

      Позволяет запись  нажатий   клавиш   в   подокне   Keystroke
 Recording окна Execution History.

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

 Запуск ассемблерного режима (-l)

      Запускает Turbo   Debugger   в   режиме  отладки  на  уровне
 ассемблера,  отображая  информацию  о  процессоре.  При  этом  не

 = 61 =

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

 Установка размера "кучи" (-m)

      Устанавливает размер  рабочей  динамической области равным n
 килобайт. Записывается в следующем виде:

      -mn

      где n - это число килобайт.  Между параметром -m и  размером
 динамической области не должно быть пробела. Пример использования
 этого параметра:

      TD -m10 TCDEMO

      По умолчанию размер динамической области равен  18К.  Нижняя
 граница равна 7К.  Если требуется память, можно использовать этот
 параметр   для   уменьшения   размера    динамической    области,
 используемой  отладчиком  Turbo  Debugger.  При отладке небольших
 программ этот параметр можно использовать для  увеличения размера
 динамической    области.    Это   позволяет   отладчику   хранить
 промежуточную  информацию,  такую  как  списки  введенных   ранее
 команд.

      Примечание: Если  с  помощью  параметра  -m  указать  размер
 динамической области равный нулю (-m0),  то Turbo Debugger  будет
 использовать максимальный размер, равный обычно 18К.

 Поддержка мыши (-p)

      Данный параметр включает поддержку мыши.  Однако,  поскольку
 по умолчанию для Turbo Debugger поддержка мыши  включена,  -p  не
 имеет значения,  если  только  это умолчание не было изменено при
 помощи TDINST. отменить поддержку мыши можно при помощи -p-.

 Параметры удаленной отладки (r)

      Все параметры -r связаны с отладкой на удаленной системе.

 Параметр -r
 -----------

      Разрешает производить    отладку   на   удаленной   системе,
 связанной   по   последовательному   интерфейсу.   По   умолчанию
 используется  последовательный  порт  COM1  и  скорость  передачи
 115 Кбод, если программой TDINST не заданы другие параметры.

 Параметр -rp N

 = 62 =

 --------------

      Устанавливает номер  порта для отладки на удаленной системе.
 N может быть равно 1 или 2, задавая COM1 и COM2 соответственно.

 Параметр -rs N
 --------------

      Устанавливает скорость  передачи  для  отладки  на удаленной
 системе.  N может быть равно 1 (9600 бод), 2 (40 Кбод) или 3 (115
 Кбод).

 Параметры обращения с исходным кодом (s)

      Эти параметры  определяют  способ обработки отладчиком Turbo
 Debugger исходного текста и идентификаторов программы.

 Параметр -sc
 ------------

      Обрабатывает идентификаторы  без  учета регистра,  даже если
 компоновка программы была выполнена с учетом регистра.

      Если параметр   -sc   не   задан,   Turbo   Debugger   будет
 обрабатывать  текст  программы  без  учета  регистра только в том
 случае,  если программа была скомпонована  с  включенным  режимом
 учета регистра.

      Примечание: Этот  параметр  не  влияет на отладку программы,
 написанной на языке  Turbo  Pascal  (поскольку  компилятор  Turbo
 Pascal всегда обрабатывает исходный текст без учета регистра).

 Параметр -sd
 ------------

      Задает одну  или  несколько  директорий,  в  которых   Turbo
 Debugger  будет  искать исходные файлы;  записывается в следующем
 формате:

      -sd <имя директории>

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

 Параметр -smN

 = 63 =

 --------------

      Данный параметр устанавливает размер  памяти,  резервируемой
 для таблицы   символических   имен.   За  ним  следует  размер  в
 килобайтах области резервируемой памяти:

      -smN

      где N - это число килобайт.  Эта опция используется, если вы
 хотите загрузить  таблицу  символических  имен вручную при помощи
 команды File|Symbol  Table.  Вы  можете  поэкспериментировать   с
 размером резервируемой таким образом памяти.


 Параметры видеоаппаратуры (-v)

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

 Параметр -vg
 ------------

      Сохраняет полный   графический   образ   экрана   выполнения
 программы.   Требует   дополнительно   8К  памяти,  но  позволяет
 отлаживать программы,  использующие некоторые графические  режимы
 отображения.  Попробуйте  использовать  этот  параметр,  если при
 отладке программы в системе Turbo Debugger  портится  формируемое
 ею графическое изображение.

 Параметр -vn
 ------------

      Запрещает использование  режима  отображения  43/50   строк.
 Задание  этого  параметра  экономит  некоторое количество памяти.
 Задавайте  его  в  том  случае,  если  вы  используете  EGA   или
 VGA-монитор  и  знаете,  что  во время работы с отладчиком вам не
 потребуется переходить в режим 43/50 строк.

 Параметр -vp
 ------------

      Разрешает сохранение палитры EGA.


 Параметры размера оверлейного пула (-y)

      Опции -y  используются  для  установки  размера  оверлейного
 пула, как в основной памяти так и в расширенной (EMS) памяти.

 Параметр -yN
 ------------

 = 64 =

      Данный параметр  устанавливает  размер  оверлейного  пула  в
 основной памяти. Синтаксис этого параметра следующий:

      -yN

      где N - это размер пула в килобайтах.  Обычно Turbo Debugger
 использует размер  пула  80К.  Минимальный  размер  пула  20К,  а
 максимальный 200К.

      Для установки   размера   постоянного    оверлейного    пула
 используется TDINST.

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

 Параметр -yeN
 -------------

      Данный параметр  устанавливает  размер  оверлейного  пула  в
 расширенной (EMS) памяти. Эта опция используется для освобождения
 части EMS-памяти  для  отлаживаемой  программы.  Синтаксис  этого
 параметра следующий:

      -yeN

      где N  -  это  число  страниц EMS-памяти по 16К,  которое вы
 желаете зарезервировать.  Например, -ye4 резервирует пул размером
 в 4   страницы.   По  умолчанию  устанавливается  размер  пула  в
 двенадцать 16К-байтовых страниц EMS-памяти.

      Для отмены оверлейного пула EMS служит параметр -ye0.
                              Файлы конфигурации                               
 -----------------------------------------------------------------

      Файл конфигурации используется отладчиком Turbo Debugger для
 изменения значений параметров командной строки,  установленных по
 умолчанию.  Вы  можете  использовать программу TDINST для задания
 значений,  которые  будут  использоваться  по  умолчанию   (когда
 отсутствует    файл   конфигурации),   и   для   создания   файла
 конфигурации.

      Turbo Debugger ищет файл конфигурации TDCONFIG.TD  сначала в
 текущей  директории,  затем  в  системной  директории  отладчика,
 заданной с  помощью  программы  TDINST,  а  затем  в  директории,
 содержащей  файл  TD.EXE.  Если  вы  работаете  в  DOS  версии 2,

 = 65 =

 отладчик  не  будет  искать  файл   TDCONFIG.TD   в   директории,
 содержащей файл TD.EXE.

      Если отладчик находит файл конфигурации,  значения, заданные
 в этом файле,  заменяют значения, установленные по умолчанию. Все
 параметры   командной   строки,   которые  задаются  при  запуске
 отладчика  Turbo  Debugger  из  DOS,   заменяют   соответствующие
 параметры,  установленные  по  умолчанию и параметры,  заданные в
 файле TDCONFIG.TD.

      В приложении D описано, как использовать программу настройки
 TDINST для создания файлов конфигурации.
                                 Меню Options                                  
 -----------------------------------------------------------------

      Меню Options позволяет задать или настроить  ряд параметров,
 которые  влияют  на работу отладчика Turbo Debugger.  В следующих
 разделах описаны все команды  этого  меню  и  даются  необходимые
 ссылки  на  другие  разделы данного руководства,  где можно найти
 более подробную информацию.

      ---------------------
      Language...    Source
      Macros              >
      Display options...
      Path for source...
      Save options...
      Restore options...
      ---------------------

 Команда Language (язык)

      В главе  9 описано,  как установить язык выражений и как это
 влияет на способ ввода выражений.


 Меню Macros

      --------------------
      Create          Alt=
      Stop Recording  Alt-
      Remove
      Dalete all
      --------------------

      Команда Macros отображает  другое  меню,  которое  позволяет
 определять новые макросы и удалять те, которые уже были назначены
 некоторой клавише.  Команды этого  подменю  описаны  в  следующих
 разделах (Create, Stop, Recording и Delete All).


 = 66 =

 Команда Create (создать)
 ------------------------

      Начинает запись последовательности нажатия  клавиш,  которой
 будет назначена некоторая клавиша (например, Alt-M). Прежде всего
 отладчик попросит вас нажать  клавишу,  которой  будет  назначена
 последовательность нажатий клавиш. Затем вам надо последовательно
 нажать все клавиши,  которые необходимо записать в виде  макроса.
 Эти нажатия клавиш будут восприниматься отладчиком Turbo Debugger
 точно так же, как если бы вы не записывали макрос. Для того чтобы
 начать  запись  макроса,  выберите команду Options|Macros|Create.
 Отладчик попросит нажать клавишу,  по которой  будет  выполняться
 вызов макроса.  Пока будет идти запись макроса,  в верхнем правом
 углу  экрана  будет  высвечиваться  надпись  Recording  (запись).
 Нажатия  клавиш  будут при этом восприниматься Turbo Debugger так
 же, как если бы записи макроса не происходило.

      Когда запись  макроса  будет  закончена,  выполните  команду
 Options|Macros|Stop Recording или нажмите ее активные клавиши Alt
 -"знак переноса".  Вы также можете  еще  раз  нажать  назначенную
 макросу клавишу (Alt-M).

      Alt= является   активной   клавишей  команды  начала  записи
 макроса.

 Команда Stop Recording (закончить запись)
 -----------------------------------------

      Заканчивает запись    последовательности   нажатий   клавиш,
 которая  будет  назначена  некоторой  клавише.  Используйте   эту
 команду  после  выполнения  команды     Options|Macros|Create для
 того, чтобы назначить макрос указанной клавише.

      Активными клавишами этой команды являются  клавиши Alt-"знак
 переноса".

 Команда Remove (удалить)
 ------------------------

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

 Команда Delete All (удалить все макросы)
 ----------------------------------------

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

 Команда Display options (параметры дисплея)

      Данная команда    открывает    блок   диалога,   позволяющий

 = 67 =

 установить несколько  опций,  управляющих  видом  дисплея   Turbo
 Debugger.



 Display Swapping (переключение изображений)
 --------------------------------------------------

      Селективные кнопки Display Swapping позволяют задать один из
 трех  способов  управления  переключением  экрана  с   выполнения
 программы   на  среду  отладчика  и  обратно.  Возможен  один  из
 следующих вариантов:

      None           Переключение экрана не производится.
      (никогда)      Используйте это значение в том случае, если
                     программа не выдает никакой информации на
                     экран.

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

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


 Integer Format (формат отображения целых чисел)
 ------------------------------------------------------

      Эти селективные   кнопки   позволяют  задать  один  из  трех
 форматов отображения целых чисел:

      Decimal                  Отображение целых чисел в обычном
      (десятичный)             десятичном формате

      Hex                      Отображение целых числе в
      (шестнадцатиричный)      шестнадцатиричном формате,
                               соответствующем текущему языку

 = 68 =


      Both                     Отображение целых чисел как в
      (оба формата)            десятичном формате, так и в
                               шестнадцатиричном (в круглых скобках
                               после десятичного значения).

 Screen Size (размер экрана)
 ----------------------------------

      Используйте эти  кнопки  для  задания  количества  строк  на
 экране в среде отладчика:  нормальное отображение в 25 строк  или
 отображение в 43/50 строк для EGA и VGA-мониторов.

 Tab Size (ширина табуляции)
 --------------------------------

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

 Команда Path for Source (путь доступа к исходным файлам)

      Задает директории,  в  которых  Turbo Debugger ищет исходные
 файлы.  Для получения более подробной информации об этой  команде
 обратитесь к главе 8, в которой описывается окно модуля.

 Команда Save Options (сохранить параметры)

      Записывает текущие параметры в файл конфигурации на диске. В
 файл записываются следующие параметры:

      - макросы;

      - конфигурация текущего окна;

      - все значения параметров, заданные в меню Options.


      Turbo Debugger  позволяет сохранять  значения параметров  тремя
 способами, в зависимости от установок  блоков  переключения  Save
 Configuration:

      Options        Сохранение всех установок, сделанных в меню
                     Options, включая окна и макросы

      Layout         Сохранение только конфигурации окон

      Macros         Сохранение только определенных к этому моменту
                     макросов.

 = 69 =



 Команда Restore Options (восстановить параметры)
 -----------------------------------------------------------------

      Восстанавливает значения параметров,  записанные в  дисковый
 файл.  Вы можете иметь несколько файлов конфигурации,  содержащих
 различные макросы, параметры окон и т.д. Можно задавать имя файла
 конфигурации,  который  был создан с помощью команды Save Options
 или DINST.
                                                                               
Временный выход в DOS в процессе отладки
 -----------------------------------------------------------------

      Иногда во время отладки программы бывает нужно выйти в DOS и
 запустить  другую  программу  или  утилиту.  Это  можно сделать с
 помощью команды File/OS Shell.

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

      Предупреждение: При  выходе  из  Turbo  Debugger  в  DOS  не
 загружайте резидентных программ.

      После окончания   выполнения  команд  операционной  системы,
 введите команду EXIT, чтобы вернуться в среду отладчика.
                                                                               
Возврат в DOS
 -----------------------------------------------------------------

      В любой момент,  нажав клавиши Alt-X,  вы  можете  завершить
 сеанс отладки и вернуться в DOS,  за исключением случая,  когда у
 вас имеется активный блок диалога (в этом случае сначала закройте
 этот блок, нажав Esc). Для этого также можно выбрать команду File
 /Quit.

      При этом  вся  память,  выделенная  отлаживаемой  программе,
 будет   освобождена.   Если   отлаживаемая  программа  использует
 подпрограммы блочного распределения памяти  операционной  системы
 DOS, то эта память также будет освобождена.




 = 70 =

              ГЛАВА 5  УПРАВЛЕНИЕ ПРОЦЕССОМ ВЫПОЛНЕНИЯ ПРОГРАММЫ               


      При отладке программы обычно выполняется какая-то ее часть и
 проверяется  правильность  ее  работы  в  текущей  точке.   Turbo
 Debugger   позволяет  управлять  процессом  выполнения  программы
 различными способами. Вы можете:

      - выполнить одну машинную команду или одну  строку исходного
 текста;

      -  выполнять вызовы процедур и функций, не входя в них;

      - включать   режим   "мультипликации"  отладчика  (выполнять
 непрерывную трассировку);

      - выполнять текущую процедуру  или  функцию  до  возврата  в
 вызвавшую ее программу;

      -  выполнять программу до конкретного места;

      -  выполнять программу до точки останова;

      - менять     направление     выполнения     программы     на
 противоположное.

      Сеанс отладки состоит  из  сменяющих  друг  друга  периодов,
 когда  работает  либо  программа,  либо отладчик.  Когда работает
 отладчик,  можно запустить отлаживаемую программу, выбрав одну из
 команд  меню  Run  или нажав ее активную клавишу.  Когда работает
 программа,  отладчик  запускается  вновь  либо  после  выполнения
 определенного  фрагмента  программы,  либо когда вы прерываете ее
 работу нажатием определенных клавиш,  либо когда  Turbo  Debugger
 встречает точку останова.

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

      Под "состоянием программы" понимается следующее:

      - значения аргументов программы, заданных в командной строке
 DOS;

      -  содержимое стека активных процедур и функций;


 = 71 =

      -  текущее положение в исходном тексте или машинном коде;

      -  значения регистров;

      -  содержимое памяти;

      -  причину, по которой отладчик прервал выполнение программы;

      -  значения переменных программы.

      В следующих   разделах   рассматривается   работа  с  окнами
 переменных  и  стека,  использование   локальных   меню   подокон
 глобальных и  локальных  переменных,  команд  Origin  и Get Info.
 Информацию о  том,  как   просматривать   и   изменять   значения
 переменных программы см. в Главе 6.

 Окно переменных (Variables)

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


      Примечание: При отладке программы, написанной на языке Turbo
 Pascal,  в переменные не будут организованы в алфавитном порядке.

      Окно Variables  открывается при помощи View|Variables.  Окно
 Variables имеет два подокна:

      - подокно  Global  (верхнее)   показывает   все   глобальные
 символические имена в программе.

      - подокно   Static   (нижнее)   показывает  все  статические
 символические имена текущего модуля (модуля, которому принадлежит
 текущий адрес  выполняемой программы,  CS:IP) и все символические
 имена, локальные относительно текущей функции.

      В обоих подокнах слева указывается имя переменной,  а справа
 -  ее  значение.  Если  Turbo  Debugger  не  может  найти никакой
 информации о типе данных для данного  идентификатора,  он  ставит
 справа от него четыре знака вопроса (????).

      Так же,  как для всех локальных меню,  для вызова локального
 меню подокна глобальных переменных надо нажать  клавиши  Alt-F10.
 Если  разрешено  использование  активных  клавиш  в  комбинации с
 клавишей Ctrl,  для выбора этой команды можно нажать клавишу Ctrl
 в сочетании с первой буквой данной команды.


 = 72 =

      Если в   программе   имеются   функции,   которые  выполняют
 рекурсивные вызовы,  либо если необходимо  просмотреть  локальные
 переменные   вызванной   функции,  то  можно  проверить  значение
 конкретного экземпляра локальных данных функции.  Для этого  надо
 открыть  окно  стека,  выполнив  команду View/Stack,  переместить
 выделяющий курсор  к  нужному  вызову  функции,  а  затем  нажать
 клавиши  Alt-F10 и выбрать команду Locals.  В подокне статических
 переменных окна переменных  будут  показаны  значения  для  этого
 конкретного экземпляра вызова функции.

 Локальное меню подокна глобальных переменных
 --------------------------------------------

      В этом  локальном  меню   имеется   две   команды:   Inspect
 (проверить) и Change (изменить).

      --------
      Inspect
      Change
      --------

 Команда Inspect
 ---------------

      Открывает окно  проверки  (Inspector),  в  котором  показано
 значение выбранной глобальной переменной. Работа с окном проверки
 более подробно описана в главе 6.

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

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

 Команда Change
 --------------

      Заменяет значение    выбранной    (выделенной)    глобальной
 переменной значением, которое вводит пользователь в блоке диалога
 Change. Turbo Debugger выполняет любое необходимое преобразование
 типов  данных  точно  так же,  как если бы для изменения значения
 использовался  оператор  присваивания  исходного   языка.   Более
 подробная информация о присваивании и преобразовании типов данных

 = 73 =

 приведена в главе 9.

      Кроме этого,  можно изменить значение выбранной  переменной,
 просто начав вводить новое значение. При этом появляется такое же
 поле запроса, как если бы сначала была выбрана команда Change.

 Локальное меню подокна статических переменных
 ---------------------------------------------

      Для вызова  локального  меню подокна статических переменных
 нажмите клавиши Alt-F10.  Если разрешено  использование  активных
 клавиш  в  комбинации  с  клавишей Crtl,  для выбора этой команды
 можно нажать клавишу Ctrl в  сочетании  с  первой  буквой  данной
 команды.

      В локальном  меню  подокна статических переменных имеются те
 же две команды: Inspect и Change.

      -----------
      Inspect
      Change
      -----------


 Команда Inspect
 ---------------

      Открывает окно проверки (Inspector),  в котором отображается
 значение выбранной локальной переменной  модуля.  Более  подробно
 работа с окном проверки описана в главе 6.

 Команда Change
 --------------

      Заменяет значение    выбранной    (выделенной)     локальной
 переменной значением, которое вводит пользователь в блоке диалога
 Change. Turbo Debugger выполняет любое необходимое преобразование
 типов  данных  точно  так же,  как если бы для изменения значения
 использовался  оператор  присваивания  исходного   языка.   Более
 подробная информация о присваивании и преобразовании типов данных
 приведена в главе 9.

      Кроме этого,  можно изменить значение выбранной  переменной,
 просто начав вводить новое значение. При этом появляется такое же
 поле запроса, как если бы сначала была выбрана команда Change.

 Окно стека (Stack)

      Окно стека открывается по  команде  F10/View/Stack.  В  этом
 окне приводится список всех активных процедур и функций. Первой в
 списке является последняя вызванная  подпрограмма,  за  ней  идет

 = 74 =

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


      Аналогичным образом   окно  Stack  выводит  имена  объектных
 правил или компонентных функций класса,  перед которыми выводятся
 имя объекта или тип класса, определяющий правило или компонентную
 функцию:

      SHAPES.ACIRCLE(174, 360, 75.0) (Turbo Pascal)

      Для вызова  локального  меню  окна  стека  нажмите   клавиши
 Alt-F10  или  клавишу  Ctrl  в  сочетании  с первой буквой нужной
 команды меню, чтобы сразу выполнить эту команду.

 Локальное меню окна стека
 -------------------------

      Локальное меню содержит две команды: Inspect и Locals.

      -------------
      Inspect
      Locals
      -------------

 Команда Inspect
 ---------------

      Открывает окно модуля (Module), расположенное возле активной
 строки выбранной функции.  Если выбранная функция является первой
 в  списке (вызвана последней),  в окне модуля указывается текущая
 точка подпрограммы (содержимое регистров CS:IP).  Если  выбранная
 функция   не   является   последней   вызванной   функцией,  окно
 располагается  возле   строки   этой   функции,   которая   будет
 выполняться  после  возврата  из  вызванной функции.

      Эту команду также можно вызвать, установив выделяющий курсор
 на нужную функцию и нажав клавишу Enter.

 Команда Locals
 --------------

      Открывает окно   переменных,   в  котором  показываются  все
 локальные  переменные  текущего   модуля,   а   также   локальные
 переменные выбранной функции.  Если какая-либо функция рекурсивно
 вызывает сама себя, в окне стека будет несколько экземпляров этой
 функции.  Установив  выделяющий курсор на один из вызовов,  можно
 просмотреть  значения  локальных  переменных  данного  экземпляра

 = 75 =

 функции.

 Команда Origin локального меню

      Окно модуля  и  подокно  кода  окна процессора имеют в своих
 локальных меню команду Origin. Эта команда позиционирует курсор в
 текущую  точку  программы,  которой  соответствует  значение пары
 регистров CS:IP.  Эта команда очень полезна в тех случаях,  когда
 вы  просматривали текст программы и хотите вернуться в точку, где
 было остановлено ее выполнение.

 Просмотр состояния выполнения программы: команда Get Info

      Команду Get Info можно использовать для получения информации
 об  использовании  памяти  и  о   причине   передачи   управления
 отладчику. Эта и другая информация отображается в отдельном окне,
 которое удаляется с экрана при нажатии любой клавиши. В этом окне
 отображается следующая информация:

      -  имя отлаживаемой программы;

      -  описание причин останова программы;

      - количество  памяти,   используемой   DOS,   отладчиком   и
 программой;

      - если имеется расширенная память, данные о ее использовании
 приводятся справа от информации об основной памяти;

      -  список прерываний, перехваченных отлаживаемой программой;

      -  версия операционной системы DOS, в которой вы работаете;

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


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


      Stoped at_ (остановлена на...)

      Программа была  остановлена в результате выполнения одной из
 команд:  Run/Execute To,  Run/Go to Cursor или Run/Until  Return.
 Это сообщение выдается также при первой загрузке программы, когда
 выполнен код начальной загрузки,  сформированный компилятором,  и
 маркер выполнения установлен в начале текста программы.

      No program loaded (программа не загружена)

 = 76 =


      Turbo Debugger был запущен без какой-либо программы. Никакой
 код не может быть выполнен, пока не будет загружена программа или
 не  будет сассемблирована часть команд с помощью команды Assemble
 локального меню подокна кода окна процессора.

      Control Break (нажаты клавиши Ctrl-Break)

      Выполнение программы было остановлено в  результате  нажатия
 клавиш  Ctrl-Break  после  того  как клавише Break была назначена
 какая-либо другая функция.

      Trace (трассировка)

      Была выполнена одна строка  исходного  текста  или  машинная
 команда по команде F7(Run|Trace).

      Breakpoint at_ (точка останова в...)

      При выполнении   программы   встретилась   точка   останова,
 заданная для прерывания работы программы.  Текст после слова "at"
 означает  адрес  команды программы,  на которой установлена точка
 останова.

      Terminated, exit code_ (завершена, код выхода...)

      Работа программы  завершена.  Текст   после   слова   "code"
 представляет    собой   код   выхода,   возвращаемый   программой
 операционной системе DOS. Если программа не возвращает DOS какого
 -либо   определенного   значения,   вместо   кода   выхода  может
 отображаться какое-то бессмысленное число. Программа не может быть
 запущена, пока не будет загружена заново командой Run|Program
 Reset.

      Loaded (загружена)

      Вы запустили отладчик Turbo Debugger, указав имя программы и
 параметр,   который   предотвращает   выполнение  кода  начальной
 загрузки,  сформированного компилятором.  Никакие команды еще  не
 были   выполнены,   включая  те,  которые  устанавливают  стек  и
 сегментные  регистры.  Это  означает,  что  если  вы  попытаетесь
 проверить  какие-либо  данные  в  своей  программе,  вы  получите
 неправильные значения.

      Step (шаг)

      Была выполнена одна строка  исходного  текста  или  машинная
 команда   без   входа   в   функцию  с  помощью  команды  F8  или
 F8(Run|Step Over).

      Interrupt (прервана)

 = 77 =


      Была нажата клавиша прерывания  (обычно  Ctrl-Break),  чтобы
 вернуть  управление  отладчику.  В  этом  случае работа программы
 немедленно прерывается и снова запускается отладчик.

      Exception_ (особая ситуация)

      Вы использовали TD386,  когда  встретилась  особая  ситуация
 процессора. Это   обычно   случается,  когда  программа  пытается
 выполнить недопустимый для данного  процессора  код  операции.  В
 документации по  процессору  Intel каждая особая ситуация описана
 подробно.

      Hardware deviсe driver stuck (конфликт драйвера аппаратного
                                    устройства)
      Вы используете аппаратный отладчик и  установили  аппаратную
 точку останова  для  стековой  переменной,  конфликтующую с Turbo
 Debugger. Прежде чем пойти дальше,  вы должны  убрать  эту  точку
 останова.

      Divide by zero (деление на ноль)

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

      Global breakpoint _ at__ (глобальная точка останова _ в _)

      Встретилась глобальная точка останова.  Вам сообщен ее номер
 и адрес в программе).
                                   Меню Run                                    
 -----------------------------------------------------------------

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

      -----------------------------
      Run                        F9
      Go to cursor               F4
      Trace into                 F7
      Step over                  F8
      Execute to...          Alt-F9
      Until return           Alt-F8
      Animate...
      Back trace             Alt-F4
      Instruction trace      Alt-F7
      -----------------------------
      Arguments...
      Program reset         Ctrl-F2
      -----------------------------

 = 78 =



 Команда Run [F9]

      Запускает программу  с  нормальной   скоростью   выполнения.
 Управление возвращается к отладчику в одном из следующих случаев:

      -  работа программы завершена;

      -  встретилась точка останова с заданным действием;

      -  выполнение прервано нажатием клавиш Ctrl-Break.

 Команда Go to Cursor [F4]   -------------------------------------

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


 Команда Trace Into
 [F7]   ---------------------------------------

      Выполняет одну строку исходного текста или машинную команду.
 Если текущим является окно Module,  то  выполняется  одна  строка
 исходного   кода,   однако,  если  текущим  окном  является  окно
 процессора,  выполняется  одна  машинная  команда.  Если  текущая
 строка  содержит  вызов  процедуры  или  функции,  Turbo Debugger
 входит в эту подпрограмму.  Если же  текущее  окно  -  окно  CPU,
 выполняется одна машинная команда.

      Turbo Debugger обрабатывает объектные правила и компонентные
 функции класса как все прочие процедуры и функции.  F7  выполняет
 трассировку исходного кода, если он имеется.

 Команда Step Over
 [F8]   ----------------------------------------

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

      Когда по  команде  Step  Over  выполняется  строка исходного
 текста,  содержащая вызов процедуры или функции,  Turbo  Debugger
 обрабатывает   этот  вызов  как  часть  данной  строки,  то  есть
 подпрограмма выполняется за один  шаг  отладки,  и  вы  сразу  же
 переходите  к  следующей  строке  текущей  подпрограммы,  либо  к
 подпрограмме, вызвавшей текущую.

 = 79 =


      Если по команде Step Over выполняется одна машинная команда,
 Turbo Debugger обрабатывает отдельные команды как единую команду,
 даже если они вызывают выполнение сразу нескольких  команд.  Ниже
 приведен   полный   перечень   команд,   которые   обрабатываются
 отладчиком Turbo Debugger как единая команда.

      CALL      Вызов подпрограммы (дальний и ближний)
      INT       Вызов подпрограммы обработки прерывания
      LOOP      Управление циклом с помощью счетчика CX
      LOOPZ     Управление циклом с помощью счетчика CX
      LOOPNZ    Управление циклом с помощью счетчика CX


      Кроме указанных за один шаг отладки выполняются команды REP,
 REPNZ и REPZ,  за которыми следуют команды  CMPS,  CMPSB,  CMPSW,
 LODSB,  LODSW,  MOVS,  MOVSB,  MOVSW,  SCAS,  SCASB, SCASW, STOS,
 STOSB, STOSW.

      Turbo Debugger обрабатывает объектные правила и компонентные
 функции класса как один оператор и обходит их, как обычные вызовы
 процедур и функций.

 Команда Execute To...
  [Alt-F9]  ---------------------------------

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

 Команда Until Return
 [Alt-F8]   ---------------------------------

      Выполняет программу  до  возврата  из  текущей   функции   в
 вызвавшую  ее  подпрограмму.  Эта команда полезна в двух случаях:
 если вы вошли в подпрограмму,  работа которой вас не  интересует,
 случайно    выполнив   команду       Run/Trace   вместо   команды
     Run/Step,  либо  если   вы   уже   определили,   что   данная
 подпрограмма   работает  правильно  и  нет  необходимости  дальше
 отслеживать ее выполнение в пошаговом режиме.


 Команда Animate
  [Alt-F4]   --------------------------------------

      Выполняет непрерывную  последовательность команд Trace into,
 обновляя  содержимое  экрана  после  выполнения  каждой  из   них
 (выглядит  как  замедленное выполнение программы).  Это позволяет
 пользователю  контролировать  текущее  положение  в  программе  и
 следить   за  изменением  значений  переменных.  Выполнение  этой

 = 80 =

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

      После выбора  Run|Animate  отладчик  запросит  у  вас  время
 задержки   между   последовательными  шагами  трассировки.  Время
 задержки  измеряется  в  десятых  долях  секунды.  По   умолчанию
 используется задержка равная 3.

 Команда Back Trace
  [Alt-F4]   -----------------------------------

      При трассировке  программы  (при  помощи  F8   или   Alt-F8)
 изменяет порядок  выполнения  на обратный.  Это удобно,  если при
 отладке вы зашли за ту точку,  в которой предполагаете  ошибку  и
 хотите вернуть выполнение программы назад.  Эта команда позволяет
 возвратиться назад либо по шагам,  либо сразу к  заданной  точке,
 высвеченной в подокне Instructions или окне Execution History.

      Предупреждение! имеется  несколько ограничений.  См.  раздел
 "Подокно Instructions".

 Команда Instruction Trace [Alt-F7]

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

      Поскольку вы не будете попадать в  начало  исходной  строки,
 эта команда обычно помещает вас в окно CPU.

 Команда Arguments...

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

 Команда Program Reset
  [Ctrl-F2]   -------------------------------

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

      Если вы  работаете в окне модуля или окне процессора,  то вы
 не будете возвращаться в начало своей программы. Вместо этого, вы
 останетесь точно в том же месте,  в котором вы были до выполнения
 команды Program Reset.  Если вы выбираете команду  Program  Reset
 только из-за того,  что вы выполнили на один оператор больше, чем
 намеревались,  вы можете переместить курсор  на  несколько  строк
 исходного текста  вверх  и нажать клавишу F4 или выбрать Run|Back

 = 81 =

 Trace, чтобы выполнить программу до этой строки,  вместо  Program
 Reset.
                  Окно Execution History (истории выполнения)                  
 -----------------------------------------------------------------

      Turbo Debugger  имеет   специальное   средство,   называемое
 историей выполнения,  позволяющее  запоминать  команды по мере их
 выполнения (при условии,  что вы трассируете код),  а также,  при
 желании, записывать  вводимые  вами  нажатия  клавиш,  при помощи
 которых вы приходите к той или иной точке  программы.  Вы  можете
 изучать эти  команды и отменять их действие,  возвращаясь в точку
 вероятной ошибки.  Если у нет EMS-памяти,  Turbo  Debugger  может
 записать до 400 команд.  При наличии EMS-памяти можно записать до
 3000 команд.

      Вы можете  изучать  историю  выполнения  в  окне   Execution
 History, которое открывается при выборе View|Execution History.

      Это окно  имеет  два подокна:  подокно Instructions вверху и
 подокно Keystroke Recording в нижней части экрана.

 Подокно Instructions

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

      История выполнения позволяет отслеживать только  те команды,
 что были  выполнены  по  команде  Trace Into (F7) или Instruction
 Trace (Alt-F7).  Отслеживание выполняется также для команды  Step
 Over, за исключением команд,  описанных на стр.84 оригинала.  При
 использовании команды Run или при выполнении  прерывания  история
 выполнения удаляется.  (Ее  запись возобновляется,  как только вы
 возобновляете трассировку).

      Обратная трассировка вызова прерывания невозможна.

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

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

 Локальное меню подокна Instructions
 -----------------------------------

      -------------------
      Inspect
      Reverse execute

 = 82 =

      -------------------
      Full history    Yes
      -------------------

      Локальное меню подокна Instructions содержит три команды:

 Команда Inspect
 ---------------

      Данная команда  перемещает  вас  к  команде,  высвеченной  в
 подокне Instructions.  Если  это  строка  исходного кода,  то она
 показана вам  в  окне  Module;  если  исходного  кода   нет,   то
 открывается окно CPU, с командами, высвеченными в подокне Code.

 Команда Full History

 (Выполнение в обратном направлении)
 -----------------------------------

      Данная команда реверсирует  выполнение  программы  к  точке,
 высвеченной в   подокне  Instructions.  Если  вы  выбрали  строку
 исходного кода, то вы вернетесь в окно Module; в противном случае
 появляется окно  CPU  с  высвеченной  линейкой  в  подокне  Code,
 установленной в позиции команды.

      Предупреждение! Обратное выполнение по части  программы, по
 которой не было прямого выполнения, невозможно. Например, если вы
 установили точку останова и нажали  F9  для  выполнения  до  этой
 точки, история  выполнения в обратном направлении будет потеряна.
 В этом случае, если вы желаете восстановить предыдущее состояние,
 вы можете   воспользоваться   средством  воспроизведения  нажатий
 клавиш окна Execution History, чтобы перезагрузить вашу программу
 и выполнить ее в прямом направлении до данной точки.

      Предупреждение! Команда  INT  приводит  к  потере предыдущей
 истории выполнения.  Выполнение  команд  в  обратном  направлении
 после данной команды невозможно, если не были нажаты клавиши Alt-
 F7 для трассировки прерывания.

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

      IN              INSW
      OUT             OUTSB
      INSB            OUTSW

 Команда Full History
 -------------------------------------

      Данная команда работает как переключатель вкл/выкл. Если она

 = 83 =

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

 Подокно Keystroke Recording
 (запись нажатий клавиш)   -----------

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

      Запись нажатий  клавиш  работает  в  сочетании  со средством
 обратного выполнения   программы,   предоставляя    разнообразные
 способы восстановления  нужной  точки  отладки.  Записываются все
 нажатия клавиш,  как  те,  что  относятся  к   управлению   Turbo
 Debugger, так  и  являющиеся  реакцией  на  действия отлаживаемой
 программы. Нажатия клавиш записываются в  файл имя_программы.TDK,
 где имя_программы - это имя отлаживаемой программы.

      Нижнее подокно   окна  Execution  History  используется  для
 воспроизведения нажатий  клавиш  и  восстановления  точки  сеанса
 отладки. Каждая  строка  в  списке  истории выполнения показывает
 причину, по которой  Turbo  Debugger  пришлось  взять  управление
 (точка останова, трассировка и т.д.) и текущую позицию в исходной
 программе в  этот  момент.  Если  адрес  программы  соответствует
 строке исходного кода,  то будет выведена эта строка. В противном
 случае команда по этому адресу дисассемблируется.

      Параметр командной строки -k включает запись нажатий клавиш.
 (См. стр.65    оригинала).    Вы    также    можете    установить
 соответствующее умолчание при помощи TDINST.

 Локальное меню подокна Keystroke Recording
 ------------------------------------------

      Локальное меню  подокна  Keystroke  Recording  содержит  две
 команды: Inspect и Keystroke Restore.

      ------------------
      Inspect
      Keystroke restore
      ------------------

 Команда Inspect
 ---------------

      Если вы высветили строку в подокне  Keystroke  Recording,  а
 затем выбрали  в  локальном  меню команду Inspect,  то появляется
 окно Module с курсором в той строке исходного кода, где произошло
 нажатие клавиши.

      Если данная строка не соответствует позиции в исходном коде,

 = 84 =

 то открывается окно CPU с высвеченной позицией команды.

 Команда Keystroke Restore
 -------------------------

      Если вы  высветили  строку в подокне Keystroke Recording,  и
 выбрали команду  Keystroke  Restore,  Turbo   Debugger   повторно
 загрузит данную   программу   и   выполнит   их  до  высвеченного
 контекста. Это особенно полезно,  если вы выполнили команду Turbo
 Debugger, удалившую историю выполнения.

                        Прерывание выполнения программы                        
 -----------------------------------------------------------------

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

      Кроме того,    прервать    выполнение    программы     может
 потребоваться  в том случае,  если по какой-то непонятной причине
 управление не возвращается отладчику.  Это может произойти в  том
 случае,  когда  выполняемый  фрагмент  кода  содержит бесконечный
 цикл: вы установили после этого фрагмента точку останова и ждете,
 когда  он будет выполнен,  но эта точка останова никогда не будет
 достигнута.

 Клавиши Ctrl-Break

      Нажатие этой комбинации клавиш практически  всегда прерывает
 выполнение  программы  и возвращает управление отладчику.  Работа
 программы прерывается сразу же после нажатия этих клавиш, поэтому
 иногда  может  показаться,  что  выполняется неожиданный фрагмент
 программы.  Например, это может быть подпрограмма обработки ввода
 с  клавиатуры  BIOS,  или команда из выполняемого в данный момент
 цикла.  Нажатие клавиш Ctrl-Break не  может  прервать  выполнение
 программы  в  следующих двух случаях (в этих случаях вам придется
 перезагрузить свою систему):

      - программа   зациклилась   в   режиме,   когда    запрещены
 прерывания;

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

      Если вы  отлаживаете  программу,  которой  самой   требуется

 = 85 =

 реагировать  на  клавиши  Сtrl-Break,  вы можете назначить другую
 клавишу прерывания.  Для этого  надо  воспользоваться  программой
 TDINST. Клавишей  прерывания  можно  назначить  любую  комбинацию
 клавиш.
                                                                               
Завершение работы программы
 -----------------------------------------------------------------

      Когда выполнение  программы завершается и происходит возврат
 в  DOS,  управление  снова  передается   отладчику.   Он   выдает
 сообщение,  показывающее  код  выхода,  который возвращается DOS.
 После того,  как  работа  программы  завершилась,  вы  не  можете
 выполнить ни одну из команд меню Run, пока не загрузите программу
 заново с помощью команды Run/Program Reset.

      Обычно после завершения работы программы сегментные регистры
 и  стек  содержат  неправильную  информацию,  поэтому  нет смысла
 проверять  или  модифицировать  какие-либо  переменные  программы
 после окончания ее выполнения.
                         Возобновление сеанса отладки                          
 -----------------------------------------------------------------

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

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

 Перезагрузка программы

      Для того   чтобы  заново  загрузить  программу,  которую  вы
 отлаживали,  выполните  команду      Run/Program   Reset.   Turbo
 Debugger  загрузить  программу  с  диска,  используя  все данные,
 которые могли быть добавлены в нее после последнего сохранения на
 диске.  Это самый безопасный способ повторного запуска программы.
 Перезапуск путем  выполнения  начала  программы  может  оказаться
 рискованным,    поскольку    для    многих   программ   требуется
 инициализация отдельных  данных,  хранящихся  в  дисковом  файле.
 Заметьте, что команда Program Reset оставляет без изменения точки

 = 86 =

 останова и отслеживаемые переменные.


 Запись и воспроизведение нажатий клавиш в макросах

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

      Чтобы обойти  эту  проблему,  можно  определить  макрос,   в
 котором  будут  "записаны"  все  клавиши,  которые  вы нажимали с
 момента  запуска  отладчика  до  того,  как  программа  войдет  в
 желаемое  состояние.  В этот момент можно прервать запись нажатий
 клавиш.  Если после этого потребуется вернуться к тому же  самому
 месту программы,  все, что потребуется сделать, это воспроизвести
 записанный макрос.

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

      Для того чтобы записать  весь  сеанс  отладки,  первое,  что
 нужно  сделать  после  запуска  отладчика из DOS,  это определить
 клавишу для  вызова  макроса.  Для  этого  надо  выбрать  команду
 Options/Macros/  Create.  Отладчик  попросит  вас нажать клавишу,
 которая будет назначена макросу.  Выберите  клавишу,  которой  не
 назначена  какая-то  другая  функция,  например,  Shift и одна из
 функциональных клавиш,  скажем Shift-F1.  Теперь выполняйте  свою
 программу,  пока  не  обнаружите ошибку.

      В этой  точке  остановите  запись  макроса,  выбрав  команду
 Macros/Stop Recording.  Теперь  сохраните  полученный  макрос  на
 диске, выбрав команду Options/Save Options. Продолжайте выполнять
 свою программу.  После того,  как в работе  программы  произойдет
 сбой и вы будете вынуждены перезагрузить ее и Turbo Debugger, вам
 достаточно будет нажать клавиши Shift-F1,  чтобы заново запустить
 программу.

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

      Примечание: Когда  макрос  записывается в файл конфигурации,
 вместе с ним записываются все параметры среды  отладчика, включая

 = 87 =

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

      Для загрузки в отладчик новой программы надо выбрать команду
 File/Open.

      Вы можете ввести имя файла  (с  расширением  .EXE)  в  блоке
 ввода File Name, либо нажать Enter для активизации блока списка с
 именами .EXE-файлов в текущей директории.  Переместите выделяющий
 курсор к нужному файлу и нажмите клавишу Enter.

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

      После имени программы можно указать ее аргументы  точно  так
 же, как это делается в командной строке DOS:

      myprog a b c

      Эта команда  загрузит  программу  MyProg с тремя аргументами
 командной строки: a, b и c.
                                                                               
Изменение аргументов программы
 -----------------------------------------------------------------

      Если при загрузке программы вы забыли задать какие-то нужные
 аргументы,  вы можете воспользоваться командой Run  |  Arguments,
 которая позволяет задавать и изменять аргументы.  Новые аргументы
 вводите точно так же,  как если бы вы указывали  их  после  имени
 программы в командной строке DOS.

      После того,  как вы введете новые аргументы,  Turbo Debugger
 спросит у вас, хотите ли вы перезагрузить свою программу с диска.
 Как  правило,  в  таких  ситуациях  следует  отвечать "Да" (Yes),
 поскольку в большинстве случаев новые аргументы будут  влиять  на
 работу программы только после ее загрузки.



 = 88 =

                    ГЛАВА 6  ПРОВЕРКА И МОДИФИКАЦИЯ ДАННЫХ                     


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

      - Окна проверки (Inspector) позволяют просматривать данные в
 той же форме,  в которой они представлены в программе.  Вы можете
 "следить"  за  значениями  указателей,  просматривать  содержимое
 массивов,  записей и объединенных типов в том виде, в котором они
 записаны в программе.

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

      - Блок  диалога  Evaluate/Modify показывает содержимое любых
 переменных и позволяет присваивать им новые значения.

      В данной главе предполагается, что вы имеете представление о
 различных   типах   данных,  которые  используются  в  том  языке
 программирования,  на котором  вы  работаете  (Си,  Паскаль,  или
 ассемблер).  Если  вы  только начинаете программировать на данном
 языке и недостаточно хорошо знакомы со всеми его типами данных, в
 этой главе вы сможете найти полезную информацию об основных типах
 данных (char,  int,  integer,  boolean,  real и т.д.).  Когда  вы
 познакомитесь  с  более сложными типами данных (pointer,  record,
 struct,  union и т.д.),  вернитесь к этой главе,  чтобы научиться
 просматривать их с помощью отладчика Turbo Debugger.

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

      Если вам  требуется  просматривать  или  изменять содержимое
 произвольных   областей    памяти,    представленное    в    виде
 шестнадцатиричных байтов данных, обратитесь к главе 11, в которой
 описана отладка на уровне ассемблера.
                                   Меню Data                                   
 -----------------------------------------------------------------

      ---------------------------
      Inspect...
      Evaluate/modify...  Ctrl-F4
      Add watch...        Ctrl-F7

 = 89 =

      Function return
      ---------------------------

      Меню Data позволяет выбрать способ просмотра  и  модификации
 данных  отлаживаемой  программы.  Имеется  возможность  вычислять
 значения выражений, изменять значения переменных и открывать окна
 проверки, отображающие значения элементов данных.

 Команда Inspect...

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

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

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

      (Подробное описание работы с окнами проверки  приведено ниже
 в разделе "Окна проверки".)

 Команда Evaluate/Modify...

      Открывает блок    диалога    Evaluate/Modify   (рис.6.1)   и
 запрашивает у  пользователя  выражение,  значение  которого  надо
 вычислить,  точно  так  же,  как это делает компилятор при выборе
 команды Eval. Этот вопрос подробно рассматривается в главе 9.

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

      Не забудьте,  что после  выражения,  за  которым  необходимо
 проследить,  может  стоять  строка управления форматом.  Вопросы,
 связанные с управлением форматом,  рассмотрены в главе  9.  Turbo
 Debugger  отображает результат вычисления в формате,  удобном для
 просмотра  значения  данного  типа.  Если  требуется   отображать
 результат  в  другом  формате,  надо  поставить  после  выражения

 = 90 =

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

      Блок диалога имеет три поля.  В верхнее подокно  вы  вводите
 выражение,  значение которого необходимо вычислить.  Это подокно,
 как и другие окна запроса, имеет "исторический" список. В среднем
 подокне  отображается  вычисленное  значение выражения.  В нижнее
 подокно можно ввести  новое  значение  выражения.  Если  значение
 выражения  не  может  быть  изменено,  в  этом подокне появляется
 сообщение "Not Available",  и вы не можете переместить  курсор  в
 это подокно.

      Ввод в блок ввода New Value действует,  когда выбрана кнопка
 Modify.  Так же, как и в других окнах, имеющих несколько подокон,
 для  перемещения  курсора из одного подокна в другое используются
 клавиши Tab и Shift-Tab. Нажатие клавиши Esc при вводе в любое из
 подокон или нажатие кнопки мыши Cancel закрывает блок ввода.

      Строки данных,  слишком  длинные  для  вывода  в блоке ввода
 Result, имеют в  конце  символ  (>).  Для  дальнейшего  просмотра
 строки можно выполнить скроллинг по этой строке.

      При отладке   программ   С++   или  объектно-ориентированного
 Паскаля блок диалога Evaluate/Modify также позволяет вам выводить
 на дисплей  поля  конкретных  вхождений  объектов или компонентов
 класса. Вы можете воспользоваться спецификатором формата, который
 может быть использован при расчете записи.

      При трассировке   правила  или  компонентной  функции  Turbo
 Debugger узнает об области определения  и  приоритетах  параметра
 Self/this. Вы   можете  вычислить  Self/this  и  сопроводить  его
 спецификаторами формата и квалификаторами.

      Turbo Debugger  позволяет   также   вызывать   правило   или
 компонентную функцию из блока диалога Evaluate/Modify.  Для этого
 нужно ввести  имя  вхождения  функции,  точку,  имя  правили  или
 компонентной функции  и список фактических параметров (или пустые
 круглые скобки, если параметры отсутствуют). В случае объявлений

      type
         Point = object
            X, Y   : Integer;
            Visible: Boolean;
            constructor Init(InitX, InitY : Integer);
            destructor  Done; virtual;
            procedure   Show; virtual;
            procedure   Hide; virtual;
            procedure   MoveTo(NewX, NewY : Integer);

 = 91 =

      end;

      var
         APoint : Point;

      вы можете ввести в окно Turbo  Debugger  Evaluate  любые  из
 следующих выражений:

 -----------------------------------------------------------------
 Выражение                          Результат
 -----------------------------------------------------------------
 APoint.X                           5($5):Integer
 APoint                             (5,23,FALSE):Point
 APoint.MoveTo                      @6F4F:00BE
 APoint.MoveTo(10,10)               вызывает правило MoveTo
 APoint.Show()                      вызывает правило Show
 -----------------------------------------------------------------

 Замечание для программистов, работающих на Си
 ---------------------------------------------

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

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

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

      Вы можете  также использовать блок диалога Evaluate/Modify в
 качестве простого калькулятора,  вводя в качестве операндов числя
 вместо переменных программы.

 Команда Add Watch

      Запрашивает у   пользователя   выражение,  за  которым  надо
 проследить,  а затем  заносит  данное  выражение  или  переменную
 программы в  список переменных,  отображаемых в окне слежения при

 = 92 =

 нажатии Enter или при выборе кнопки OK.

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

 Команда Function Return

      Отображает значение,  которое должно быть возвращено текущей
 функцией.  Эту  команду можно использовать только перед возвратом
 из функции в вызвавшую программу.

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

      Благодаря этой команде отпадает необходимость открывать окно
 процессора,  чтобы проверить возвращаемое значение,  помещенное в
 регистры процессора. А поскольку тип и формат возвращаемых данных
 известны, то    использование    данной    команды   проще,   чем
 использование шестнадцатиричного дампа.
                                                                               
Выбор элементов данных в исходном тексте
 -----------------------------------------------------------------

      Turbo Debugger  имеет  мощный  механизм,  который  исключает
 необходимость  ввода  с  клавиатуры  имен   переменных,   которые
 требуется   проверить.   Находясь  в  любом  окне  модуля,  можно
 установить курсор на имя любой  переменной  и  выполнить  команду
 Inspect локального меню,  чтобы открыть окно проверки,  в котором
 будет отображаться значение  выбранной  переменной.  Можно  также
 выбрать  выражение  для проверки.  Для этого прежде чем выполнять
 команду Inspect,  надо позиционировать курсор на  это  выражение,
 нажать  клавишу  Ins  и  с  помощью  клавиш  управления  курсором
 выделить выражение.  Работа с окном  модуля  подробно  описана  в
 главе 8.
                                 Окно слежения                                 
 -----------------------------------------------------------------

      В окно  слежения  (Watches)  можно  заносить  переменные   и
 выражения   программы,  за  которыми  необходимо  следить.  Можно
 следить как за значениями простых  переменных  (например,  целого
 типа),  так  и за содержимым сложных элементов данных,  таких как
 массивы.  Кроме того,  можно  отслеживать  значение  вычисляемого
 выражения,  в  котором  нет  прямых  обращений к областям памяти,
 например, x * y + 4.

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

 View/Watches.  В  этом  окно  отображается  список  переменных  и
 выражений,  за которыми необходимо следить. Слева указывается имя
 переменной  или  выражение,  а  справа  тип  данных  и  значение.
 Значения  сложных  типов,  таких   как   массивы   и   структуры,
 заключаются  либо  в  фигурные (для си-программ),  либо в круглые
 (для паскаль-программ) скобки. Если в строке не хватает места для
 отображения всего выражения,  часть выражения отсекается.

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

      Это означает,  что  если  имя  какой-либо переменной введено
 неправильно,  эта ошибка не  будет  обнаружена,  поскольку  Turbo
 Debugger  будет  рассматривать  его  как имя переменной,  которое
 станет допустимым в процессе выполнения  программы.  Если  вы  не
 используете  механизм  изменения  области  действия,  описанный в
 главе 9, Turbo Debugger будет вычислять значение выражения в окне
 слежения,  используя  область  действия  в текущей точке останова
 программы.  Следовательно,  выражения в окне слежения будут иметь
 такие же значения,  как если бы они находились в тексте программы
 в той точке,  в которой она была остановлена.  Если отслеживаемое
 выражение содержит имя переменной, которая не доступна из текущей
 области действия (например,  если она описана в  другом  модуле),
 значение  этого выражения неопределено и вместо него отображается
 четыре знака вопроса (????).

      При выполнении трассировки внутри объектного правила  к окну
 Watches можно добавить параметр Self/this.

 Локальное меню окна слежения

      Так же,  как  и  другие локальные меню,  локальное меню окна
 слежения вызывается нажатием  клавиш  Alt-F10.  Если  для  нужной
 команды  меню  определена  активная клавиша,  для ее вызова можно
 нажать клавишу Ctrl в сочетании с первой буквой этой команды.

      -------------------
      Watch...
      Edit...
      Remove
      Delete All
      -------------------
      Inspect
      Change

 = 94 =

      -------------------

 Команда Watch
 ----------------

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

 Команда Edit
 ---------------

      Позволяет пользователю отредактировать выражение, занесенное
 в окно слежения.  Можно корректировать введенное ранее  выражение
 или ввести новое.

      Эту команду также можно вызвать, установив выделяющий курсор
 на нужное выражение в окне слежения и нажав  клавишу  Enter.  Для
 помещения отредактированного  выражения  в  окно  Watches нажмите
 Enter или выберите OK.

 Команда Remove
 --------------

      Удаляет выбранное выражение из окна слежения.

 Команда Delete All
 ------------------

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

 Команда Inspect
 ---------------

      Открывает окно проверки,  в котором отображается  содержимое
 выбранного  элемента  из  окна  слежения.  Если выбранный элемент
 является сложным объектом (массивом,  записью или структурой), то
 можно  просмотреть  все  его элементы,  а не только тот,  который
 указан в окне слежения.  (Все вопросы,  касающиеся окон  проверки
 данных, рассмотрены ниже в разделе "Окна проверки данных".)

 Команда Change
 --------------

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

 написана   отлаживаемая   программа,   Turbo  Debugger  выполняет
 необходимое преобразование типов точно так же,  как если  бы  для
 изменения значения переменной использовался оператор присваивания
 (= или :=).  В главе 9 приведена более  подробная  информация  об
 операторе присваивания и преобразовании типов.
                             Окна проверки данных                              
 -----------------------------------------------------------------

      В окне   проверки   (Inspector)   данные   отображаются    в
 соответствии с их типом.  Все типы - скалярные (например,  char и
 int),  указатели (char* в Си и ^ в Паскале),  массивы (long x[4],
 array [1..10] of word), функции, структуры, записи, объединения и
 множества - отображаются по-разному.

      В окне проверки отображается список всех  элементов, которые
 составляют   проверяемый   объект   данных.   В   заголовке  окна
 указывается тип проверяемых данных и имя, если оно имеется.

      Первым элементом  в  окне  проверки  всегда  является  адрес
 области    памяти,   содержащей   проверяемые   данные,   который
 записывается в формате <сегмент:смещение> (если  данные  хранятся
 не в регистре и не равны константе, например 3).

      Для того  чтобы  просмотреть содержимое окна проверки в виде
 строк байтов данных,  надо, находясь в этом окне, выбрать команду
 View/Dump.  На  экране появится окно процессора,  в подокне данных
 которого будут отображаться  данные,  соответствующие  выбранному
 элементу в окне проверки.  Чтобы вернуться к окну проверки,  надо
 закрыть окно  процессора  с  помощью  команды  Window/Close  (или
 клавиши Alt-F3), либо нажав кнопку мыши на блоке закрытия.

      В следующих   разделах   описаны  различные  окна  проверки,
 используемые для каждого  из  языков,  поддерживаемых  отладчиком
 Turbo  Debugger:  Си,  Паскаль  и  ассемблер.  Для  каждого языка
 используется свой формат представления данных в  окнах  проверки.
 Элементы  данных  и  их  значения  всегда  отображаются  в том же
 формате, в котором они описаны в исходном тексте программы.

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

 Окна проверки данных си-программы

 Скалярные типы
 --------------

      В окнах  проверки  скалярных  типов   отображаются   простые
 элементы данных, например,

 = 96 =


      char x = 4;
      unsigned long y = 123456L;

      В этих окнах проверки кроме верхней строки, содержащей адрес
 переменной, имеется еще одна строка информации. Слева указывается
 тип скалярной переменной (char, unsigned long и т.д.), а справа -
 ее  значение.  Значение  может  быть  представлено в десятичном и
 шестнадцатиричном форматах  или  в  обоих  одновременно.  Вначале
 значение   обычно  представляется  в  десятичном  формате,  после
 которого в круглых скобках указывается шестнадцатиричное значение
 (с   обычным   префиксом   0x,   используемым   в  языке  Си  для
 шестнадцатиричного формата).  Для изменения способа представления
 значений можно использовать утилиту TDINST.

      Если проверяемая   переменная   относится   к   типу   char,
 отображается также ее символьный эквивалент.  Если представленное
 значение  не  имеет  печатаемого символьного эквивалента,  то для
 отображения символьного значения можно использовать обратный слеш
 (\),   за   которым   следует   шестнадцатиричное  значение.  Это
 символьное  значение  будет  отображаться  перед  десятичным  или
 шестнадцатиричным значением.


 Указатели
 ---------

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

      char *p = "abc";
      int *ip = 0;
      int **ipp = @ip;

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

      Если ссылочная  переменная  указывает  на  строку  символов,
 заканчивающуюся  символом  0,  в   окне   проверки   отображается
 дополнительная  информация,  показывающая значения всех элементов
 массива символов.  Слева в каждой строке указан  индекс  элемента
 массива ([1],  [2] и т.д.), а справа - значение элемента в том же
 формате,  который используется в окне проверки скалярных типов. В
 этом случае вся строка целиком отображается в верхней строке окна
 вместе с  адресом  ссылочной  переменной  и  адресом  строки,  на
 которую она указывает.

 = 97 =


      Вы также  получаете  несколько  строк,  если открываете окно
 Inspector и используете команду локального меню Range. Этот метод
 важен для программистов Си,  использующих указатели для ссылки на
 массивы элементов как на единый элемент.  Например,  если  у  вас
 есть код

      int array[10];
      int *arrayp = array;

      и вы хотите посмотреть,  куда указывает  arrayp,  используйте
 локальную команду   Range  для  arrayp,  задав  начальный  индекс
 массива 0 и диапазон,  равный 10.  Если вы не сделаете этого,  то
 получите только первый элемент массива.

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

 Массивы
 -------

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

      long threed[3][4][5];
      char message[] = "eat these words";

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

      Для исследования  любой  части  массива  можно  использовать
 команду локального меню Range.  Это полезно, если массив содержит
 большое число элементов, вам нужно обратиться к середине массива.

 Структуры и объединения
 -----------------------

      В окнах   проверки   структур   и  объединений  отображаются
 значения элементов структур и объединений, например,

      struct date {
         int year;
         char month;
         char day;
      } today;

      union {

 = 98 =

         int small;
         long large;
      } holder;

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

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

 Функции
 -------

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

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


 Окна проверки данных паскаль-программы


 Скалярные типы
 --------------

      В окнах  проверки  скалярных  типов   отображаются   простые
 элементы данных, например,

      var
        X : integer;
        Y : longint;

      В этих окнах проверки кроме верхней строки, содержащей адрес
 переменной, имеется еще одна строка информации. Слева указывается
 тип скалярной переменной (byte, word, integer, longint и т.д.), а
 справа  -  ее  значение.  Значение  может  быть  представлено   в
 десятичном и шестнадцатиричном форматах или в обоих одновременно.
 Вначале значение  обычно  представляется  в  десятичном  формате,
 после  которого  в  круглых скобках указывается шестнадцатиричное
 значение (с обычным  префиксом  $,  используемым  в  языке  Turbo

 = 99 =

 Pascal  для  шестнадцатиричного  формата).  Для изменения способа
 представления значений можно использовать утилиту TDINST.

      Если проверяемая  переменная  относится  к  типу  byte   или
 shortint,  отображается  также  ее  символьный  эквивалент.  Если
 представленное  значение   не   имеет   печатаемого   символьного
 эквивалента,   то  для  отображения  символьного  значения  можно
 использовать  символ  #,  за  которым  следует  шестнадцатиричное
 значение.   Это  символьное  значение  будет  отображаться  перед
 десятичным или шестнадцатиричным значением.


 Указатели
 ---------

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

      var
        IP : ^integer;
        LP :^^pointer;

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

      Несколько строк   информации   также  можно  получить,  если
 открыть окно проверки,  выполнить команду Range локального меню и
 указать количество, большее чем 1.


 Массивы
 -------

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

      var
        A : array[1..10,1..20] of integer;
        B : array[1..50] of boolean;

      Каждый элемент массива отображается в отдельной строке окна.
 Слева в каждой строке указывается индекс элемента массива. Справа
 указывается  значение  элемента.  Если  значение элемента массива
 является сложным элементом данных,  таким как массив или  запись,

 = 100 =

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

      Для исследования  любой  части  массива  можно  использовать
 команду локального меню Range.  Это полезно, если массив содержит
 большое число элементов, вам нужно обратиться к середине массива.



 Записи
 ------

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

      record
        year : integer;
        month : 1..12;
        day : 1..31;
      end


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

 Процедуры и функции
 -------------------

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



 Окна проверки данных ассемблерных программ

 Скалярные типы
 --------------

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

      VAR1      DW  99
      MAGIC     DT  4.608
      BIGNUM    D0  123456

      В этих окнах проверки кроме верхней строки, содержащей адрес
 переменной, имеется еще одна строка информации. Слева указывается

 = 101 =

 тип скалярной переменной (byte,  word,  dword,  qword и т.д.),  а
 справа  -  ее  значение.  Значение  может  быть  представлено   в
 десятичном и шестнадцатиричном форматах или в обоих одновременно.
 Вначале значение  обычно  представляется  в  десятичном  формате,
 после  которого  в  круглых скобках указывается шестнадцатиричное
 значение (с обычным префиксом h,  используемым в языке ассемблера
 для    шестнадцатиричного   формата).   Для   изменения   способа
 представления значений можно использовать утилиту TDINST.


 Указатели
 ---------

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

      X         DW  0
      XPTR      DW  X
      FARPTR    DD  X


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

      Если ссылочная  переменная относится к типу byte и указывает
 на строку символов,  заканчивающуюся символом 0,  в окне проверки
 отображается  дополнительная  информация,  показывающая  значения
 всех элементов массива символов.  Слева в  каждой  строке  указан
 индекс  элемента массива ([1],  [2] и т.д.),  а справа - значение
 элемента в том же формате,  который используется в окне  проверки
 скалярных типов.  В этом случае вся строка целиком отображается в
 верхней строке окна  вместе  с  адресом  ссылочной  переменной  и
 адресом строки, на которую она указывает.

      Несколько строк  в  окне  проверки  указателей  также  можно
 получить, открыв это окно, выполнив команду Range локального меню
 и задав значение, больше 1.


 Массивы
 -------

      В окне проверки массивов ассемблерной программы отображаются
 значения элементов массива, например,

 = 102 =


      WARRAY  DW 10 DUP (0)
      MSG     DB "Greetings",0

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

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


 Структуры и объединения
 -----------------------

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

      X    STRUCT
      MEM1       DB  ?
      MEM2       DD  ?
      X    ENDS
      ANX  X         <1,ANX>

      Y    UNION
      ASBYTES    DB  10 DUP (?)
      ASFLT      DT  ?
      Y    ENDS
      AY   Y         <?,1.0>


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


                         Локальное меню окна проверки                          
 -----------------------------------------------------------------

      --------------------
      Range...
      Change...
      --------------------

 = 103 =

      Inspect
      Descend
      New expression...
      Type cast...
      --------------------

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

      Для вызова локального меню окна проверки надо нажать клавиши
 Alt-F10.   Если   разрешено   использование   активных  клавиш  в
 комбинации с клавишей  Ctrl,  для  вызова  команды  можно  нажать
 клавишу Ctrl в сочетании с первой буквой ее названия.


 Команда Range

      Задает начальный элемент  и  количество  элементов,  которые
 необходимо   отобразить  в  окне  проверки.  Эту  команду  удобно
 использовать при проверке массивов,  когда необходимо просмотреть
 лишь некоторый поддиапазон всех элементов массива.

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

      Эта команда особенно удобна для проверки массивов в  Си, где
 часто  описываются  указатели  на элемент данных (например,  char
 *p),  который в действительности является массивом символов, а не
 одиночным символом.

 Команда Change

      Заменяет значение  выделенного  элемента  данных  значением,
 введенным пользователем в ответ на  запрос  отладчика.  Если  это
 позволяет   язык   программирования,   Turbo  Debugger  выполняет
 необходимое преобразование типа точно так же,  как  если  бы  для
 изменения  значения  переменной  был  использован соответствующий
 оператор присваивания.  Более подробная информация  об  операторе
 присваивания и преобразовании типов приведена в главе 9.

 Команда Inspect

      Открывает еще  одно  окно  проверки,  в котором отображается
 содержимое выбранного элемента. Это бывает полезно в тех случаях,
 когда элемент,  отображаемый в окне проверки, сам содержит другие

 = 104 =

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

      Если в текущем окне проверки проверяется функция, по команде
 Inspect будет показан ее исходный текст.

      Эту команду также можно вызвать,  выбрав  нужный  элемент  в
 окне проверки и нажав клавишу Enter.

      Для того  чтобы  вернуться в предыдущее окно проверки,  надо
 нажать клавишу Esc,  которая закроет новое окно  проверки.  Когда
 проверка  структуры данных закончена и необходимо убрать с экрана
 все окна  проверки,  можно  выполнить  команду  Window/Close  или
 нажать клавишу Alt-F3, либо нажать кнопку мыши на блоке закрытия.

 Команда Descend

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

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

 Команда New Expression

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

      Окна проверки для объектов Паскаля и классов  С++  несколько
 отличаются от  обычных окон Inspector.  Описание этих окон см.  в
 главе 10.

 Команда Type Cast

      Позволяет задавать проверяемому элементу данных  другой  тип
 (Byte, Word,   Int,  Char,  pointer).  Это  полезно,  когда  окно
 Inspector содержит символическое имя, для которого нет информации

 = 105 =

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



 = 106 =

                            ГЛАВА 7  ТОЧКИ ОСТАНОВА                            

      Turbo Debugger  имеет  единую  концепцию  "точки  останова",
 которая объединяет функции  отладчика,  которые  обычно  называют
 точками останова, точками слежения и контрольными точками.

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

      В отладчике Turbo Debugger эти три  концепции  объединены  в
 одну концепцию точки останова, определение которой делится на три
 части:

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

      -  условие, при котором происходит включение точки останова;

      -  что происходит при включении точки останова.

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

      "Условие" может быть следующим:

      -  всегда;

      -  когда становится истинным некоторое выражение;

      -  когда изменяется значение некоторого объекта данных.

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

      "Что происходит" означает одно из следующих событий:

      -  работа программы останавливается (точка останова);

      -  регистрируется значение выражения;

 = 107 =


      -  выполняется выражение (вставка кода).

      В этой   главе   показываются  преимущества  точек  останова
 отладчика Turbo  Debugger  над  традиционными  точками  останова,
 точками   слежения   и   контрольными   точками.   Вы   научитесь
 пользоваться окном точек останова и окном  регистрации,  изучите,
 как устанавливать простые точки останова, условные точки останова
 и точки останова,  регистрирующие значения переменных  программы.
 Кроме того, вы изучите, как устанавливать точки останова, которые
 отслеживают тот  момент,  когда  изменяется  значение  переменной
 выражения или объекта данных.

      Во многих случаях вам будет требоваться устанавливать только
 несколько простых точек останова, по достижении каждой из которых
 выполнение программы будет останавливаться.  Можно установить или
 сбросить точку  останова  в  любом  месте  программы.  Для  этого
 достаточно  установить курсор на нужную строку исходного текста и
 нажать клавишу F2. Можно также установить точку останова на любой
 строке  машинного  кода,  нажав  клавишу  F2 в тот момент,  когда
 маркер выполнения находится на нужной команде в подокне кода окна
 процессора.Либо,  если у вас есть мышь,  нажмите кнопку на первых
 двух  столбцах  того  места,  где  вы  хотите  установить   точку
 останова.  (Если  вы  находитесь  в правом столбце,  то в позиции
 указателя при этом появится  кружочек).  Количество  одновременно
 установленных точек останова ничем не ограничено.
                               Меню Breakpoints                                
 -----------------------------------------------------------------

      Глобальное меню  Breakpoints  может  быть  вызвано  в  любой
 момент нажатием его активной клавиши Alt-B.

      -----------------------------
      Toggle                     F2
      At...                  Alt-F2
      Changed memory global...
      Expression true global...
      Hardware breakpoint...
      Delete All
      -----------------------------

 Команда Toggle

      Устанавливает или сбрасывает  точку  останова  в  выделенной
 строке  окна  модуля  или подокна кода окна процессора.  Активная
 клавиша - F2.

 Команда At

      Устанавливает точку останова в определенном месте программы.

 = 108 =

 Отладчик   запрашивает   адрес   строки,  на  которой  необходимо
 установить точку останова. Активная клавиша - Alt-F2.

 Команда Changed Memory Global

      Устанавливает точку  останова,  которая  переключается   при
 изменении   содержимого  определенной  области  памяти.  Отладчик
 запрашивает имя области памяти,  за которой  необходимо  следить.
 Для  получения  более  подробной информации обратитесь к описанию
 команды Changed Memory  в  разделе  "Локальное  меню  окна  точек
 останова", следующем ниже в данной главе.

 Команда Expression True Global

      Устанавливает точку останова,  которая переключается,  когда
 выражение,  заданное пользователем становится истинным.  Отладчик
 запрашивает   выражение   у  пользователя.  Для  получения  более
 подробной информации  обратитесь  к  описанию  команды  Condition
 Expression  True  в разделе "Локальное меню окна точек останова",
 следующем ниже в данной главе.

 Команда Hardware Breakpoint

      Информация об интерфейсе аппаратного отладчика  находится  в
 файле на  дистрибутивных  дискетах.  См.  в файле README описание
 доступа к этой дисковой информации.

      Предупреждение! Для аппаратной отладки у вас  должна иметься
 плата отладчика.

 Команда Delete All
 ------------------

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

      Как действие,  выполняемое в точке останова,  так и условие,
 при  котором   происходит   ее   включение,   могут   управляться
 выражением,  вводимым пользователем.  Это выражение вычисляется с
 учетом области  действия  адреса,  в  котором  установлена  точка
 останова, а не области действия точки, в которой была остановлена
 программа.  Это означает, что в выражении, по которому происходит
 переключение  точки  останова,  могут использоваться имена только
 тех  переменных,  которые  являются  допустимыми  в   том   месте
 программы, в котором установлена точка останова (если эта область
 действия не заменяется). Более подробно области действия описаны в
 главе 9.

      Если в выражении используются локальные переменные некоторой

 = 109 =

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

      Окно точек останова  (Breakpoints)  открывается  по  команде
 View/Breakpoints   главного   меню.  Оно  позволяет  пользователю
 просматривать и изменять условия переключения точки останова. Это
 окно  можно  использовать  и  для  задания  новых точек останова,
 удаления точек останова и настройки имеющихся точек останова.

      Окно точек  останова  разделено  на  два  подокна.  В  левом
 подокне  приведен  список  адресов,  на которых установлены точки
 останова. В правом подокне приведена информация о точке останова,
 выделенной  в  левом  подокне.  Только  левое  подокно имеет свое
 локальное меню,  которое вызывается нажатием клавиш Alt-F10.  Его
 опции влияют  на  то,  высвечивается  ли точка останова в подокне
 Breakpoint List.

 Локальное меню окна точек останова

      ---------------------
      Set options...
      Hardware options...
      ---------------------
      Add...
      Remove
      Delete all
      Inspect
      ---------------------

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

      Локальное меню  окна  точек  останова  вызывается   нажатием
 клавиш  Alt-F10.  Если  для  команды  локального  меню определена
 активная клавиша,  для ее выбора достаточно нажать клавишу Ctrl в
 сочетании с первой буквой названия команды.


 Команда Set Options
 -------------------

      Открывает блок   диалога   Breakpoint   Options,  в  котором
 содержится два набора селективных кнопок,  один блок ввода и один
 блок проверки. В этом блоке диалоге вы можете


 = 110 =

      - определить,   что   происходит   при   срабатывании  точки
 останова, высвеченной в подокне Breakpoint List

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

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

      - разрешать или отменять точку останова

      - устанавливать или изменять адрес точки останова

      - делать точку останова глобальной


      Селективные кнопки Action  (действие)  имеют  три  возможных
 установки:


      Break (останов)

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

      Execute (выполнение)

      Заставляет отладчик  выполнять  определенное выражение.  Это
 выражение запрашивается отладчиком.  Выражение  не  должно  иметь
 таких побочных эффектов,  как изменение значения переменной.  Эта
 команда  может  использоваться  для  "вставки   кода",   позволяя
 вставлять   выражение,  которое  будет  выполнено  перед  текущей
 строкой программы.

      Log (регистрация)

      Заставляет отладчик зарегистрировать  значение  выражения  в
 окне  Log.  Отладчик запросит у вас выражение,  значение которого
 необходимо зарегистрировать.  Будьте внимательны и не допускайте,
 чтобы   это   выражение  имело  какие-либо  неожиданные  побочные
 эффекты.  Подробное описание побочных эффектов приведено в  главе
 9.

      Селективные кнопки    Condition   (условие)   имеют   четыре
 возможные установки,


      Always (всегда)

      Показывает, что для переключения точки останова не требуется

 = 111 =

 выполнения никаких дополнительных условий.

      Changed Memory (изменение содержимого памяти)

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

      (long)a,4

      длина отслеживаемой области будет равна 16 байтам, поскольку
 под тип long отводится 4 байта, и число таких объектов равно 4.

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

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

      Expression True (выражение истинно)

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

      Hardware (аппаратная отладка)

      Заставляет отладчик  включать  точку  останова   с   помощью
 драйвера  устройства  с  аппаратной  поддержкой.  Используйте это
 меню,  если работаете на машине с процессором 80386 и  установлен
 драйвер  устройства  TDH386.SYS,  или если в вашей машине имеется
 плата  аппаратного  отладчика  и  ее  изготовитель   снабдил   ее
 драйвером устройства для отладчика Turbo Debugger.


 = 112 =

      В поставляемой на дискетах документации рассмотрен интерфейс
 аппаратного отладчика и использование меню Hardware.


      Блок ввода  Pass  Count  позволяет  установить,  сколько раз
 должно быть выполнено  определенное  действие  прежде  чем  будет
 включена  точка останова.По умолчанию это число равно 1.  Счетчик
 количества проходов уменьшает свое значение  на  единицу,  только
 когда условие включения точки останова выполняется. Это означает,
 что если вместе с условием задано количество  проходов  n,  точка
 останова   будет   включена,  когда  в  n-ый  раз  условие  будет
 выполнено.

      Блок переключения   Breakpoint   Disabled   разрешает    или
 запрещает   включать   выделенную  точку  останова.  Эта  команда
 работает  как  триггер,  имеющий  два  состояния:  "разрешено"  и
 "запрещено",  который  переключается при каждом выполнении данной
 команды.  Запрещенная точка останова остается  "невидимой",  пока
 она  снова  не будет разрешена,  и ведет себя так,  как будто она
 была удалена.

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

 Команда Hardware Options

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

      Предупреждение! Для    использовании   средства   аппаратной
 отладки необходимо иметь плату отладчика.

 Команда Add
 (добавить)
 -------------------------

      Добавляет в  список имеющихся  точек останова  еще одну  точку.
 Вы должны ввести адрес в блоке ввода Address.

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

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

 включения   отсутствуют,   а  ее  действием  является  прерывание
 (останов) выполнения программы.

 Команда Remove
 (удалить)
 ------------------------

      Удаляет выделенную точку останова.

 Команда Delete All
 (удалить все)
 --------------------------------

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

 Команда Inspect
 (проверить)
 ---------------------------

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

      Эту команду также можно вызвать,  нажав Enter в тот  момент,
 когда выделяющая полоса установлена на точке останова.
                               Окно регистрации                                
 -----------------------------------------------------------------

      Окно регистрации  (Log)  открывается  при   выборе   команды
 View/Log. Это окно позволяет просматривать список важных событий,
 которые произошли во время сеанса отладки.

      В окне регистрации отображается  список  строк,  которые  во
 время  отладки  заносятся  в  журнал  (log).  Если  в журнал было
 занесено более 50 строк, самые старые строки удаляются из вершины
 прокручиваемого в окне списка.  Чтобы изменить количество строк в
 списке,  можно либо  задать  соответствующий  параметр  командной
 строки  при  запуске  отладчика,  либо воспользоваться программой
 настройки TDINST.  Можно также сохранить весь журнал,  непрерывно
 записывая его в дисковый файл.  Для этого служит команда Open Log
 File локального меню.

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


 = 114 =

      - Работа    программы    была    остановлена   в   указанном
 пользователем  месте.  Точка  программы,  в   которой   произошел
 останов, регистрируется в журнале.

      - Выполнена  команда  Add Comment локального меню.  Отладчик
 запрашивает у пользователя комментарий и заносит его в журнал.

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

      - Выполнена  команда  Window/Dump  Pane  To Log (из главного
 меню), которая регистрирует текущее содержимое подокна.

 Локальное меню окна регистрации

      -------------------
      Open log file...
      Close log file
      Logging         Yes
      Add comment...
      Erase log
      -------------------

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

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


 Команда Open Log File
 (открыть журнальный файл)
 --------------------------------------------------

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

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

      Если требуется  начать  запись  в  дисковый  файл  не  с той
 информации, которая уже имеется в окне регистрации, то прежде чем
 выбрать   команду   Open   Log  File,  необходимо  очистить  окно
 регистрации командой Erase Log.

 = 115 =


 Команда Close Log File
 (закрыть журнальный файл)
 ------------------------------------------------

      Останавливает запись строк журнала в файл, заданный командой
 Open Log File локального меню, после чего файл закрывается.

 Команда Logging
 (регистрация)
 -----------------------------

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

 Команда Add Comment
  (добавить комментарий)
 ------------------------------------------

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

 Команда Erase Log
  (стереть журнал)
 ----------------------------------

      Очищает журнал.  После  этого  окно  регистрации  становится
 пустым. Однако это не влияет на запись журнала в дисковый файл.
                            Простые точки останова                             
 -----------------------------------------------------------------

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

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

      - Переместите курсор к нужной строке исходного текста в окне
 модуля   и  выполните  команду  Breakpoints/Toggle  (или  нажмите
 клавишу F2 или кнопку мыши на  данной  строке).  Выполнение  этой
 команды  для  строки,  на которой уже установлена точка останова,
 вызовет удаление этой точки останова.

      - Переместите курсор к нужной команде в  подокне  кода  окна
 процессора  и  выполните  команду Breakpoints/Toggle (или нажмите
 клавишу F2 или кнопку мыши на  данной  строке).  Выполнение  этой
 команды  для  строки,  на которой уже установлена точка останова,

 = 116 =

 вызовет удаление этой точки останова.

      - Выполните команду Breakpoints/At и введите  адрес  строки,
 на которой требуется установить точку останова. (Адрес кода имеет
 тот же формат,  что и указатели в отлаживаемом  языке.  Выражения
 описаны в главе 9).

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

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

      Если требуется остановить работу программы на десятом вызове
 некоторой функции,  можно установить точку останова в начале этой
 функции  и  использовать  блок  ввода  Pass  Count  блока диалога
 Breakpoint  Options,  который  определяет,   сколько   раз   надо
 пропустить данную точку останова прежде чем она будет включена.

      Если требуется  остановить  работу  программы в определенном
 месте,  но только в том случае, если будет выполнено определенное
 условие,   можно   задать  соответствующее  выражение,  используя
 селективную  кнопку  Expression  True  блока  диалога  Breakpoint
 Options.   Каждый  раз,  когда  будет  встречаться  данная  точка
 останова, отладчик будет вычислять значение выражения, и если оно
 окажется  истинным  (ненулевым),  точка  останова будет включена.
 Этот  способ  можно  использовать  в  сочетании   с   определением
 количества проходов,  что позволит включать точку останова только
 после  того,  как  выражение  становилось  истинным  определенное
 количество раз.

      Используя селективную  кнопку Change Memory локального меню,
 можно определить точку останова,  которая будет включаться только
 в том случае, если изменится значение некоторого элемента данных.
 Этот способ может оказаться значительно  более  эффективным,  чем
 задание глобальной точки останова,  которая тщательно отслеживает
 все  изменения.   Если   требуется   проследить   за   изменением
 какого-либо  элемента  данных  при достижении определенной строки
 исходного  текста,  этот  способ   уменьшает   объем   обработки,
 выполняемой отладчиком для определения момента изменения элемента
 данных.
                           Глобальные точки останова                           

 = 117 =

 -------------------------

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

      - В  блоке  диалога Breakpoint Options включите блок Global.
 Используйте эту команду,  если хотите  задать  условие  включения
 и/или количество проходов, либо если при включении точки останова
 вы хотите выполнить какое-либо  действие,  отличное  от  останова
 программы.

      - Выберите  из  главного  меню  команду  Breakpoints/Changed
 Memory  Global.  Используйте  ее  для  остановки  программы   при
 изменении содержимого области памяти.

      - Выберите  из  главного меню команду Breakpoints/Expression
 True Global.  Используйте эту команду  для  остановки  программы,
 когда выражение становится истинным.

      При задании  глобальной  точки  останова обычно используется
 локальное  меню  окна  Breakpoint,  которое  позволяет   изменить
 условие  или  действие;  в  противном случае точка останова будет
 установлена на каждой строке исходного текста  и  будет  работать
 точно так же, как команда Run/Trace Into главного меню.

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

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

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

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

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



 = 118 =

 Останов при изменении объектов данных
 -------------------------------------

      Если требуется   определить,   в   какой  момент  выполнения
 программы происходит  изменение  значения  определенного  объекта
 данных,  можно  установить  глобальную точку останова,  используя
 один из способов, рассмотренных в предыдущем разделе. Затем можно
 использовать  селективную  кнопку  Changed  Memory  блока диалога
 Breakpoint  Options.  Введите  выражение,  которое  обращается  к
 области  памяти,  за которой требуется следить,  и необязательное
 количество объектов для слежения.

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

      Если установлен   драйвер   аппаратного   отладчика,   Turbo
 Debugger попытается для слежения  за  изменением  области  данных
 установить  "аппаратную"  точку  останова.  Различные  аппаратные
 отладчики  поддерживают  разное   количество   и   разные   виды
 аппаратных  точек останова.  Открыв окно точек останова с помощью
 команды     View/ Breakpoints,  можно проверить,  используется ли
 для  некоторой точки останова аппаратная поддержка.  Каждая точка
 останова,  имеющая аппаратную  поддержку,  помечается  звездочкой
 (*).  Эти точки останова работают значительно быстрее, чем другие
 глобальные точки останова, не имеющие аппаратной поддержки.
                                                                               
Регистрация значений переменных
 -----------------------------------------------------------------

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

      Выберите селективную кнопку Log из блока  диалога Breakpoint
 Options.  Отладчик  попросит ввести выражение,  значение которого
 должно  регистрироваться  каждый  раз,  когда  включается   точка
 останова.  Если  необходимо  регистрировать  значения  нескольких
 переменных, надо задать несколько точек останова.
                                                                               
Выполнение выражений
 -----------------------------------------------------------------

      Выполняя выражение,  имеющее  побочные  эффекты,  при каждом
 включении точки  останова,  можно  эффективно  "вставлять"  новые

 = 119 =

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

      Однако применение  этого  способа ограничено только вставкой
 выражения  перед  выполнением  уже  имеющейся  строки   исходного
 текста;  то  есть  его  нельзя  использовать для непосредственной
 модификации существующих строк программы.



 = 120 =

                                                                               
ГЛАВА 8  ПРОВЕРКА И МОДИФИКАЦИЯ ФАЙЛОВ

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

      В этой  главе  показано,  как проверять и модифицировать два
 вида дисковых файлов: файлы, содержащие исходный текст программы,
 и другие дисковые файлы.
                      Проверка исходных файлов программы                       
 -----------------------------------------------------------------

      Исходные файлы программы - это  файлы,  содержащие  исходный
 текст  программы,  из  которого  был сформирован объектный модуль
 (файл типа EXE).  Обычно эти  файлы  бывают  нужны  при  проверке
 работы  или разработке какого-либо фрагмента программы.  Во время
 отладки часто  требуется  просматривать  исходный  текст  функции
 чтобы  проверить  правильность ее параметров или возвращаемого ею
 значения.

      По ходу выполнения программы  Turbo  Debugger  автоматически
 отображает исходный текст текущего фрагмента программы.

      Файлы, включаемые  в  исходный  текст  программы специальной
 директивой компилятора (директивой #include  в  Си  и  директивой
 INCLUDE  в  ассемблере)  также рассматриваются как исходные файлы
 программы (т.е.,  при выборе View|Module они появляются в подокне
 списка  Pick  a module).  Для просмотра исходных файлов программы
 всегда следует использовать окно модуля,  поскольку это указывает
 отладчику,  что  данный  файл  является исходным модулем.  В этом
 случае он позволяет выполнять различные действия, необходимые для
 отладки,  например,  устанавливать  точки  останова или проверять
 переменные программы, позиционируя курсор в соответствующее место
 программы. Эти и другие приемы описаны в следующем разделе.

 Окно модуля

      Окно модуля  (Module)  открывается  путем выбора из главного
 меню команды View/Module (или нажатием клавиши F3).

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

      Затем Turbo  Debugger  загружает  исходный  файл  выбранного
 модуля. Отладчик ищет исходный файл в следующих местах:


 = 121 =

      -  в директории, куда компилятор помещает файл типа EXE;

      - в  директориях,  заданных  командой       Options/Path  for
 Source или параметром -sd командной строки;

      -  в текущей директории;

      -  в директории, содержащей отлаживаемую программу.


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

      Заметим, что при запуске отладчика Turbo Debugger требуется,
 чтобы отладчику были доступны как файл типа EXE,  так и  исходный
 файл программы.  Turbo Debugger ищет исходные файлы сначала в той
 же  директории,  где  находил  их   компилятор   при   компиляции
 программы, затем в директории, заданной командой Options/Path for
 Source,  затем в текущей директории,  а затем в  директории,  где
 находится файл типа EXE.

      Если после   имени   файла,  указанного  в  заголовке  окна,
 появляется слово modified (модифицирован),  это означает,  что  в
 текст   программы  были  внесены  изменения  после  компиляции  и
 компоновки программы,  в  результате  которых  была  сформирована
 отлаживаемая  программа.  В  результате  этой  модификации номера
 строк подпрограмм в измененном исходном  файле  могут  больше  не
 соответствовать  номерам  строк  в  той  версии  исходного файла,
 которая использовалась  для  построения  отлаживаемой  программы.
 Вследствие   этого,   указатель,   показывающий   текущую  строку
 программы (CS:IP), будет установлен не на той строке.

 Локальное меню окна модуля

      ------------------
      Inspect
      Watch
      ------------------
      Module...
      File...
      ------------------
      Previous
      Line...
      Search...
      Next
      Origin
      Goto...

 = 122 =

      Exit
      ------------------

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

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

      Для вызова локального меню окна модуля  используйте  клавиши
 AltF10. Если разрешено использование активных клавиш в комбинации
 с клавишей Ctrl,  для вызова команды можно нажать клавишу Ctrl  в
 сочетании с  первой  буквой ее названия (например,  Ctrl-S вместо
 Search).


 Команда Inspect
  (проверить)
 ---------------------------

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

      С помощью  клавиши Ins можно выбрать для проверки (выделить)
 целое выражение.  Это исключает необходимость ввода с  клавиатуры
 выражения, которое в явном виде имеется в тексте программы.

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

 Команда Watch
  (следить)
 -----------------------

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

      С помощью  клавиши  Ins  можно  выбрать  для  слежения целое
 выражение.  Это  исключает  необходимость  ввода   с   клавиатуры
 выражения, которое в явном виде имеется в исходном модуле.

 = 123 =


 Команда Module
  (модуль)
 -----------------------

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

 Команда File
  (файл)
 -------------------

      Позволяет выбрать для просмотра один из  нескольких исходных
 файлов,    составляющих    просматриваемый    модуль.    Отладчик
 представляет на экране список,  из которого можно выбрать  нужный
 файл.  В  большинстве  случаев  модуль  состоит  только из одного
 исходного  файла,  который  содержит  исходный  текст  программы.
 Другие   файлы,   включенные  в  модуль  обычно  содержат  только
 определения констант и структур данных. Используйте эту команду в
 том  случае,  если  исходный текст модуля содержится в нескольких
 файлах.

      Для просмотра  первого  файла  используйте  View|File.  Если
 требуется  просматривать  одновременно  более одного файла,  надо
 использовать View/Another/File для открытия последующих окон File.
 Module главного  меню,

 Команда Previos
  (предыдущий)
 ----------------------------

      Возвращает курсор  в  то  место  исходного  модуля,  которое
 просматривалось  ранее.  Эту команду можно также использовать для
 возврата в предыдущее место программы после  выполнения  команды,
 которая изменила положение курсора в исходном модуле.

 Команда Line
  (строка)
 ---------------------

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

 Команда Search
  (найти)
 ----------------------


 = 124 =

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

      Для поиска  можно  использовать   простые   метасимволы:   ?
 соответствует  любому  одному  символу,  а * соответствует нулю и
 более   символов.   При   достижении   конца   файла   поиск   не
 возобновляется   автоматически  с  его  начала.  Для  того  чтобы
 выполнить поиск во всем файле, надо сначала перейти на его первую
 строку, нажав клавиши Ctrl-PgUp.

 Команда Next
  (следующий)
 ------------------------

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

      Иногда бывает так,  что команда Search сначала находит не ту
 строку,  которую  в  действительности требовалось найти.  Команда
 Next позволяет повторять поиск, исключая необходимость повторного
 ввода с клавиатуры искомой строки.

 Команда Origin
  (исходный)
 -------------------------

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

 Команда Goto
  (перейти)
 ----------------------

      Позиционирует курсор в указанное место программы.  Для этого
 надо ввести адрес той строки,  к которой требуется перейти. Можно
 ввести  номер  строки,  имя  функции или шестнадцатиричный адрес.
 Задание адреса строки подробно рассматривается в главе 9.


 = 125 =

      Эту команду можно также вызвать, просто начав вводить метку,
 к  которой требуется перейти.  При этом на экране появляется поле
 запроса, точно  такое  же,  как  если  бы  была  выбрана  команда
 Run|Execute To.  Это  удобная  форма  выбора  часто  используемой
 команды.

 Команда Edit
  (редактировать)
 ----------------------------

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

      Используя окно файла, можно проверять и модифицировать любой
 дисковый  файл.  С  помощью  команд  Ascii  и  Hex,  описанных  в
 следующих  разделах  главы,  содержимое файла можно просматривать
 как в в виде  текста,  так  и  в  виде  шестнадцатиричных  байтов
 данных.

 Окно файла

      Окно файла  (File)  открывается  с помощью команды View/File
 главного меню.  Используя  метасимволы  DOS,  можно  получить  на
 экране  список файлов и выбрать из него нужный файл.  Можно также
 ввести имя конкретного файла с клавиатуры.

      В окне файла отображается содержимое выбранного  файла.  Имя
 просматриваемого файла отображается в верхней части окна вместе с
 номером  строки,  на  которой   находится   курсор   (если   файл
 просматривается в текстовом формате).

      Когда окно файла открывается в первый раз, файл отображается
 в нем либо в  текстовом,  либо  в  шестнадцатиричном  формате,  в
 зависимости от того, какая информация в нем содержится: текст или
 двоичные данные.  С помощью команды Display As,  описанной  ниже,
 можно   в   любой   момент   перейти   из  текстового  формата  в
 шестнадцатиричный и наоборот.

 Локальное меню окна файла

      ---------------------
      Goto
      Search
      Next
      ---------------------
      Display as      Ascii

 = 126 =

      File...
      Edit
      ---------------------

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

      Для того чтобы вызвать локальное меню окна File, надо нажать
 клавиши Alt-F10.  Если разрешено использование активных клавиш  в
 комбинации  с  клавишей  Ctrl,  для  вызова  команды можно нажать
 клавишу Ctrl в сочетании с первой буквой ее названия.


 Команда Goto
  (перейти)
 ----------------------

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

 Команда Search
  (найти)
 ----------------------

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

      Если файл отображается в текстовом формате для  поиска можно
 использовать простые метасимволы:  ?  соответствует любому одному
 символу, а * соответствует нулю и более символов.

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

 информация о последовательностях байтов приведена в главе 9.

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

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

 Команда Next
  (следующий)
 ------------------------

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

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

 Команда Display As
  (формат отображения)
 ---------------------------------------

      Переключает режим   отображения   содержимого    файла    из
 текстового  (ASCII) формата в шестнадцатиричный и наоборот.  Если
 выбрать текстовый формат,  файл будет отображаться  на  экране  в
 таком  же  виде,  как  и  при  просмотре  его с помощью текстового
 редактора.  Если  выбрать  шестнадцатиричный  формат,  то  каждая
 строка  файла  будет  начинаться  с  шестнадцатиричного  смещения
 байтов этой строки относительно начала  файла.  В  каждой  строке
 отображается 8 или 16 байтов в зависимости от ширины окна. Справа
 от шестнадцатиричных данных отображаются символы, соответствующие
 отображаемым байтам. При этом отображается полный набор символов,
 то есть для байтовых  значений  меньше  32  и  больше  127  будут
 отображаться соответствующие им символы.

 Команда File
  (файл)
 -------------------

      Позволяет выбрать  для  просмотра  другой  файл.   Используя
 метасимволы  DOS,  можно  получить  на экране список и выбрать из
 него нужный файл.  Можно также ввести  с  клавиатуры  точное  имя
 файла,   который   требуется  загрузить.  Эта  команда  позволяет
 просматривать другой файл,  не открывая еще  одного  окна  файла.
 Если  требуется  просматривать  одновременно два разных файла или

 = 128 =

 две разных части одного файла, надо воспользоваться командой View
 /Another/File, которая откроет новое окно файла.

 Команда Edit
  (редактировать)
 ----------------------------

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

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




 = 129 =

                              ГЛАВА 9  ВЫРАЖЕНИЯ                               

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

      Turbo Debugger может вычислять значения выражений и сообщать
 программисту результат.  Выражения можно также  использовать  для
 обращения  к  определенной  области  памяти,  содержимое  которой
 необходимо проверить.  Выражение может быть введено  в  ответ  на
 любой  запрос  отладчика,  в котором требуется значение или адрес
 ячейки памяти.  (Заметим,  что в каждом языке  используются  свои
 правила вычисления выражений.)

      Для вычисления  значения  введенного  выражения используется
 команда   Data/Evaluate/Modify,    открывающая    блок    диалога
 Evaluate/Modify.  Эту  команду  можно использовать как в качестве
 простого калькулятора,  так и  для  проверки  значений  элементов
 данных отлаживаемой программы.

      В этой  главе описывается,  как Turbo Debugger выбирает язык
 программирования для вычисления значений выражений,  и как  можно
 заставить   его   использовать   конкретный   язык.   Описываются
 компоненты выражений,  которые являются общими для  всех  языков,
 такие  как  номера строк исходного текста и обращения к регистрам
 процессора.  Затем описываются компоненты,  из  которых  строятся
 выражения  в  каждом из языков,  такие как константы,  переменные
 программы,  строки и знаки операций. Для каждого языка приводится
 перечень  операций,  поддерживаемых отладчиком Turbo Debugger,  и
 описывается синтаксис выражений.

      Для получения  более   подробной   информации   о   правилах
 построения выражений в языках Си,  Паскаль и ассемблер обратитесь
 к  соответствующей  документации:  Руководству   пользователя   и
 Справочному  руководству по компилятору Turbo C (Turbo C Compiler
 User's Guide  и  Reference  Guide),  Руководству  пользователя  и
 Справочному  руководству  по  языку  Turbo  Pascal  (Turbo Pascal
 User's Guide и Reference Guide) или  Справочному  руководству  по
 языку Turbo Assembler (Turbo Assembler Reference Guide).
                     Выбор языка для вычисления выражений                      
 ------------------------------------

      Обычно Turbo Debugger определяет,  какой  язык  использовать
 для  вычисления выражений,  анализируя расширение имени исходного
 файла  текущего  модуля,  то  есть  модуля,   на   котором   было
 остановлено выполнение программы.  Это определение можно отменить
 с помощью команды  Options/Language,  которая  позволяет  выбрать
 один  из  трех языков:  Си,  Паскаль или ассемблер.  Если выбрана
 опция  Source,  выражения  будут  вычисляться  в  соответствии  с

 = 130 =

 правилами  языка  исходного файла.  (Если Turbo Debugger не может
 определить,  на каком языке написана программа, он использует для
 вычисления выражений правила языка Си.

      Обычно Turbo  Debugger сам правильно определяет,  какой язык
 надо использовать.  Однако в некоторых  случаях  может  оказаться
 полезным   точно  указать  отладчику,  какой  язык  использовать,
 например, при отладке ассемблерного модуля, который вызывается из
 программы, написанной на другом языке. Точно указав язык, который
 должен использоваться для вычисления выражений,  можно обращаться
 к данным так,  как это принято в данном языке,  даже если текущий
 модуль написан на другом языке.

      Иногда бывает рассматривать выражения  или  переменные,  как
 если бы  они  были  написаны на другом языке;  например,  если вы
 отлаживаете Паскаль-программу, соглашения языка ассемблера или Си
 могут давать  более  простой  способ  изменения  значения  байта,
 хранимого в строке.

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

      Даже если при  входе  в  Turbo  Debugger  намеренно  выбрать
 неправильный язык,   Е   В   способен   самостоятельно   получить
 информацию о языке из  таблицы  символических  имен  и  исходного
 файла. Однако, при некоторых обстоятельствах Turbo Debugger может
 иметь проблемы,  связанные с неверным  способом  хранения  данных
 вследствие неоднозначности определения языка.
                   Адреса кода, адреса данных и номера строк                   
 -----------------------------------------------------------------

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

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

 -----------------------------------------
 Язык       Формат      Пример

 = 131 =

 -----------------------------------------
 Си         0xnnnn      0x1234:0x0010
 Паскаль    $nnnn       $1234:$0010
 Ассемблер  nnnnh       1234h:0B234h

      В ассемблере шестнадцатиричные числа,
 начинающиеся с цифр от A до E, должны иметь
 ведущий ноль.
 -----------------------------------------
             Доступ к идентификаторам вне текущей области действия             
 -----------------------------------------------------------------

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

      Как правило, Turbo Debugger ищет идентификатор, используемый
 в выражении точно так же,  как это делает  компилятор.  Например,
 компилятор  языка  Си  сначала  ищет  в текущей функции,  затем в
 текущем модуле статический  (локальный)  идентификатор,  а  затем
 глобальный идентификатор. Компилятор языка Паскаль сначала ищет в
 текущей процедуре или функции,  затем в вызвавшей ее подпрограмме
 (если  текущая  область  действия  является  вложенной),  затем в
 разделе реализации текущего модуля (если текущая область действия
 находится в модуле), а затем ищется глобальный идентификатор.

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

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

 Замена области действия

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

      Обычно для   разделения   компонентов    области    действия
 используется  знак  номера (#).  Кроме того,  если в данном языке
 точка (.) не имеет другого назначения,  она может  использоваться

 = 132 =

 вместо знака номера.

      Для замены  области  действия  идентификатор  записывается в
 следующем формате:

      [#модуль[#имя файла]]#номер строки[#имя переменной]

      или

      [#модуль[#имя файла]][#имя функции]#имя переменной

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

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


      #123                          Строка 123 текущего модуля.

      #123#myvar1                   Идентификатор myvar1,
                                    находящийся в строке 123
                                    текущего модуля.

      #mymodule#123                 Строка 123 модуля mymodule.

      #mymodule#123#myvar1          Идентификатор myvar1,
                                    находящийся    в строке 123
                                    модуля mymodule.

      #mymodule#file1#123           Строка 123 исходного файла
                                    file1, который является частью
                                    модуля mymodule.

      #mymodule#file1#123#myvar1    Идентификатор myvar1,
                                    находящийся в стоке 123
                                    исходного файла file1, который
                                    является частью модуля
                                    mymodule.

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

      #myvar2                       То же, что и myvar2 без #.

      #myfunc#myvar                 Переменная myvar2 подпрограммы

 = 133 =

                                    myfunc.

      #mymodule#myvar2              Переменная myvar2 модуля
                                    mymodule.

      #mymodule#myfunc#myvar2       Переменная myvar2 подпрограммы
                                    myfunc модуля mymodule.

      #mymodule#file2#myvar2        Переменная myvar2 из файла
                                    file2, включенного в модуль
                                    mymodule.

      #mymodule#file2#myfunc#myvar2 Переменная myvar2 функции
                                    myfunc, определенной в файле
                                    file2, описанном в модуле
                                    mymodule.

      И наконец,  Turbo Debugger позволяет замену области действия
 при использовании имен объекта,  класса,  правила и  компонентной
 функции. Вот несколько примеров:

      AnInstance                    Вхождение AnInstance, доступное
                                    в текущей области действия.

      AnInstance.AField             Поле AField, доступное через
                                    вхождение AnInstance, доступное
                                    в текущей области действия.

      AnObjectType.AMethod          Правило AMethod, доступное
                                    через объект типа AnObjectType,
                                    доступный в текущей области
                                    действия.

      AnInstance.AMethod            Правило AMethod, доступное
                                    через вхождение AnInstance,
                                    доступное в текущей области
                                    действия

      AUnit.AnInstance.AField       Поле AField, доступное через
                                    вхождение AnInstance, доступное
                                    через модуль AUnit.

      AUnit.AnObjectType.AMethod    Правило AMethod,  доступное
                                    через объект типа AnObjectType,
                                    доступный через модуль AUnit.

      AUnit.AnObjectType.AMethod.   Локальная переменная AVar,
      ANestedProc.AVar              доступная через процедуру
                                    ANestedProc, доступную через
                                    правило AMethod, доступное
                                    через тип объекта AnObjectType,

 = 134 =

                                    доступный через модуль AUnit.

      Такие выражения  с квалифицированными идентификаторами можно
 использовать везде, где возможно использование выражения, включая
 блок диалога  Evaluate/Modify и окно Watches,  либо при изменении
 выражения в окне Inspector,  либо  при  использовании  локального
 меню в  окне  Module для перехода (Goto) к правилу,  компонентной
 функции или процедуре в исходном коде.

      Если вы при отладке программы  на  С++  желаете  исследовать
 функцию с перегруженным именем, введите это имя в соответствующем
 блоке ввода.  Turbo Debugger откроет блок диалога Pick  A  Symbol
 Name с  блоком  списка  всех  функций,  имеющих данное имя,  и вы
 сможете выбрать желаемое.

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

      Когда Turbo Debugger вычисляет значение выражение, он должен
 решить,   какая   часть  программы  является  "текущей"  областью
 действия,  то есть областью действия идентификаторов,  записанных
 без  замены  области  действия.  Во  многих  языках  это является
 важным,  поскольку идентификаторы,  описанные внутри  процедур  и
 функций,    могут    совпадать   по   написанию   с   глобальными
 идентификаторами.  Поэтому Turbo  Debugger  должен  знать,  какой
 экземпляр идентификатора имеется в виду.

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

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

      При выполнении    некоторых    команд    требуется   вводить
 последовательности байтов.  К  ним  относятся  команды  Search  и
 Change  локального  меню подокна данных окна процессора,  а также
 команды Search и Change локального меню окна файла, отображающего
 содержимое файла в шестнадцатиричном формате.

 = 135 =


      В последовательности   байтов   могут  сочетаться  скалярные
 значения (без плавающей точки) и строки,  записанные  в  формате,
 допустимым   в   текущем   языке,  выбранным  с  помощью  команды
 Options/Language.  Для  записи  строк  и  скалярных  значений   в
 выражениях используется одинаковый синтаксис.  Скалярные значения
 преобразуются  в  последовательность  байтов,  например  значение
 123456  типа  longint  языка  Паскаль  преобразуется в 4-байтовое
 шестнадцатиричное значение 40 E2 01 00.

      ---------------------------------------------------------
      Язык           Последовательность       Шестнадцатиричное
                          байтов                   значение
      ---------------------------------------------------------
      Си                "ab"0x04"c"             61 62 04 63
      Паскаль           'ab'#4'c'               61 62 04 63
      Ассемблер         1234 "AB"               34 12 41 42
      ---------------------------------------------------------
                              Выражения языка Си                               
 -----------------------------------------------------------------

      Turbo Debugger полностью поддерживает  синтаксис  выражений,
 принятый  в  языке  Си.  Выражение может включать идентификаторы,
 знаки  операций,  строки,  переменные  и   константы.   Все   эти
 компоненты описаны в следующих разделах.

 Идентификаторы языка Си

      Идентификатор -  это  имя  элемента данных или подпрограммы,
 принятое в программе. Идентификатор должен начинаться с буквы или
 символа   подчеркивания  (_).  Далее  могут  следовать  такие  же
 символы, а также цифры от 0 до 9. При вводе идентификатора первый
 символ  подчеркивания  можно опускать.  Если идентификатор введен
 без подчеркивания и  он  не  может  быть  найден,  в  его  начало
 добавляется  символ подчеркивания и поиск повторяется.  Поскольку
 обычно  компилятор   ставит   символ   подчеркивания   в   начало
 идентификаторов,  это  освобождает  пользователя от необходимости
 добавлять его самому.

 Регистровые псевдопеременные языка Си

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

      ----------------------------------------------------------
      Псевдопеременная         Тип                 Регистр
      ----------------------------------------------------------
           _AX            unsigned int               AX

 = 136 =

           _AL            unsigned char              AL
           _AH            unsigned char              AH

           _BX            unsigned int               BX
           _BL            unsigned char              BL

                              117
           _BH            unsigned char              BH

           _CX            unsigned int               CX
           _CL            unsigned char              CL
           _CH            unsigned char              CH

           _DX            unsigned int               DX
           _DL            unsigned char              DL
           _DH            unsigned char              DH

           _CS            unsigned int               CS
           _DS            unsigned char              DS
           _SS            unsigned char              SS
           _ES            unsigned char              ES

           _SP            unsigned int               SP
           _BP            unsigned char              BP
           _DI            unsigned char              DI
           _SI            unsigned char              SI

           _IP            unsigned int               IP
      ----------------------------------------------------------

      Следующие псевдопеременные  обеспечивают  доступ к регистрам
 процессора 80386.

      -----------------------------------------------------
      Псевдопеременная         Тип                 Регистр
      -----------------------------------------------------
           _EAX           unsigned long              EAX
           _EBX           unsigned long              EBX
           _ECX           unsigned long              ECX
           _EDX           unsigned long              EDX

           _ESP           unsigned long              ESP
           _EBP           unsigned long              EBP
           _EDI           unsigned long              EDI
           _ESI           unsigned long              ESI

           _FS            unsigned int               FS
           _GS            unsigned int               GS
      -----------------------------------------------------

 Константы и форматы чисел языка Си

 = 137 =


      Константы могут  быть  либо  целыми числами,  либо числами с
 плавающей точкой.

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

           --------------------------------------
           Формат              Система счисления
           --------------------------------------
           цифры               Десятичная
           0цифры              Восьмеричная
           0Xцифры             Шестнадцатиричная
           0xцифры             Шестнадцатиричная
           --------------------------------------

      Обычные константы  имеют тип int (16 битов).  Если требуется
 определить константу типа long,  после ее значения надо поставить
 букву l или L, например 123456L.

      Константа с  плавающей  точкой  содержит  десятичную точку и
 может записываться в  десятичном  или  экспоненциальном  формате,
 например,

      1.234  4.5e+11

 Строки символов и Esc-последовательности языка Си
 -----------------------------------------------------------------

      Строка представляет   собой   последовательность   символов,
 заключенная   в  кавычки  ("").  В  качестве  символа  Esc  можно
 использовать принятый в Си обратный слеш (\).

      ------------------------------------------------------
      Последовательность  Значение       Символ
      ------------------------------------------------------
      \\                                 Обратный слеш
      \a                  0X07           Звуковой сигнал
      \b                  0X08           Стирание влево
      \f                  0X0C           Перевод страницы
      \n                  0X0A           Перевод строки
      \r                  0X0D           Возврат каретки
      \t                  0X09           Горизонтальная
                                         табуляция
      \v                  0X0B           Вертикальная
                                         табуляция
      \xnn                nn             Шестнадцатиричное
                                         байтовое значение
      \nnn                nnn            Восьмеричное
                                         байтовое значение

 = 138 =

      ------------------------------------------------------

      Если после обратного слеша поставить любой из указанных выше
 символов,  этот символ будет вставлен в строку в неизменном виде.

 Операции языка Си и старшинство операций

      В отладчике Turbo Debugger используются те же  операции, что
 и  в  языке  Си,  и установлено такое же старшинство операций.  В
 отладчике предусмотрена одна дополнительная операция,  которая не
 входит  в  набор  операций  языка  Си:  она  обозначается двойным
 двоеточием (::).  Эта операция имеет более высокий приоритет, чем
 все  операции  языка  Си  и  используется  для создания константы
 дальнего  адреса  из  выражения,  стоящего  слева  и   выражения,
 стоящего справа. Например,

      0X1234::0X1000  _ES::_BX

      Первостепенные операции

      () [] . -> sizeof

 имеют высший приоритет и выполняются слева направо. Унарные операции

      * & - !  ++ --

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

      высший    * / %
                + -
                >> <<
                <> <= >=
                == !=
                &
                ^
                |
                &&
      низший    ||

      Единственная троичная  операция  ?:   имеет   более   низкий
 приоритет, чем все бинарные операции.

      Все операции  присваивания  имеют  равный  приоритет,  более
 низкий, чем троичная операция, и группируются справа налево.

      = += =+ *= /= \= >>= <<= &= ^= |=


 = 139 =

 Выполнение функций в си-программе

      Из выражения на языке Си можно вызывать  функции  точно  так
 же,  как это делается в исходном тексте программы. Turbo Debugger
 будет выполнять программу с заданными аргументами  функции.  Этот
 способ   может   оказаться  очень  удобным  для  проверки  работы
 написанной функции.  Можно вызывать ее несколько  раз  с  разными
 аргументами и каждый раз проверять возвращаемое ею значение.

      Допустим, в  программе  имеется  следующая функция,  которая
 возводит число x в степень y:

      long power(int x, int y) {
         long temp = 1;
         while (y--)
            temp *= x;
         return(temp);
      }

      Приведенная ниже  таблица  показывает  результаты выполнения
 этой функции при вызове ее с разными аргументами.

           ----------------------------------------------
           Выражение           Результат
           ----------------------------------------------
           power(3,2)*2        18
           25 + power(5,8)     390650
           power(2)            Ошибка (пропущен аргумент)
           ----------------------------------------------

 Выражения языка Си с побочными эффектами

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

      Операции присваивания  (=,  +=  и  т.д.)  изменяют  значение
 элемента  данных,  записанного слева от знака операции.  Операции
 приращения и отрицательного приращения (++ --)  изменяют значение
 элемента  данных,  который  записан  справа  или слева от них,  в
 зависимости от того,  используются ли они в  качестве  префиксной
 или постфиксной операции.

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


 = 140 =

      myfunc(1,2,3) + 7


      то позже программа может начать работать  неправильно  из-за
 того,  что  функция  myfunc  изменила  значения других переменных
 программы.

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

      Отладчик Turbo  Debugger  позволяет   явно   указывать   тип
 указателя   точно  так  же,  как  это  делается  в  си-программе.
 Преобразование типа  содержит  описание  типа  данных  языка  Си,
 заключенное  в  круглые  скобки.  Оно  должно  быть  записано  до
 выражения, в котором вычисляется указатель на область памяти.

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

      (long far *)0x3456::0
      (char far *)_ES::_BX

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

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

      *(int *)iptr

      Для этого также служит команда  Type  Cast  локального  меню
 окна Inspector.

      Для преобразования типа в  отладчике  Turbo  Debugger  можно
 использовать следующие зарезервированные слова языка Си:

      char                float               near
      double              huge                short
      enum                int                 struct
      far                 long                union
                                              unsigned
                            Выражения языка Паскаль                            
 -----------------------------------------------------------------

 = 141 =


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

 Идентификаторы языка Паскаль

      Идентификаторами в   языке   Паскаль  являются  определяемые
 пользователем имена элементов данных и  подпрограмм, используемые
 в  программе.  Идентификатор  в  языке Паскаль может начинаться с
 буквы (a-z,  A-Z) или  символа  подчеркивания  (_).  Далее  могут
 следовать цифры (0-9), символы подчеркивания и буквы.

      Обычно идентификатор  подчиняется правилам области действия,
 которые гласят, что "вложенные" локальные идентификаторы заменяют
 другие  идентификаторы  с  теми  же  именами.  Это  правило можно
 обойти,  если требуется обратиться к идентификаторам, находящимся
 в   других  областях  действия.  Для  получения  более  подробной
 информации обратитесь к разделу  "Доступ  к  идентификаторам  вне
 текущей области действия" данной главы.

 Константы и форматы чисел языка Паскаль

      Константы могут  быть  либо  целыми,  либо  вещественными (с
 плавающей точкой).  Отрицательные константы начинаются  со  знака
 "минус" (-).  Если в числе имеется десятичная точка или символ e,
 означающий  экспоненту,  то  это  число  является   вещественным,
 например,

      123.4  456e34  123.45e-5

      Целочисленные константы  обычно  записываются  в  десятичном
 формате,  но могут записываться и в шестнадцатиричном формате.  В
 этом   случае   перед   константой  ставится  знак  доллара  ($).
 Десятичные целочисленные константы должны лежать в диапазоне от -
 2137483648  до  2137483647.  Шестнадцатиричные  константы  должны
 лежать в диапазоне от $00000000 до $FFFFFFFF.

 Строки языка Паскаль

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

      'abc'

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


 = 142 =

      'def'#7'xyz'

 Операции языка Паскаль

      Turbo Debugger   поддерживает  все  операции,  допустимые  в
 выражениях паскаль-программы.

      Унарные операции  имеют  высший  приоритет  по  отношению  к
 другим операциям и равный приоритет между собой.

      @         Получение адреса переменной
      ^         Значение указателя
      not       Побитовое дополнение
      тип       Преобразование типа
      +         Унарный плюс, положительное число
      -         Унарный минус, отрицательное число

      Бинарные операции имеют более низкий приоритет и расположены
 в порядке понижения приоритета.

      * / div mod and shl shr
      in + - or xor
      < <= > <= = <>

      Операция присваивания   (:=)   имеет   низший   приоритет  и
 возвращает некоторое значение, так же как и в Си.

 Вызов процедур и функций паскаль-программы

      Обращения к  функциям  могут  производиться  из   выражений.
 Например,  допустим,  что  в  паскаль-программе  описана  функция
 HalfFunc, которая выполняет деление целого числа на 2:

      function HalfFunc(i: integer): real;

      Используя команду   Data/Evaluate/Modify,   можно   вызывать
 функцию HalfFunc следующим образом:

      HalfFunc(3)
      HalfFunc(10)=HalfFunc(10 div 2)

      Можно также  вызывать  процедуры,  хотя,  конечно,   не   из
 выражений.  Если  ввести  одно  имя процедуры или функции,  Turbo
 Debugger укажет ее адрес  и  описание.  Для  того  чтобы  вызвать
 процедуру или функцию,  для которой не требуется параметров, надо
 поставить после ее имени пустые круглые скобки, например,

      MyProc()       Вызывает процедуру MyProc
      MyProc         Указывает адрес процедуры MyProc и т.д.
      MyFunc=5       Сравнивает адрес функции MyFunc с числом 5
      MyFunc()=5     Вызывает функцию MyFunc и сравнивает

 = 143 =

                     возвращенное ею значение с числом 5.
                          Выражения языка ассемблера                           
 -----------------------------------------------------------------

      Turbo Debugger  полностью  поддерживает  синтаксис выражений
 языка  ассемблера.  Выражение   состоит   из   операций,   строк,
 переменных  и  констант.  В  следующих  разделах  описаны все эти
 компоненты.

 Идентификаторы языка ассемблера

      Идентификаторами являются определяемые  пользователем  имена
 элементов   данных   и  подпрограмм,  используемые  в  программе.
 Идентификатор в языке ассемблера начинается с  буквы  (a-z,  A-Z)
 или  одного из следующих символов:  @ ?  _ $.  Далее могут стоять
 цифры от 0 до 9  и  такие  же  символы.  Точка  (.)  также  может
 использоваться  в качестве первого символа идентификатора,  но не
 может находиться внутри него.

      Специальный символ $ означает текущую  точку  программы,  на
 которую указывает регистровая пара CS:IP.

 Константы языка ассемблера

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

      1.234  4.5e+11

      Целочисленные константы   записываются  в  шестнадцатиричном
 формате или к ним применяется один из способов  изменения системы
 счисления языка ассемблера.

           --------------------------------------
           Формат              Система счисления
           --------------------------------------
           цифры               Шестнадцатиричная
           цифрыO              Восьмеричная
           цифрыQ              Восьмеричная
           цифрыD              Десятичная
           цифрыB              Двоичная
           --------------------------------------

      Шестнадцатиричное число  всегда должно начинаться с цифры от
 0 до 9.  Если требуется ввести число, начинающееся с буквы (A-F),
 надо поставить перед ним цифру 0.

 Операции языка ассемблера


 = 144 =

      Turbo Debugger   поддерживает   большинство  операций  языка
 ассемблера,  которые  расположены   ниже   в   порядке   убывания
 приоритета.

      xxxPTR(BYTE PTR...)
      . (выбор элемента структуры)
      : (смена сегмента)
      OR XOR
      AND
      NOT
      EQ NE LT LE GT GE
      + -
      * / MOD SHR SHL
      Унарный +, унарный -
      OFFSET SEG
      () []

      Значение переменной может быть изменено с  помощью  операции
 присваивания, например,

      a = [BYTE PTR DS:4]
                              Управление форматом                              
 -----------------------------------------------------------------

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

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

      ---------------------------------------------------------------
      Символ                        Формат
      ---------------------------------------------------------------
      c         Отображает символьное или строковое выражение в
                виде необработанных символов. Обычно непечатаемые
                символьные значения отображаются в виде Esc-
                последовательностей или десятичных чисел. Этот
                указатель формата заставляет отладчик отображать
                символы, используя полный набор символов фирмы IBM.
      d         Отображает целочисленные значения в десятичном
                формате.
      f[#]      Отображает число в формате с плавающей точкой с
                указанным количеством цифр. Если количество цифр не

 = 145 =

                указано, используется столько цифр, сколько
                необходимо.
      m         Отображает выражение, обращающееся к памяти, в виде
                шестнадцатиричных байтов.
      md        Отображает выражение, обращающееся к памяти, в виде
                десятичных байтов.
      p         Отображает необработанное ссылочное значение,
                указывая (если возможно) в качестве сегмента
                название регистра. Показывает также объект, на
                который оно указывает. Если не задан указатель
                формата, этот формат используется по умолчанию.
      s         Отображает массив или указатель на массив в виде
                заключенной в кавычки строки символов. Стока
                заканчивается нулем.
      x или h   Отображает целое число в шестнадцатиричном формате.

      ---------------------------------------------------------------



 = 146 =

                                                                               
ГЛАВА 10 Отладка программ на С++ и объектно-ориентированном Паскале
 -----------------------------------------------------------------

      Для того,   чтобы   соответствовать   требованиям   С++    и
 объектно-ориентированного Паскаля,      Turbo     Debugger     был
 усовершенствован, и теперь  поддерживает  объектно-ориентированное
 программирование. Для  использования этих новых средств требуется
 Turbo Pascal версии 5.5 или Turbo С++,  а  также  Turbo  Debugger
 версии 2.0.

      Помимо расширений,  позволяющих трассировку объектных правил
 или компонентных функций класса,  а также  исследование  объектов
 или классов  в блоке диалога Evaluate/Modify и окне Watch,  Turbo
 Debugger 2.0 имеет  специальный  набор  окон  и  локальных  меню,
 специально разработанных для работы с объектами и классами.
                                Окно Hierarchy                                 
 -----------------------------------------------------------------

      Turbo Debugger  имеет  специальное  окно  для   исследования
 иерархической структуры  объектов  или классов.  В это окно можно
 войти, выбрав View|Hierarchy.

      Окно Hierarchy выводит на дисплей информацию о типах объектов
 и  классов,  а  не  об их конкретных вхождениях.  В левом подокне
 перечислены в алфавитном порядке типы,  используемые отлаживаемым
 модулем.  В  правом подокне (два подокна используется при отладке
 программы на С++  с  множественным  наследованием)  показаны  все
 объекты  или  классы  и  их  иерархия  с использованием линейного
 графика, на котором базовый тип помещается в левой части подокна,
 а  нисходящие от него типы (которые также могут являться предками
 в случае класса с множественным наследованием)  помещаются справа
 от базового типа, и линиями показаны взаимосвязи между предками и
 их потомками.

 Подокно Object Type List (список типов объектов)  ---------------

      В левом подокне находится алфавитный  список  всех  объектов
 или типов класса,  используемых текущим модулем.  Для того, чтобы
 не перемещать  курсор  среди  большого  числа  элементов  списка,
 используется средство    инкрементного    сопоставления:    когда
 светящаяся линейка находится  в  левом  подокне,  просто  начните
 набирать нужное имя объекта или типа класса, и при каждом нажатии
 клавиши Turbo  Debugger  будет  высвечивать  первый   из   типов,
 соответствующих набранным к этому моменту символам.

      Для открытия    окна   Inspector   для   высвеченного   типа
 объекта/класса нажмите  Enter.  Эти  окна  описаны  на  стр.  158
 оригинала.

 Локальное меню подокна Object Type/Class   ----------------------

 = 147 =


      ---------
      Inspect
      Tree
      ---------

      Для вывода  на  дисплей  локального  меню  данного   подокна
 нажмите Alt-F10. Если при помощи DINST вы разрешили использование
 активных клавиш,  то можно ими  воспользоваться.  Локальное  меню
 содержит два пункта: Inspect и Tree.

 Команда Inspect
 ---------------

      Выводит для высвеченного типа объекта/класса окно Inspector.

 Команда Tree
 ------------

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

 Подокно Hierarchy Tree   ----------------------------------------

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

      Для нахождения  отдельного объекта или типа класса в сложном
 иерархическом дереве перейдите в левое подокно  и  воспользуйтесь
 средством инкрементного  поиска;  затем выберите в локальном меню
 пункт Tree  для  возврата  в  подокно  с  иерархическим  деревом.
 Соответствующий тип появится под высвеченной линейкой.

      При нажатии   Enter  для  высвеченного  типа  появится  окно
 Inspector для типов объект/класс.

      Если вы загрузили программу на  С++,  использующую  классы  с
 множественным наследованием,  то появится третье подокно,  Parent
 Tree, располагающееся  ниже  подокна  Hierarchy   Tree   в   окне
 Hierarchy. Если исследуемый класс имеет несколько предков, и если
 команда Parent локального меню подокна Hierarchy Tree установлена
 в состояние    Yes,   то   в   подокне   Parent   Tree   появится
 реверсированное дерево и сообщение Parents  of  Class  ("Родители
 класса") в левой части подокна и "предки",  расположенные вниз  и
 вправо относительно этого сообщения,  причем линиями обозначаются
 взаимосвязи между предками и потомками.


 = 148 =

      Вы можете   открыть   окно   Inspector   для   любого   типа
 объект/класс, находящегося в подокне Parent Tree, как для подокна
 Hierarchy Tree.

 Локальное (локальные) меню подокна Hierarchy Tree
 -------------------------------------------------

      -------------
      Inspect
      -------------

      -------------
      Inspect
      Parents   Yes
      -------------

      Локальное меню  (Alt-F10 в правом подокне) подокна Hierarchy
 Tree имеет только один пункт Inspect. При выборе этого пункта для
 высвеченного типа    появляется    окно    Inspector   для   типа
 объекта/класса.

      Если вы загрузили программу на С++,  использующую классы  с
 множественным наследованием,  то локальное меню подокна Hierarchy
 Tree содержит и вторую команду, Parents. Эта команда работает как
 переключатель ,  при  помощи  которого  вы  можете управлять тем,
 показывать ли предков данного класса в подокне Parent  Tree.  Это
 полезно, когда   исследуемый   вами   класс  имеет  множественное
 наследование. По умолчанию команда Parents имеет значение Yes.

 Локальное меню подокна Parent Tree
 ----------------------------------

      ------------
      Inspect
      ------------

      Turbo Debugger   имеет   специальный   тип  окна  Inspector,
 позволяющий проверять детали объекта: окно Inspector типа объект/
 класс. В  этом  окне  сведена  информация  о данном типе,  а не о
 конкретных вхождениях этого типа в переменные.
                       Окна Inspector типа объект/класс                        

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

      Если высвеченное  поле  данных  является  объектом или типом

 = 149 =

 класса, либо указателем  объекта  или  типа  класса,  то  нажатие
 Enter откроет   для   этого   поля  другое  окно  Inspector  типа
 объект/класс. (Это идентично выбору команды Inspect  в  локальном
 меню данного подокна). Таким образом, сложные вложенные структуры
 объектов или классов  можно  просматривать  быстро,  с  минимумом
 нажатий клавиш.

      Для краткости  параметры  правила или компонентной функции в
 окне Inspector типа объект/класс не показываются. Для того, чтобы
 исследовать их   параметры,   нужно  высветить  интересующие  вас
 правило или компонентную функцию и нажать Enter.  появляется окно
 Inspector для  правил/компонентных  функций.  В  верхнем  подокне
 этого окна показан адрес кода для реализации в данном объекте или
 типе класса выбранного правила или компонентной функции,  а также
 имена и типы всех параметров.  Если ваша  программа  написана  на
 объектно-ориентированном Паскале,   то   нижнее  подокно  содержит
 указание на  то,  является  ли  данное  правило  процедурой   или
 функцией.

      Нажатие Enter    в    любой   точке   окна   Inspector   для
 правил/компонентных функций вызывает на передний план окно Module
 с курсором,   установленным   на  коде,  реализующем  проверяемые
 правило или компонентную функцию.

      Как и при стандартной проверке,  Esc закрывает текущее  окно
 Inspector, а Alt-F3 закрывает все эти окна.

 Локальное меню окна Inspector типа объект/класс   ---------------

      Нажатие Alt-F10  вызывает  локальное  меню  каждого подокна.
 Если в TDINST  разрешены  активные  клавиши,  вы  можете  выбрать
 элемент локального  меню,  нажав  Ctrl  и  первую  букву названия
 данного элемента.

      --------------------
      Inspect
      Hierarchy
      Show inherited   Yes
      --------------------

      Локальное меню подокна Object Data Field имеет три элемента:

 Команда Inspect
 ---------------

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

 Команда Hierarchy
 -----------------

 = 150 =


      Открывает окно Hierarchy  для  инспектируемого  объекта  или
 типа. Окно Hierarchy описано на стр. 155 оригинала.

 Команда Show Inherited
 ----------------------

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

      -------------------
      Inspect
      Hierarchy
      Show inherited  Yes
      -------------------

      Локальное меню  нижнего  подокна Object Method имеет команды
 Inspect, Hierarchy и Show Inherited.

 Команда Inspect
 ---------------

      Для высвеченного элемента открывается окно Inspector правил/
 компонентных функций.   При   нажатии    Ctrl-I    с    курсором,
 установленном на адресе, показанном в этом окне, на передний план
 вызывается окно  Module  с  курсором,  установленном   на   коде,
 реализующем инспектируемое правило/функцию.

 Команда Hierarchy
 -----------------

      Открывает окно Hierarchy  для  инспектируемого  объекта  или
 типа класса. Окно Hierarchy рассматривается на стр.155 оригинала.

 Команда Show Inherited
 ----------------------

      Для этой команды умолчанием является значение  Yes.  В  этом
 случае   все   правила  или  компонентные  функции  показываются,
 независимо  от  того,  определены  ли   они   в   пределах   типа
 инспектируемого   объекта   или   класса,   или   наследуются  от
 порождающего   типа.   При   установке   No   выводятся    только
 правила/функции, определенные в пределах инспектируемого типа.
                       Окна Inspector вхождений объекта                        
 -----------------------------------------------------------------


 = 151 =

      Окна Inspector типа объект/класс обеспечивают  информацию об
 объектах/типах класса,   но   ничего   не   говорят   о   данных,
 содержащихся в конкретных вхождениях данных объектов  или классов
 в конкретные   моменты   выполнения   программы.  Turbo  Debugger
 обеспечивает расширенную  форму  знакомого  окна  Inspector   для
 записей, предназначенную специально для инспектирования вхождений
 объектов и классов.

      Для перехода  в  это  окно  поместите  курсор  на  вхождение
 объекта или класса в окне Module и нажмите Ctrl-I.

      Большинство окон Inspector для записей данных Turbo Debugger
 имеет два   подокна:   в   верхнем    находятся    имена    полей
 записей/компоненты и  их текущие значения,  а в нижнем - тип поля
 или компонента,  высвеченного в верхнем подокне.  Окно  Inspector
 вхождений объектов/классов  также имеет оба эти подокна,  а между
 ними - третье подокно.  В нем сведены  правила  или  компонентные
 функции данного  вхождения,  а также адрес кода,  соответствующий
 каждому вхождению.  (адрес кода учитывает полиморфные  объекты  и
 VMT).

 Локальные меню окна Inspector вхождений объекта/класса   --------

      Каждое подокно  данного  окна  имеет  собственном  локальное
 меню, выводимое при нажатии Alt-F10  в  соответствующем  подокне.
 Если в   TDINST   разрешены   активные   клавиши,  то  можно  ими
 пользоваться.

      ---------------------
      Range...
      Change...
      Methods           Yes
      Show inherited    Yes
      ---------------------
      Inspect
      Descend
      New expression...
      Type cast
      Hierarchy
      ---------------------

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

 Команда Range...
 ----------------

      Данная команда  не   изменилась   сравнительно   с   первыми
 версиями. Она    выводит    диапазон    элементов    меню.   Если
 инспектируемый элемент  не  является  массивом  или   указателем,

 = 152 =

 доступ к этому элементу невозможен.

 Команда Change...
 -----------------

      Выбрав эту команду,  вы можете загрузить  новое  значение  в
 высвеченное поле  данных  или  компонент.  Эта  команда  также не
 изменилась по сравнению с прошлыми версиями Turbo Debugger.

 Команда Methods
 ---------------

      Данная команда работает как переключатель Yes/No, причем Yes
 устанавливается по умолчанию.  При этом правила или  компонентные
 функции перечисляются  в среднем подокне.  При установке значения
 No средняя панель не появляется.  Значение данного  переключателя
 запоминается и   используется   при   открытии   следующего  окна
 Inspector.

 Команда Show inherited
 ----------------------

      Данная команда   работает   как  переключатель  Yes/No.  При
 установке значения  Yes  показываются   все   поля   данных   или
 компоненты, а   также   все  правили  или  компонентные  функции,
 независимо от того,  определены ли они в пределах инспектируемого
 типа или  наследуются  от  порождающего  типа.  При  установке No
 показываются только  поля  и  правила,  определенные  в  пределах
 инспектируемого и отображаемого типа.

 Команда Inspect
 ---------------

      Как и в предыдущих  версиях  Turbo  Debugger,  выбор  данной
 команды открывает   окно  Inspector  для  высвеченного  поля  или
 компонента. Нажатие Enter  на  высвеченном  поле  или  компоненте
 делает то же самое.

 Команда Descend
 ---------------

      Данная команда  не  изменилась  по  сравнению   с   прошлыми
 версиями Turbo   Debugger.  Высвеченный  элемент  занимает  место
 элемента текущего  окна  Inspector.  Новые  окна   Inspector   не
 открываются. Однако,    вы    не   можете   вернуться   к   полю,
 инспектированному перед этим,  как  это  позволяет  делать  опция
 Inspector.

      Descend используется  для  инспектирования  сложных структур
 данных, если вы не желаете открывать специальное  окно  Inspector
 для каждого элемента.

 = 153 =


 New Expression...
 -----------------

      Относительно прошлых версий не  изменилась.  Данная  команда
 запрашивает у   вас   новый  элемент  данных  или  выражение  для
 инспектирования. Этот новый элемент заменяет текущий, находящийся
 в окне; другое окно при этом не открывается.

 Команда Type Cast...
 --------------------

      Позволяет задать инспектируемому элементу другой  тип данных
 (Byte, Word,  Int,  Char,  pointer).  Это  полезно в тех случаях,
 когда окно Inspector  содержит  символическое  имя,  для  которого
 информация о типе отсутствует, а также для явного присвоения типа
 нетипированным указателям.

 Команда Hierarchy
 -----------------

      При выборе данной команды открывается окно Hierarchy. Полное
 описание данного окна см. на стр.155 оригинала.

 Среднее и нижнее подокна   --------------------------------------

      В среднем  подокне   перечисляются   правила   объекта   или
 компонентные функции    класса.   Единственное   различие   между
 локальным меню подокна Object Method и  локальным  меню  верхнего
 подокна состоит  в отсутствии команды Change.  В отличие от полей
 данных или компонентов,  правила и компонентные функции не  могут
 изменяться во время выполнения, и эта команда не нужна.

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




 = 154 =

                                                                               
ГЛАВА 11 Отладка на уровне ассемблера
 -----------------------------------------------------------------

      Эта глава предназначена для программистов, которые знакомы с
 программированием на языке ассемблера для процессора семейства 80
 х86.

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

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

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

      Однако иногда   может   потребоваться   глубже   исследовать
 проблему,   просматривая   машинные    команды,    сформированные
 компилятором,  содержимое  регистров  процессора  и стека.  Чтобы
 делать это, вы должны быть знакомы с семейством процессоров 80х86
 и  с  тем,  как компилятор преобразует исходный текст программы в
 машинные команды.  Поскольку  имеется  достаточно  много  хороших
 книг, посвященных внутренней работе процессора, мы не будем здесь
 рассматривать  ее  детально.   Просматривая   машинные   команды,
 сформированные  для  каждой  строки  исходного  текста программы,
 можно быстро изучить,  как компилятор генерирует машинный код  из
 исходного текста.

      Компиляторы Си  и  Паскаля,  например,  позволяют записывать
 строки исходного текста программы,  в которых  выполняется  более
 одного  действия.  Поскольку  отладчик  выполняет за один шаг всю
 строку исходного текста,  иногда может  возникнуть  необходимость
 узнать  результат  выполнения  некоторой  части строки.  Выполняя
 программу   по   одной   машинной   команде,   можно    проверять
 промежуточные   результаты,   хотя   прежде   придется  затратить
 некоторое время на то,  чтобы изучить, как компилятор транслирует

 = 155 =

 операторы исходного текста в машинный код.
                                Окно процессора                                
 -----------------------------------------------------------------

      В этом  окне  отображается  полная  информация  о  состоянии
 процессора. Можно проверять и изменять биты и байты, составляющие
 код и  данные  программы.  С  помощью  встроенного  ассемблера  в
 подокне  кода  можно  поставить  временную "заплату" в программу,
 вводя команды точно в таком  же  виде,  как  они  записываются  в
 исходном тексте на языке ассемблера.  Кроме того можно обращаться
 к внутренним байтам  любой  структуры  данных,  отображать  их  в
 нескольких различных форматах и модифицировать их.


      Для того чтобы открыть  окно  процессора,  надо  выбрать  из
 главного  меню  команду View/CPU.  В зависимости от того,  что вы
 просматривали в текущем  окне,  после  открытия  окна  процессора
 выделяющий  курсор  будет  установлен  в  нем  на соответствующей
 позиции кода,  данных или  стека.  Это  дает  возможность  быстро
 просматривать  внутреннюю  структуру  кода,  данных  или  стека в
 текущей точке программы.

      Приведенная ниже таблица показывает, где будет установлен
 выделяющий курсор после выполнения команды CPU.

      ------------------------------------------------------------
      Текущее окно Подокно окна процессора    Положение в окне
      ------------------------------------------------------------
      Стека               Стека            Текущее состояние SS:SP
      Модуля              Кода             Текущее состояние CS:IP
      Действия            Кода             Адрес действия
      Переменных          Данных*          Адрес элемента
      Проверки            Данных           Адрес элемента
      Точек останова      Кода             Адрес точки останова

      *Подокно кода, если элемент в окне - не подпрограмма.
      ------------------------------------------------------------

      В верхней строке окна процессора  указан  тип  используемого
 процессора  (8086,  80186,  80286  или  80386).  Окно  процессора
 разделено на пять подокон.  Для  перехода  из  одного  подокна  в
 другое  используются  клавиши  Tab  и Shift-Tab.  В верхнем левом
 подокне  (подокне  кода)  отображается  дисассемблированный   код
 программы  вперемешку  со  строками  исходного текста.  Во втором
 верхнем подокне (подокне регистров) показано содержимое регистров
 процессора.   В  правом  подокне  (подокне  флагов)  отображается
 состояние  восьми  флагов  процессора.  В  нижнем  левом  подокне
 (подокне   данных)   отображается   в  шестнадцатиричном  формате
 построчный дамп любой выбранной области памяти.  В нижнем  правом
 подокне (подокне стека) показано содержимое стека.

 = 156 =


      В подокне  кода  указатель в виде стрелки показывает текущую
 точку программы (CS:IP). В подокне стека указатель в виде стрелки
 показывает  текущую  позицию в стеке (SS:SP).

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

      В подокне   флагов   отображается  состояние  каждого  флага
 процессора.

      Так же как и для других окон нажатие клавиш Alt-F10 вызывает
 локальное  меню  подокна  кода.  Если для команды меню определена
 активная клавиша,  нажатие клавиши  Ctrl  в  сочетании  с  первой
 буквой нужной команды вызывает эту команду.

      В подокнах кода, данных и стека нажатие клавиш Ctrl-"Стрелка
 влево"  и  Ctrl-"Стрелка   вправо"   сдвигают   начальный   адрес
 отображения  данных  в  окне  соответственно  на единицу вверх и
 вниз.  Этот способ проще,  чем использование команды  Goto,  если
 требуется лишь немного сместить отображение в окне.
                                 Подокно кода                                  
 -----------------------------------------------------------------

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

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

 Дисассемблер   --------------------------------------------------

      В окне кода автоматически дисассемблируются  и  отображаются
 команды  программы.  Если  адрес  соответствует  либо глобальному
 идентификатору,  либо  локальному  идентификатору,  либо   номеру
 строки,  в строке перед дисассемблированной командой отображается
 данный  идентификатор  (если  командой  Mixed  установлен   режим
 отображения  строк  исходного  текста  перед дисассемблированными
 командами).  Кроме того,  если имеется строка  исходного  текста,
 которая   соответствует   адресу   данного   идентификатора,  она
 отображается после этого идентификатора.

 = 157 =


      Глобальные идентификаторы отображаются в виде  обычных имен.
 Для  локальных  идентификаторов  указывается имя модуля,  который
 отделяется от самого идентификатора знаком # или  точкой.  Номера
 строк  отображаются в виде имени модуля,  за которым стоит знак #
 или точка, а затем десятичный номер строки.

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

      Turbo Debugger может обнаруживать числовой сопроцессор 8087/
 80287/80387  и  дисассемблировать  его  команды,  если  в  машине
 установлена соответствующая микросхема или имеется ее эмулятор.

      Команда дальнего  возврата  имеет  мнемоническое обозначение
 RETF. Команда ближнего возврата обозначается RET.

      Там, где  это  возможно,  назначение  команд  JMP   и   CALL
 обозначается символически. Если текущая команда является командой
 перехода или условного перехода стрелка,  указывающая направление
 перехода будет отображаться только в том случае, если выполняемая
 команда действительно вызовет переход.  Кроме того, адреса памяти
 в командах MOV, ADD и других отображаются в символическом виде.

 Локальное меню подокна кода   -----------------------------------

      --------------
      Goto
      Origin
      Follow
      Caller
      Previous
      Search
      View source
      Mixed      Yes
      --------------
      New cs:ip
      Assemble...
      I/O
      --------------

      Если вы еще не перешли в подокно кода, сделайте это сейчас с
 помощью клавиши Tab или Shift-Tab. Затем вызовите локальное меню,
 нажав клавиши Alt-F10.

 Команда Goto
 ------------

      После выбора    этой    команды   отладчик   запрашивает   у

 = 158 =

 пользователя новый адрес,  к которому надо перейти. Можно вводить
 адреса,  находящиеся за пределами программы. Это дает возможность
 проверять  код  BIOS,  DOS  и   резидентных   утилит.   Подробная
 информация, касающаяся ввода адресов, приведена в главе 9.

      Для возврата  в  позицию,  которая  являлась  текущей  перед
 выполнением команды Goto, можно использовать команду Previous.

 Команда Origin
 --------------

      Позиционирует курсор  в текущую точку программы,  на которую
 указывает   пара   регистров   CS:IP.   Этой   командой    удобно
 пользоваться,  когда  необходимо  вернуться  к исходной позиции в
 программе.

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

 Команда Follow
 --------------

      Позиционирует курсор  в адрес назначения выделенной в данный
 момент команды.  Курсор в подокне кода позиционируется на команду
 с  адресом,  по  которому выделенная команда передает управление.
 Для команд условного перехода адрес указывается так,  как если бы
 данный переход был выполнен.

      Эту команду   можно  использовать  с  командами  CALL,  JMP,
 командами условного перехода (JZ,  JNE,  LOOP,  JCXZ  и  т.д.)  и
 командой INT.

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

 Команда Caller
 --------------

      Позиционирует выделяющий курсор на команду,  которая вызвала
 текущее прерывание или подпрограмму.

      Эта команда работает не всегда.  Если подпрограмма обработки
 прерывания или другая  подпрограмма  занесла  данные  в  стек,  в
 некоторых случаях Turbo Debugger не может определить, откуда была
 вызвана данная подпрограмма.

      С помощью команды Previos можно вернуть выделяющий  курсор в
 подокне  кода  в  позицию,  где  он  был установлен до выполнения
 команды Caller.

 = 159 =


 Команда Previos
 ---------------

      Возвращает выделяющий  курсор в подокне кода в позицию,  где
 он  был  установлен  до  выполнения  последней  команды,  которая
 изменила  его  позицию на экране.  Позиция курсора,  измененная с
 помощью клавиш управления курсором и клавиш PgUp и PgDw  не может
 быть восстановлена с помощью команды Previos.

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

 Команда Search
 --------------

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

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

      PUSH  DX
      POP   (DI+1)
      ADD   AX,100

      Однако попытка   найти   следующие   команды   приведет    к
 непредсказуемым результатам:

      JE    123
      CALL  MYfUNC
      LOOP  $-10

      Вместо команды   можно  вводить  последовательность  байтов.
 Более подробно ввод последовательности байтов описан в главе 9.

 Команда Mixed
 -------------

      Включает один      из      трех      режимов     отображения
 дисассемблированных команд и исходного кода:

      No        Исходный код не отображается совсем; отображаются
      (нет)     только дисассемблированные команды.

 = 160 =


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

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

 Команда New CS:IP
 -----------------

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

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

 Команда Assemble
 ----------------

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

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

 Команда I/O
 -----------

 = 161 =


      -------------
      In byte
      Out byte
      read word
      Write word
      -------------

      Выполняет ввод  или  вывод  значения  в область ввода/вывода
 процессора,    позволяет    проверять    содержимое     регистров
 ввода/вывода,  находящихся  на  платах и записывать в них данные.

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


      Команда In Byte

      Считывает байт  из порта ввода/вывода.  Отладчик запрашивает
 номер порта,  содержимое которого требуется проверить.  Для  того
 чтобы  считать значение из порта длиной в одно слово, используйте
 команду Read Word.

      Команда Out Byte

      Записывает байт в порт  ввода/вывода.  Отладчик  запрашивает
 номер  порта и значение,  которое требуется записать в него.  Для
 того  чтобы  записать  значение  в  порт  длиной  в  одно  слово,
 используйте команду Write Word.

      Команда Read Word

      Считывает слово из порта ввода/вывода.  Отладчик запрашивает
 номер порта,  содержимое которого требуется проверить.  Для  того
 чтобы  считать значение из порта длиной в один байт,  используйте
 команду In Byte.

      Команда Write Word

      Записывает слово в порт ввода/вывода.  Отладчик  запрашивает
 номер  порта и значение,  которое требуется в него записать.  Для
 записи  значения  в  порт  ввода/вывода  длиной   в   один   байт
 используйте команду Out Byte.

      С помощью  команд  IN  и OUT можно получить доступ к области
 ввода/вывода,   которую   используют   контроллеры   периферийных
 устройств,   такие   как   платы   последовательного  интерфейса,
 контроллеры диска и видеоадаптеры.

      Будьте внимательны  при  использовании   этой   команды:   в
 некоторых  устройствах  ввода/вывода  чтение  из портов считается

 = 162 =

 важным  событием,  по  которому   устройство   должно   выполнить
 какое-либо действие,  как например, установка битов состояния или
 загрузка  нового  байта   данных   в   порт.   При   неосторожном
 использовании  этой  команды  может  нарушиться нормальная работа
 отлаживаемой программы или устройства.
                           Подокна Register и Flags                            
 -----------------------------------------------------------------

      Подокно Register, находящееся вверху справа от подокна Code,
 показывает содержимое регистров процессора.

      Верхнее правое  подокно  -  это  подокно  Flags,  в  котором
 показаны  состояния восьми флагов процессора.  В приведенной ниже
 таблице перечислены все флаги и их обозначения в  подокне флагов.

           ------------------------------------------
           Буква в подокне     Название флага
           ------------------------------------------
                c              Флаг переноса
                z              Флаг нуля
                s              Флаг знака
                o              Флаг переполнения
                p              Флаг четности
                a              Флаг дополнительного
                               переноса
                i              Флаг разрешения
                               прерывания
                d              Флаг направления
           ------------------------------------------


 Локальное меню подокна регистров --------------------------------

      Для вызова локального меню  подокна  регистров  надо  нажать
 клавиши  Alt-F10.  Если разрешено использование активных клавиш в
 комбинации с клавишей Ctrl,  команду меню  можно  вызвать,  нажав
 клавишу Ctrl в сочетании с первой буквой ее названия.

      --------------------
      Increment
      Decrement
      Zero
      Change...
      Registers 32-bit  No
      --------------------


 Команда Increment
 -----------------


 = 163 =

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

 Команда Decrement
 -----------------

      Уменьшает на единицу значение выделенного регистра.

 Команда Zero
 ------------

      Устанавливает значение выделенного регистра равным нулю.

 Команда Change...
 -----------------

      Изменяет значение выделенного регистра. Отладчик запрашивает
 новое значение.  При вводе нового значения можно использовать все
 имеющиеся возможности вычисления выражения.

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

 Команда Registers 32-bit
 ------------------------

      Выполняет переключение между режимами  отображения  значений
 16- или 32-битовых регистров процессора. При работе с процессором
 80386 обычно используется режим отображения 32-битовых регистров,
 если с помощью данной команды не был установлен режим отображения
 16-   битовых   регистров.   В   действительности   необходимость
 просматривать  значения 32-битовых регистров имеется только в том
 случае,  если  отлаживаемая  программа   использует   возможности
 32-битовой адресации процессора 80386.  При отладке программы,  в
 которой используется только обычная  16-битовая  адресация  можно
 использовать режим отображения 16-битовых регистров.

 Локальное меню подокна флагов   ---------------------------------

      -------
      Toggle
      -------

      Для вызова   локального  меню  подокна  флагов  надо  нажать
 клавиши Alt-F10.  Если разрешено использование активных клавиш  в
 комбинации  с  клавишей Ctrl,  команду меню можно вызвать,  нажав
 клавишу Ctrl в сочетании с первой буквой ее названия.


 = 164 =


 Команда Toggle
 --------------

      Устанавливает значение флага равным 1,  если оно было  равно
 0,  и 0,  если оно было равно 1.  Значение 0 соответствует сбросу
 флага,  а значение 1 - его установке.  Для  изменения  выбранного
 флага можно также нажать клавишу Enter.
                                Подокно данных                                 
 -----------------------------------------------------------------

      В этом подокне отображается построчное  содержимое выбранной
 области  памяти.  В  левой  части каждой строки указывается адрес
 данных,  отображаемых в данной строке.  Адрес либо отображается в
 виде   шестнадцатиричных   значений  сегмента  и  смещения,  либо
 значение сегмента заменяется  названием  регистра  DS,  если  оно
 совпадает с содержимым этого регистра.

      Далее в  строке  отображается  один  или несколько элементов
 данных.  Формат представления данных зависит от того, какой режим
 отображения  был  выбран  с помощью команды Display As локального
 меню.  Если выбран один из форматов отображения чисел с плавающей
 точкой (Comp,  Float,  Real,  Double,  Extended), в каждой строке
 отображается только одно число с плавающей точкой. В формате Byte
 в каждой строке отображается 8 байтов,  в формате Word - 4 слова,
 в формате Long - 2 двойных слова.

      В правой части каждой строки приводятся символьные значения,
 соответствующие   отображаемым   байтам  данных.  Turbo  Debugger
 отображает для всех байтовых значений их  символьные эквиваленты,
 поэтому не удивляйтесь, если справа от шестнадцатиричных значений
 байтов  данных  вы  увидите  какие-то  непонятные  символы;   это
 символьные эквиваленты шестнадцатиричных значений.

      Примечание: Если  подокно  данных  используется для проверки
 содержимого видеопамяти,  области данных ПЗУ,  содержащего  BIOS,
 или   векторов  с  меньшими  адресами  памяти,  в  подокне  будут
 отображаться значения, которые содержатся в памяти при выполнении
 отлаживаемой  программы,  а не фактические значения,  которые там
 содержатся при работе отладчика Turbo Debugger. То есть это не те
 значения, которые содержатся в памяти в момент их просмотра. Если
 программа обращается  к  областям  памяти,  которые  используются
 отладчиком,  он  обнаруживает  это  и  берет  правильные значения
 данных из того  места,  где  он  хранит  копию  областей  данных,
 используемых программой пользователя.

 Локальное меню подокна данных   ---------------------------------

      Для вызова   локального  меню  подокна  данных  надо  нажать
 клавиши Alt-F10.  Если разрешено использование активных клавиш  в

 = 165 =

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

      ----------------
      Goto
      Search
      Next
      Change
      Follow       >
      Previous
      ----------------
      Display as   >
      Block        >
      ----------------

 Команда Goto
 ------------

      Позиционирует курсор  на элемент данных с указанным адресом.
 После выбора этой команды надо ввести  новый  адрес,  к  которому
 требуется  перейти.  Вводимые  адреса могут относиться к областям
 памяти,  занимаемым DOS,  резидентными программами и выходить  за
 пределы  отлаживаемой  программы,  что позволит проверять данные,
 находящиеся  в  области  данных  BIOS.  Ввод   адресов   подробно
 рассмотрен в главе 9.

 Команда Search
 --------------

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

 Команда Next
 ------------

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

 Команда Change...
 -----------------

      Позволяет изменять  байты,  находящиеся  в  текущей  позиции
 курсора.  Если  курсор  установлен  на  ASCII-символе  или выбран
 байтовый формат,  в ответ на запрос отладчика  необходимо  ввести
 последовательность   байтов.   В  противном  случае  надо  ввести
 элемент,   соответствующий    текущему    формату    отображения.
 Последовательности байтов рассмотрены в главе 9.

 = 166 =


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

 Команда Follow
 --------------

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

      -----------------------
      Near code
      Far code
      -----------------------
      Offset to data
      Segment:offset to data
      Base segment:0 to data
      -----------------------

      Команда Near Code

      Интерпретирует слово   под   курсором  в  подокне  Data  как
 смещение в текущем кодовом  сегменте,  заданном  в  регистре  CS.
 Подокно Code  становится  текущим  подокном  и позиционируется на
 этот адрес.

      Команда Far Code

      Интерпретирует двойное слово под курсором в подокне Data как
 дальний  адрес  (сегмент  и  смещение).  Подокно  Code становится
 текущим подокном и позиционируется на этот адрес.

      Команда Offset to Data

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

      Команда Segment: Offset to Data

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

      Команда Base Segment:0 to Data

      Данная команда интерпретирует слово под курсором  как  адрес

 = 167 =

 сегмента и позиционирует подокно Data на начало этого сегмента.

 Команда Previos
 ---------------

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

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

 Команда Display As
 ------------------

      -----------
      Byte
      Word
      Long
      Comp
      Float
      Real
      Double
      Extended
      -----------

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

 Формат Byte
 -----------

      Информация в    подокне    данных    отображается   в   виде
 шестнадцатиричных байтов.  Этот формат  соответствует  типу  char
 языка Си и типу byte языка Паскаль.

 Формат Word
 -----------

      Информация в   подокне   данных    отображается    в    виде
 шестнадцатиричных   чисел   длиной  в  одно  слово.  Отображаются
 2-байтовые шестнадцатиричные значения.  Этот формат соответствует
 типу int языка Си и типу word языка Паскаль.

 Формат Long

 = 168 =

 -----------

      Информация в   подокне   данных    отображается    в    виде
 шестнадцатиричных целых чисел длиной в два слова. Отображаются 4-
 байтовые шестнадцатиричные числа.  Этот формат соответствует типу
 long языка Си и типу longint языка Паскаль.

 Формат Comp
 -----------

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

 Формат Float
 ------------

      Информация в  подокне  данных  отображается  в виде коротких
 чисел с плавающей точкой. Числа с плавающей точкой отображаются в
 экспоненциальной  форме.  Этот  формат  соответствует  типу float
 языка Си и типу single (стандарт IEEE) языка Паскаль.

 Формат Real
 -----------

      Информация в  подокне  данных отображается в виде 6-байтовых
 чисел с плавающей точкой,  используемых в языке Паскаль.  Числа с
 плавающей  точкой  отображаются  в  экспоненциальной форме.  Этот
 формат соответствует типу real языка Паскаль.

 Формат Double
 -------------

      Информация в  подокне  данных отображается в виде 8-байтовых
 чисел с плавающей точкой. Числа с плавающей точкой отображаются в
 экспоненциальной  форме.  Этот  формат  соответствует типу double
 языка Си и типу TBYTE языка ассемблера.

 Формат Extended
 ---------------

      Информация в подокне данных отображается в виде 10-байтовых
 чисел с плавающей точкой. Числа с плавающей точкой отображаются в
 экспоненциальной  форме.  Этот  формат  соответствует внутреннему
 формату представления  данных  в  сопроцессоре  80х87.  Он  также
 соответствует типу long double языка Си и типу extended (стандарт
 IEEE) языка Паскаль.

 Команда Block
 -------------


 = 169 =

      ------------
      Clear
      Move
      Set
      Read
      Write
      ------------

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

 Команда Clear
 -------------

      Сбрасывает в ноль (0) содержимое непрерывного  блока памяти.
 Отладчик запрашивает начальный адрес и количество байтов, которые
 необходимо очистить.

 Команда Move
 ------------

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

 Команда Set
 -----------

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

 Команда Read
 ------------

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

 Команда Write
 -------------

      Записывает содержимое блока памяти в файл.  Отладчик сначала
 запрашивает  имя  файла,  в который требуется записать данные,  а
 затем адрес блока памяти, из которого должны быть взяты данные, и
 количество байтов в этом блоке.

 = 170 =

                                 Подокно Stack                                 
 -----------------------------------------------------------------

      Подокно Stack,  находящееся в нижнем правом углу  окна  CPU,
 показывает содержимое стека.

 Локальное меню подокна стека
 ----------------------------

      ------------
      Goto
      Origin
      Follow
      Previous
      Change...
      ------------

      Для вызова локального меню подокна стека надо нажать клавиши
 Alt-F10.   Если   разрешено   использование   активных  клавиш  в
 комбинации с клавишей Ctrl,  для вызова команды меню можно нажать
 клавишу Ctrl в сочетании с первой буквой ее названия.

 Команда Goto
 ------------

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

      Команда Previos возвращает выделяющий курсор в подокне стека
 в позицию, где он был установлен до выполнения команды Goto.

 Команда Origin
 --------------

      Устанавливает выделяющий  курсор в текущую позицию стека, на
 которую  указывает  пара  регистров  SS:SP.  Эту  команду  удобно
 использовать для возврата в исходное положение.

      Команда Previos возвращает выделяющий курсор в подокне стека
 в позицию, где он был установлен до выполнения команды Origin.

 Команда Follow
 --------------

      Позиционирует выделяющий курсор на слово в стеке, на которое
 указывает выделенное слово. Эту команду удобно использовать в тех

 = 171 =

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

      Команда Previos возвращает выделяющий курсор в подокне стека
 в позицию, где он был установлен до выполнения команды Follow.

 Команда Previos
 ---------------

      Возвращает выделяющий курсор в подокне стека в  позицию, где
 он  был установлен до выполнения команды,  изменяющей его текущее
 положение.  Положение выделяющего курсора,  измененное с  помощью
 клавиш управления курсором или клавиш PgUp и PgDw,  не может быть
 восстановлено.

      Повторные выполнения команды Previos  переключают содержимое
 подокна стека с одного запомненного адреса на другой.

 Команда Change
 --------------

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

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

      Отладчик Turbo Debugger позволяет ассемблировать команды для
 процессоров 8086,  80186,  80286,  80386,  а  также  команды  для
 числовых сопроцессоров 8087, 80287 и 80387.

      Если для  модификации  отлаживаемой  программы  используется
 встроенный ассемблер  отладчика  Turbo  Debugger,  то  изменения,
 вносимые в программу,  не являются постоянными. Если перезагрузить
 программу с  помощью  команды  Run/Program  Reset  или  загрузить
 другую  программу  с  помощью  команды  File/Open,  все внесенные
 изменения будут утеряны.

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

      В следующем    разделе   описаны   различия   в   синтаксисе

 = 172 =

 встроенного ассемблера и языка Turbo Assembler.

 Изменение размера адреса операнда   -----------------------------

      Для команд  вызова  (CALL),  перехода  (JMP)   и   условного
 перехода  (JNE,  JL  и  т.д.)  ассемблер автоматически генерирует
 команды   минимального   размера,   которые   достигают    адреса
 назначения.  Для  того  чтобы  получить  команды нужного размера,
 можно использовать префиксы NEAR и FAR,  записанные перед адресом
 назначения, например,

      CALL FAR XYZ
      jmp NEAR Al

 Операнды в памяти и промежуточные операнды
 ------------------------------------------

      Когда некоторый   идентификатор   программы  используется  в
 качестве  операнда  команды,   необходимо   указать   встроенному
 ассемблеру,  как он должен его обрабатывать: как значение или как
 адрес.   Если   в   качестве   операнда   записано   только   сам
 идентификатор,  ассемблер  обрабатывает его как адрес,  точно так
 же, как если бы перед ним стоял оператор OFFSET языка ассемблера.
 Если   идентификатор   заключен  в  квадратные  скобки  ([]),  он
 обрабатывается  как  содержимое  области  памяти.   Допустим,   в
 программе имеется следующее описание данных:

      A    DW 4

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

      mov dx,a
      mov ax,[a]

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

      mov ax, offset a

 Изменение размера операнда   ------------------------------------

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

      BYTE PTR
      WORD PTR


 = 173 =

      Ниже приведено  два  примера  изменения  размера  операнда с
 помощью указанных выражений.

      add BYTE PTR[si],10
      mov WORD PTR[bp+10],99

      При ассемблировании команд числового сопроцессора 8087/80287
 для изменения размера операндов кроме  указанного  способа  можно
 использовать следующие выражения:

      DWORD PTR
      QWORD PTR
      TBYTE PTR

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

      fild QWORD PTR[bx]
      stp  TBYTE PTR[bp+4]

 Команды обработки строк   ---------------------------------------

      При ассемблировании команд обработки строк  в  мнемоническое
 обозначение  команды необходимо включать размер (байт или слово).
 Ассемблер не  воспринимает  форму  строковых  команд,  в  которой
 используется безразмерное мнемоническое обозначение для операнда,
 в котором указан  размер.  Например,  вместо  команды  STOS  WORD
 PTR[DI], следует использовать команду STOSW.
                                                                               
Окно дампа
 -----------------------------------------------------------------

      В этом окне отображается  построчный  дамп  любой  выбранной
 области  памяти.  Это  окно  работает  точно так же,  как подокно
 данных окна процессора.

      Для получения информации о работе с этим окном и  о командах
 его  локального меню обратитесь к разделу "Локальное меню подокна
 данных" данной главы.

      Это окно  удобно  использовать  при   отладке   ассемблерной
 программы    на   уровне   исходного   текста,   если   требуется
 просматривать содержимое областей данных.  Для того чтобы открыть
 окно дампа, можно использовать команду View/Dump.

      Окно дампа  также  можно  использовать  при  работе  в  окне
 проверки,  когда требуется просмотреть последовательность байтов,
 составляющих проверяемый элемент данных.  Выбор команды View/Dump
 открывает   окно   дампа,   в   котором   отображаются    данные,
 просматриваемые в окне проверки.
                                                                               
Окно регистров

 = 174 =

 -----------------------------------------------------------------

      В этом окно отображается содержимое регистров  процессора  и
 состояние его флагов.  Оно работает аналогично комбинации подокон
 регистров и флагов окна процессора.

      Для получения информации о работе с этим окном и  о командах
 его  локальных меню обратитесь к разделам "Локальное меню подокна
 регистров" и "Локальное меню подокна флагов" данной главы.

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

      Для удобства работы можно уменьшить  размер  окна  модуля  и
 поместить окно регистров рядом с ним.
                 Генерация кода для программ на языке Turbo C                  
 --------------------------------------------

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

      Значения, возвращаемые  функцией,  помещаются  в   следующие
 регистры:

           ------------------------------------
           Тип возвращаемого        Регистр(ы)
           значения
           ------------------------------------
           int                      AX
           long                     DX:AX
           float                    ST(0)
           double                   ST(0)
           long double              ST(0)
           near*                    AX
           far*                     DX:AX
           ------------------------------------

      Часто используемые указатели  типа  int  и  near  компилятор
 помещает  в  регистры,  используя  сначала  регистр  SI,  а затем
 регистр DI.

      Доступ к предопределенным переменным  и  параметрам  функций
 осуществляется через регистры SS:BP.

      Регистры AX,  BX,  CX и DX  не  обязательно  сохраняют  свои
 значения при вызовах функций.

 = 175 =


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

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

      -  условные переходы, соответствующие оператору if...else;

      -  таблица переходов по адресам кода;

      -  таблица переходов по значениям ключей и адресам кода.

      Более подробная   информация   о   генерации  кода  Turbo  С
 находится в соответствующих руководствах по Turbo С.



 = 176 =

                                                                               
ГЛАВА 12 Сопроцессор 80х87 и эмулятор
 -----------------------------------------------------------------

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

      В этой  главе рассмотрены различия между сопроцессором 80х87
 и его программным эмулятором.  Описывается также  окно  числового
 процессора  (Numeric  Processor)  и объясняется,  как проверять и
 модифицировать содержимое регистров сопроцессора, битов состояния
 и управляющих битов.

      Глава предназначена  для  программистов,  знакомых с работой
 математического сопроцессора 80х87.
                                                                               
Сравнение сопроцессора 80х87 и его эмулятора
 --------------------------------------------

      Отладчик Turbo Debugger автоматически определяет, использует
 ли программа  арифметический  сопроцессор  или  его  эмулятор,  и
 соответствующим образом настраивает свою работу.

      Заметим, что   в   большинстве  случаев  в  одной  программе
 используется либо эмулятор,  либо сам сопроцессор,  но не оба они
 одновременно.  Если  требуется  отладить особый ассемблерный код,
 который  использует  как  сопроцессор,  так  и  эмулятор,   Turbo
 Debugger  не  сможет  отображать состояние сопроцессора,  а будет
 отображать только состояние эмулятора.
                           Окно числового процессора                           
 -----------------------------------------------------------------

      Окно числового  процессора открывается командой View/Numeric
 Processor главного  меню.  В  верхней  строке  окна  отображается
 текущее  содержимое  указателя  команд,  указателя  данных  и код
 операции текущей команды.  Указатель данных  и  указатель  команд
 отображаются  в  виде 20- битовых физических адресов.  Эти адреса
 можно преобразовать в формат  <сегмент>:<смещение>,  взяв  первые
 четыре  разряда в качестве значения сегмента и последний разряд в
 качестве значения смещения.

      Например, если   в   верхней   строке   записано    значение
 IPTR=5A669,  можно  рассматривать  его  как  адрес  5a66:9,  если
 требуется проверить текущие данные и команду в  окне  процессора.

 = 177 =

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

      В верхней   строке   приводится   информация   о   последней
 выполненной  операции  с  плавающей   точкой.   IPTR   показывает
 20-битовый  физический адрес,  по которому была вызвана последняя
 команда с плавающей точкой.  OPCODE  показывает  тип  выполненной
 команды.  OPTR  показывает  20-битовый  физический  адрес области
 памяти,  к которой обращалась  выполненная  команда,  если  такая
 имеется.

 Подокно register    ---------------------------------------------

 80-разрядные регистры данных с плавающей точкой
 ------------------------------------------------

      В подокне регистров отображается содержимое  всех  регистров
 данных  с плавающей точкой (ST(0) - ST(7)) и их состояние (valid/
 zero/special/empty). Содержимое регистров отображается в виде 80-
 разрядного числа с плавающей точкой.

      Если увеличить  размеры  окна  числового  процессора  (нажав
 клавишу   F5)   или   расширить    его    с    помощью    команды
 Window/Move/Resize,   можно  просматривать  содержимое  регистров
 данных в виде строк шестнадцатиричных байтов.

 Локальное меню подокна регистров
 --------------------------------

      --------
      Zero
      Empty
      Change
      --------

      Для вызова локального меню нажмите клавиши Alt-F10 или сразу
 же вызовите нужную команду,  нажав клавишу  Ctrl  в  сочетании  с
 первой буквой ее названия.

 Команда Zero
 ------------

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

 Команда Empty
 -------------

      Устанавливает выделенный   курсором   регистр   в  состояние

 = 178 =

 "пусто".  Это особое состояние,  которое показывает,  что регистр
 больше не содержит достоверных данных.

 Команда Change
 --------------

      Загружает новое значение  в  регистр,  выделенный  курсором.
 Отладчик  запрашивает  значение,  которое  необходимо  загрузить.
 Можно ввести целое или вещественное  значение,  используя  полный
 синтаксис  выражений  языка Си.  Введенное значение автоматически
 преобразуется к 80-битовому формату промежуточных данных, который
 используется в числовом процессоре.

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

 Подокно Control   -----------------------------------------------

 Управляющие биты
 ----------------

      В следующей  таблице перечислены различные управляющие флаги
 и указано их назначение.

      -------------------------------------------------------
        Название флага         Назначение
        в подокне
      -------------------------------------------------------
           im             Маска неверной операции
           dm             Маска ненормализованного операнда
           zm             Маска деления на нуль
           om             Маска переполнения
           um             Маска отрицательного переполнения
           pm             Маска точности
           iem            Маска запроса на прерывание
                          (только для 8087)
           pc             Управление точностью
           rc             Управление округлением
           ic             Управление бесконечностью
      ------------------------------------------------------


 Локальное меню подокна управления
 ---------------------------------

      ----------
      Toggle
      ----------


 = 179 =

      Перейдите в окно  управления,  нажав  клавиши  Shift-Tab,  а
 затем вызовите его локальное меню,  нажав клавиши Alt-F10. (Можно
 также  сразу  вызвать  нужную  команду,  нажав  клавишу  Ctrl   в
 сочетании с первой буквой ее названия.)

 Команда Toggle
 --------------

      Циклически изменяет  значение  выделенного  курсором   флага
 состояния. Большинство флагов может принимать только два значения
 (0 и 1);  для них  команда  Toggle  переключает  флаг  во  второе
 возможное  значение.  Часть  флагов  может принимать более одного
 значения;  для  них  эта  команда   последовательно   увеличивает
 значение флага, пока не будет достигнуто максимальное значение, а
 затем сбрасывает его в ноль.

      Значение флага можно также изменять с помощью клавиши Enter.


 Подокно Status  -------------------------------------------------

 Биты состояния
 --------------

      В приведенной   ниже  таблице  перечислены  различные  флаги
 состояния и указано их назначение.

           ----------------------------------------------
             Название флага         Назначение
             в подокне
           ----------------------------------------------
                ie             Неверная операция
                de             Ненормализованный операнд
                ze             Деление на нуль
                oe             Переполнение
                ue             Отрицательное переполнение
                pe             Точность
                ir             Запрос на прерывание
                cc             Код условия
                st             Указатель вершины стека
           ----------------------------------------------

 Локальное меню подокна состояния
 --------------------------------

      -------------
      Toggle
      -------------

      Нажмите клавишу Tab,  чтобы перейти в подокно  состояния,  а
 затем нажав клавиши Alt-F10,  вызовите его локальное меню. (Можно

 = 180 =

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

 Команда Toggle
 --------------

      Циклически изменяет  значение  выделенного  курсором   флага
 состояния. Большинство флагов может принимать только два значения
 (0 и 1);  для них  команда  Toggle  переключает  флаг  во  второе
 возможное  значение.  Часть  флагов  может принимать более одного
 значения;  для  них  эта  команда   последовательно   увеличивает
 значение флага, пока не будет достигнуто максимальное значение, а
 затем сбрасывает его в ноль.

      Значение флага можно также изменять с помощью клавиши Enter.




 = 181 =

                                                                               
ГЛАВА 13  Справочник команд отладчика
 -----------------------------------------------------------------

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

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

      - все  команды  главного  меню и команды локальных меню всех
 видов окон;

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

      - клавиши для перемещения и изменения размеров окон.
                               Активные клавиши                                
 -----------------------------------------------------------------

      Активная клавиша  - это клавиша,  нажатие которой заставляет
 отладчик выполнять определенное действие независимо  от  текущего
 состояния   среды   отладчика  Turbo  Debugger.  В  таблице  13.1
 перечислены все активные клавиши.

                Таблица 13.1 Активные клавиши
 --------------------------------------------------------------------
 Клавиша        Команда меню                  Назначение
 --------------------------------------------------------------------
 F1                                 Получение контекстно-зависимой
                                    интерактивной подсказки
 F2             Breakpoints|Toggle  Устанавливает точку останова в
                                    позиции курсора
 F3             View|Module         Список взятых модулей
 F4             Run|Go to Cursor    Выполнение до позиции курсора
 F5             Window|Zoom         Наезд/отъезд для текущего окна
 F6             Window|Next Window  Переход к следующему окну
 F7             Run|Trace Into      Выполнение одной исходной строки
                                    или команды
 F8             Run|Step Over       Выполнение одной исходной строки
                                    или команды с пропуском вызовов
 F9             Run|Run             Запуск программы
 F10                                Вызов линейки меню,
                                    выход из меню
 -----------------------------------------------------------------
 Alt-F1         Help|Previous Topic Возврат к прошлому экрану
                                    подсказки
 Alt-F2         Breakpoints|At      Устанавливает точку останова
                                    по адресу
 Alt-F3         Window|Close        Закрывает текущее окно

 = 182 =

 Alt-F4         Run|Back Trace      Реверсирует выполнение программы
 Alt-F5         Window|User Screen  Показывает экран вывода программы
 Alt-F6         Window|Undo Close   Открывает последнее закрытое окно
 Alt-F7         Run|Instruction     Выполняет одну команду программы
                Trace
 Alt-F8         Run|Until Return    Выполняет программу до возврата
                                    из функции
 Alt-F9         Run/Execute To      Выполняет программу до заданного
                                    адреса
 Alt-F10                            Вызывает локальное меню окна
 Alt-1-9                            Делает активным окно с заданным
                                    номером
 Alt-пробел                         Вызывает меню System
 Alt-B                              Вызывает меню Breakpoints
 Alt-D                              Вызывает меню Data
 Alt-F                              Вызывает меню File
 Alt-H                              Вызывает меню Help
 Alt-O                              Вызывает меню Options
 Alt-R                              Вызывает меню Run
 Alt-V                              Вызывает меню View
 Alt-W                              Вызывает меню Window
 Alt-X          File|Quit           Осуществляет выход из отладчика
                                    и возврат в DOS
 Alt-=          Options|Macros|     Определяет клавишный макрос
                Create
 Alt--          Options|Macros|     Завершает запись макроса
                Stop Recording
 Ctrl-F2        Run|Program Reset   Завершает сеанс отладки и
                                    устанавливает программу
                                    в исходное состояние
 Ctrl-F4        Data|Evaluate       Вычисляет значение выражения
 Ctrl-F5        Window|Size/Move    Инициирует перемещение или
                                    изменение размера окна
 Ctrl-F7        Data|Add Watch      Заносит переменную в окно
                                    слежения
 Ctrl-F8        Breakpoints|Toggle  Переключает точку останова в
                                    текущей позиции курсора
 Ctrl-F9        Run|Run             Запускает программу
 Ctrl-F10                           Вызывает локальное меню окна
 Ctrl-Стрелка вправо                Смещает начальный адрес в подокне
                                    кода, данных или стека окна
                                    процессора на 1 байт вверх
 Ctrl-Стрелка влево                 Смещает начальный адрес в подокне
                                    кода, данных или стека окна
                                    процессора на 1 байт вниз
 Ctrl-A                             Перемещение к предыдущему слову
 Ctrl-C                             Скроллинг на один экран вниз
 Ctrl-D                             Перемещение вправо на один
                                    столбец
 Ctrl-E                             Перемещение вверх на одну строку
 Ctrl-F                             Перемещение к следующему слову

 = 183 =

 Ctrl-R                             Скроллинг на один экран вверх
 Ctrl-S                             Перемещение влево на один
                                    столбец
 Ctrl-X                             Перемещение на одну строку вниз
 -----------------------------------------------------------------
 Shift-F1       Help|Index          Переход к оглавлению интерак-
                                    тивной подсказки
 Shift-Tab                          Перемещение курсора к предыду-
                                    щему подокну или элементу блока
                                    диалога
 Shift-"стрелка вправо"             Перемещение курсора между
 Shift-"стрелка влево"              подокнами окна (подокно в
 Shift-"стрелка вверх"              направлении стрелки становится
 Shift-"стрелка вниз"               активным)
 -----------------------------------------------------------------
 Esc                                Закрывает окно проверки,
                                    выполняет возврат из меню
 Ins                                Начинает выбор (выделение) блока
                                    текста; для выделения используйте
                                    клавиши "Стрелка влево" и
                                    "Стрелка вправо"
 Tab            Window|Next Pane    Перемещает курсор в следующее
                                    подокно текущего окна
 --------------------------------------------------------------------
                             Команды главного меню                             
 -----------------------------------------------------------------

      Линейка меню вызывается нажатием клавиши  F10;  затем  можно
 перейти к конкретному меню,

      - подведя курсор  к заголовку нужного меню и нажав Enter;

      - нажав высвеченную букву заголовка меню.

      Меню можно  открыть  и непосредственно (без предварительного
 вызова линейки меню) нажатием Alt в  сочетании  с  первой  буквой
 имени желаемого меню.

 Меню =(System)   ------------------------------------------------

      Restore Standard    Восстанавливает стандартный макет окна
      Repaint Desktop     Перерисовывает экран
      About               Выводит информацию о Turbo Debugger

 Меню File   -----------------------------------------------------

      Open                Загружает в отладчик новую программу
      Change Dir          Выполняет смену диска и/или директории
      Get Info            Выдает информацию о программе
      DOS Shell           Запускает командный процессор ДОС

 = 184 =

      Resident            Делает Turbo Debugger резидентным
      Symbol Load         Загружает таблицу символических имен,
                          независимую от файла .EXE.
      Table Relocate      Устанавливает базовый адрес таблицы
                          символических имен
      Quit                Выполняет возврат в ДОС

 Меню View   -----------------------------------------------------

      Breakpoints         Просмотр точек останова
      Stack               Просмотр стека вызова
      Log                 Просмотр журнала событий и данных
      Watches             Просмотр значений отслеживаемых переменных
      Variables           Просмотр списка локальных и глобальных
                          переменных
      Module              Просмотр исходного текста модуля программы
      File                Просмотр содержимого дискового файла
                          в текстовом или шестнадцатиричном формате
      CPU                 Просмотр машинных команд, данных и
                          содержимого стека
      Dump                Просмотр построчного дампа области памяти
      Registers           Просмотр состояния регистров и флагов
                          процессора
      Numeric Processor   Просмотр состояния сопроцессора или
                          его эмулятора
      Execution History   Выводит ассемблерный код, который был
                          запомнен для обратной трассировки или
                          обратного воспроизведения нажатий клавиш
      Hierarchy           Выводит список объектов или типов класса
                          и иерархическое дерево
      Another
        Module            Открывает еще одно окно модуля
        Dump              Открывает еще одно окно дампа
        File              Открывает еще одно окно файла

 Меню Run   ------------------------------------------------------

      Run                 Запускает программу без остановок
      Go To Cursor        Выполняет программу до текущей позиции
                          курсора
      Trace Into          Выполняет одну строку исходного текста
                          или команду
      Step Over           Выполняет одну строку исходного текста
                          без вхождения в подпрограмму
      Execute To          Выполняет программу до указанного адреса
      Until Return        Выполняет программу до возврата из функции
      Animate             Запускает программу в непрерывном
                          пошаговом режиме
      Back Trace          Реверсирует выполнение программы на
                          одну исходную строку или команду
      Instruction Trace   Выполняет одну команду

 = 185 =

      Arguments           Устанавливает аргументы командной строки
      Program Reset       Заново загружает текущую программу

 Меню Breakpoint   -----------------------------------------------

      Toggle              Переключает точку останова в текущей
                          позиции курсора
      At                  Устанавливает точку останова на строке
                          с указанным адресом
      Changed Memory      Устанавливает глобальную точку останова,
      Global              которая включается при изменении
                          содержимого области памяти
      Expression True     Устанавливает глобальную точку останова,
      Global              которая включается, когда выражение
                          становится истинным
      Delete All          Удаляет все точки останова

 Меню Data  ------------------------------------------------------

      Inspect             Позволяет проверить элемент данных
      Evaluate/Modify     Вычисляет значение выражения
      Add Watch           Заносит переменную в окно слежения
      Function Return     Отображает значение, возвращаемое
                          текущей подпрограммой

 Меню Options   --------------------------------------------------

      Language            Определяет язык для вычисления выражений
                          по исходному модулю
      Macros
        Create            Определяет клавишный макрос
        Stop Recording    Заканчивает запись макроса
        Remove            Удаляет клавишный макрос
        Delete All        Удаляет все клавишные макросы
      Display Options     Позволяет установить опции экрана
                          (свопинг, размер, табуляция)
      Path for Source     Список директорий, в которых находятся
                          исходные файлы
      Save Options        Сохраняет на диске параметры отладчика,
                          макросы и параметры окон
      Restore Options     Восстанавливает параметры с диска


 Меню Window   ---------------------------------------------------

      Zoom                Выполняет трансформацию до полного размера
                          окна и назад
      Next                Последовательно активизирует окна,
                          открытые на экране
      Next Pane           Выполняет переход к следующему подокну
                          текущего окна

 = 186 =

      Size/Move           Позволяет изменить размеры и положение
                          текущего окна
      Iconize/Restore     Уменьшает размер окна до небольшой
                          пиктограммы и восстанавливает его
      Close               Закрывает текущее окно
      Undo Close          Отменяет последнюю команду Close
      Dump Pane to Log    Записывает в окно регистрации содержимое
                          текущего подокна
      User Screen         Выводит на дисплей выход вашей программы
      Open window list    Выводит список открытых окон  для активации
      Window Pick         Выводит меню открытых меню, если на экране
                          их более 9

 Меню Help   -----------------------------------------------------

      Index               Выводит оглавление интерактивной подсказки
      Previous Topic      Выводит предыдущий экран подсказки
      Help on Help        Выводит подсказку по самой интерактивной
                          системе подсказки
                            Команды локальных меню                             

      Раскрывающееся, или    "локальное",   меню   текущего   окна
 вызывается нажатием клавиш Alt-F10.  Если разрешено использование
 активных   клавиш   в   комбинации   с   клавишей   Ctrl,   можно
 непосредственно вызвать одну из  команд  локального  меню,  нажав
 клавишу Ctrl в сочетании с первой буквой названия нужной команды.
 (Для  того  чтобы  разрешить  использование  активных  клавиш   в
 комбинации с клавишей Ctrl, можно использовать программу TDINST.)

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

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

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


 = 187 =

 Локальное меню окна точек останова   ----------------------------

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

 Set Options              Устанавливает для точки останова:
                          действие, условия, счетчик проходов и
                          разрешение/запрещение точки
 Hardware Options         Позволяет устанавливать аппаратные
                          точки останова
 Add                      Добавляет новую точку останова
 Remove                   Удаляет выделенную точку останова
 Delete All               Удаляет все точки останова
 Inspect                  Просмотр строки программы, на которой
                          установлена точка останова

      Del - это активная клавиша для команды Remove данного окна

 Локальные меню окна процессора   --------------------------------

      Окно процессора разделено на пять подокон, каждое из которых
 имеет свое локальное меню:  подокно кода, подокно данных, подокно
 стека, подокно регистров и подокно флагов.

 Локальное меню подокна кода
 ---------------------------

 Goto                     Отображает команду с указанным адресом
 Origin                   Отображает текущую команду (CS:IP)
 Follow                   Отображает команду, к которой выполняется
                          переход по команде JMP или CALL
 Caller                   Отображает код вызвавшей подпрограммы
 Previos                  Отображает последнюю просматриваемую
                          команду
 Search                   Выполняет поиск команды или байтов
 View Source              Делает активным окно модуля
 Mixed                    No/Yes/Both (нет/да/оба): режим отображения
                          исходного текста в подокне кода
 New CS:SP                Устанавливает новое значение регистровой
                          пары CS:IP
 Assemble                 Ассемблирует команду, выделенную курсором
   In Byte                Считывает байт из порта ввода/вывода
   Out Byte               Записывает байт в порт ввода/вывода
   Read Word              Считывает слово из порта ввода/вывода
   Write Word             Записывает слово в порт ввода/вывода

      Ввод любого  символа  является  сокращенной  формой  команды
 Search локального меню данного подокна.


 = 188 =

 Локальное меню подокна данных
 -----------------------------

 Goto                     Отображает данные с указанным адресом
 Search                   Выполняет поиск строки или байтов данных
 Next                     Выполняет поиск следующего экземпляра
 Change                   Изменяет байты данных, указанные курсором
 Follow                   Выполняет переход на ближний адрес
 Near Code                Устанавливает подокно Code на ближний
                          адрес под курсором
 Far Code                 Устанавливает подокно Code на дальний
                          адрес под курсором
 Offset to Data           Устанавливает подокно Data на ближний
                          адрес под курсором
 Segment:Offset to Data   Устанавливает подокно Data на дальний
                          адрес под курсором
 Base Segment:0 to Data   Устанавливает подокно Data на начало
                          сегмента, содержащегося по адресу под
                          курсором
 Previos                  Отображает последние просматриваемые данные
 Display As
   Byte                   Отображает шестнадцатиричные байты
   Word                   Отображает шестнадцатиричные слова
   Long                   Отображает шестнадцатиричные двойные слова
   Comp                   Отображает 8-байтовые целые числа типа comp
                          языка Паскаль
   Float                  Отображает 4-байтовые числа с плавающей
                          точкой (тип single языка Паскаль)
   Real                   Отображает 6-байтовые числа с плавающей
                          точкой (тип real языка Паскаль)
   Double                 Отображает 8-байтовые числа с плавающей
                          точкой
   Extended               Отображает 10-байтовые числа с плавающей
                          точкой (тип long double языка Си)
 Block
   Clear                  Сбрасывает в 0 содержимое блока памяти
   Move                   Перемещает блок памяти
   Set                    Устанавливает блок памяти в определенное
                          значение
   Read                   Считывает данные из файла в память
   Write                  Записывает данные из памяти в файл

      Ввод любого  символа  является  сокращенной  формой  команды
 Change локального меню данного подокна.

 Локальное меню подокна флагов
 -----------------------------

 Toggle                   Устанавливает или сбрасывает выделенный
                          флаг


 = 189 =

      Нажатие клавиши  Enter  является  сокращенной  формой   этой
 команды локального меню данного подокна.

 Локальное меню подокна регистров
 --------------------------------

 Increment                Увеличивает на 1 значение выделенного
                          регистра
 Decrement                Уменьшает на 1 значение выделенного
                          регистра
 Zero                     Сбрасывает в 0 значение выделенного
                          регистра
 Change                   Устанавливает выделенный регистр в
                          в новое значение
 Registers 32-bit         No/Yes (нет/да): отображение 32-битовых
                          регистров

      Ввод любого  символа  является  сокращенной  формой  команды
 Change локального меню данного подокна.

 Локальное меню подокна стека
 ----------------------------

 Goto                     Отображает элемент стека с заданным адресом
 Origin                   Отображает элемент, на который указывает
                          пара регистров SS:SP
 Follow                   Отображает код, на который указывает
                          текущий элемент
 Previos                  Отображает последний просматриваемый
                          элемент
 Change                   Позволяет отредактировать данные

      Ввод любого  символа  является  сокращенной  формой  команды
 Change локального меню данного подокна.

 Окно Dump   -----------------------------------------------------

      Окно Dump  идентично  подокну  Data окна CPU.  Его локальное
 меню идентично локальному меню подокна Data.


 Меню окна файла   -----------------------------------------------

      В этом   окне  отображается  содержимое  дискового  файла  в
 текстовом или шестнадцатиричном формате.

 Goto                     Отображает строку с указанным номером или
                          шестнадцатиричным смещением
 Search                   Выполняет поиск строки или байтов данных
 Next                     Выполняет поиск следующего экземпляра
 Display As               Ascii/Hex: устанавливает формат отображения

 = 190 =

                          (текстовый/шестнадцатиричный)
 File                     Позволяет просмотреть содержимое другого
                          файла
 Edit                     Позволяет отредактировать содержимое файла
                          или изменить байты в текущей позиции
                          курсора

      Ввод любого  символа  является  сокращенной  формой  команды
 Search локального меню данного подокна.

 Меню окна регистрации   -----------------------------------------

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

 Open Log File            Начинает регистрацию данных в файле
 Close Log File           Останавливает регистрацию данных в файле
 Logging                  No/Yes (да/нет): включает или выключает
                          режим регистрации
 Add Comment              Записывает в журнал введенные пользователем
                          комментарии
 Erase Log                Стирает содержимое журнала регистрации

      Ввод любого символа является сокращенной формой  команды Add
 Comment локального меню данного подокна.

 Меню окна модуля ------------------------------------------------

      В этом  подокне  отображается  исходный  текст  программного
 модуля.

 Inspect                  Отображает значение переменной, на которой
                          установлен курсор
 Watch                    Заносит переменную, на которой установлен
                          курсор, в окно слежения
 Module                   Отображает текст другого модуля
 File                     Отображает содержимое другого файла
 Previos                  Отображает последний просматриваемый модуль
                          с последней текущей позицией курсора
 Line                     Отображает номер строки в модуле
 Search                   Выполняет поиск строки символов
 Next                     Выполняет поиск следующего экземпляра
                          строки
 Origin                   Отображает текущее место программы
 Goto                     Отображает строку исходного текста или
                          команду с указанным адресом
 Edit                     Запускает текстовый редактор с исходным
                          файлом

      Ввод любого символа является сокращенной формой команды Goto
 локального меню данного подокна.

 = 191 =


 Меню окна числового процессора   --------------------------------

      Окно числового  процессора разделено на три подокна: подокно
 регистров, подокно состояния и подокно управления.

 Локальное меню подокна регистров
 --------------------------------

 Zero                     Сбрасывает в 0 выделенный регистр
 Empty                    Устанавливает выделенный регистр в
                          состояние "пусто"
 Change                   Устанавливает выделенный регистр в заданное
                          значение

      Ввод любого  символа  является  сокращенной  формой  команды
 Change локального меню данного подокна.

 Локальное меню подокна состояния
 --------------------------------

 Toggle                   Циклически присваивает флагу допустимые
                          значения

      Нажатие клавиши  Enter  является  сокращенной  формой   этой
 команды локального меню данного подокна.

 Локальное меню подокна управления
 ---------------------------------

 Toggle                   Циклически присваивает флагу допустимые
                          значения

      Нажатие клавиши   Enter  является  сокращенной  формой  этой
 команды локального меню данного подокна.

 Локальные меню окна иерархии   ----------------------------------

      Окно иерархии имеет два подокна,  Object Type/Class  List  и
 Hierarchy Tree.  Также имеется третье подокно,  Parent Tree, если
 выполняется программа С++ с множественным наследованием.

 Локальное меню подокна Object Type/Class List
 ---------------------------------------------

 Inspect                  Показывает содержимое высвеченного объекта
                          или типа класса
 Tree                     Переходит к подокну Hierarchy Tree

 Локальное меню подокна Hierarchy Tree
 -------------------------------------

 = 192 =


 Inspect                  Показывает содержимое высвеченного объекта
                          или типа класса
 Parents                  Включается, когда выведено подокно Parent
                          Tree и вы выполняете программу С++ с
                          множественным наследованием

 Локальное меню подокна Parent Tree
 ----------------------------------

 Inspect                  Показывает содержимое высвеченного объекта
                          или типа класса

 Меню окна регистров   -------------------------------------------

      Окно Registers идентично подокнам Register и Flags окна CPU.
 Его локальные  меню  идентичны  локальным меню подокон Register и
 Flags.

 Меню окна стека    ----------------------------------------------

      В этом окно отображаются функции,  которые в  данный  момент
 являются активными.

 Inspect                  Отображает исходный текст выделенной
                          функции
 Locals                   Отображает типы аргументов функции

      Нажатие клавиши  Enter  является  сокращенной формой команды
 Inspect локального меню данного подокна.

 Локальные меню окна переменных ----------------------------------

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

 Локальное меню подокна глобальных идентификаторов
 -------------------------------------------------

 Inspect                  Отображает значение выделенной переменной
 Change                   Заменяет значение выделенной переменной

      Нажатие клавиши Enter является  сокращенной  формой  команды
 Inspect локального меню данного подокна.

 Локальное меню подокна локальных идентификаторов
 ------------------------------------------------

 Inspect                  Отображает значение выделенной переменной
 Change                   Заменяет значение выделенной переменной

 = 193 =


      Нажатие клавиши  Enter  является  сокращенной формой команды
 Inspect локального меню данного подокна.

 Меню окна слежения   --------------------------------------------

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

 Watch                    Заносит переменную в окно слежения
 Edit                     Позволяет отредактировать имя переменной
 Remove                   Удаляет выделенную переменную
 Delete All               Удаляет все отслеживаемые переменные
 Inspect                  Отображает значение выделенной переменной
 Change                   Заменяет значение выделенной переменной

      Следующие клавиши   являются   сокращенной   формой   команд
 локального меню данного окна:

 любой символ             Watch
 Enter                    Edit
 Del                      Remove

 Локальное меню окна проверки  -----------------------------------

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

 Range                    Выбирает для проверки элементы массива
 Change                   Заменяет значение выделенного элемента
 Inspect                  Открывает новое окно проверки для
                          выделенного элемента
 Descend                  Раскрывает выделенный элемент в данном окне
                          проверки
 New Expression           Отображает новое выражение в данном окне
                          проверки
 Type Cast                Выполняет приведение высвеченного типа к
                          новому типу

 Меню окна проверки для типа объект/класс   ----------------------

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

 Inspect                  Показывает содержимое высвеченного типа
 Hierarchy                Возвращается к окну Hierarchy
 Show Inherited           Выполняет переключение между показом
                          всего содержимого объекта или класса
                          и показом содержимого, объявленного в
                          текущем объекте или классе

 = 194 =


 Меню окна проверки вхождений объекта/класса   -------------------

      Это окно имеет три подокна,  из которых  только  первые  два
 имеют локальные  меню.  (Третье  выводит  только  тип объекта или
 класс, которому принадлежит данное вхождение). Оба локальных меню
 одинаковы и содержат следующие команды:

 Range                    Выбирает инспектируемые компоненты
                          массива.
 Change                   Изменяет значение высвеченного элемента
 Methods                  Управляет тем, выводятся ли в среднее
                          подокно имена правил или компонентных
                          функций
 Show Inherited           Управляет тем, показывается ли все
                          содержимое объекта или класса, или только
                          объявленное в текущем объекте или классе
 Inspect                  Открывает новое окно Inspect для
                          высвеченного элемента
 Descend                  Расширяет высвеченный элемент в данное
                          окно проверки
 New Expression           Проверяет в данном окне Inspect новое
                          выражение
 Type Cast                Преобразовывает тип высвеченного элемента
                          данных к новому типу
 Hierarchy                Выполняет возврат к окну Object Hierarchy

                               Текстовые подокна                               
 -----------------------------------------------------------------

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

 -----------------------------------------------------------------
 Клавиша                            Назначение
 -----------------------------------------------------------------
 Ins                      Начинает выделение блока текста
 Стрелка вверх            Перемещает курсор на одну строку вверх
 Стрелка вниз             Перемещает курсор на одну строку вниз
 Стрелка вправо           Перемещает курсор на одну позицию вправо
 Стрелка влево            Перемещает курсор на одну позицию влево
 Ctrl-Стрелка вправо      Перемещает курсор к следующему слову
 Ctrl-Стрелка влево       Перемещает курсор к предыдущему слову
 Home                     Перемещает курсор в начало строки
 End                      Перемещает курсор в конец строки
 PgUp                     Прокрутка на один экран вверх
 PgDw                     Прокрутка на одни экран вниз
 Ctrl-Home                Перемещает курсор к верхней строке окна

 = 195 =

 Ctrl-End                 Перемещает курсор к нижней строке окна
 Ctrl-PgUp                Перемещает курсор к первой строке файла
 Ctrl-PgDw                Перемещает курсор к последней строке файла
 -----------------------------------------------------------------

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

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

      Таблица 13.3   Команды подокон списков
 --------------------------------------------------------------------
 Клавиша                            Назначение
 --------------------------------------------------------------------
 Стрелка вверх            Перемещает курсор на одну строку вверх
 Стрелка вниз             Перемещает курсор на одну строку вниз
 Стрелка вправо           Скроллинг вправо
 Стрелка влево            Скроллинг влево
 Home                     Перемещает курсор в начало строки
 End                      Перемещает курсор в конец строки
 PgUp                     Прокрутка на один экран вверх
 PgDw                     Прокрутка на одни экран вниз
 Ctrl-Home                Перемещает курсор к верхней строке окна
 Ctrl-End                 Перемещает курсор к нижней строке окна
 Ctrl-PgUp                Перемещает курсор к первой строке файла
 Ctrl-PgDw                Перемещает курсор к последней строке файла
 Backspace                Возврат на один символ при поиске по буквам
 буква                    Последовательный поиск по вводимым буквам
 --------------------------------------------------------------------

      Для перемещения  в  подокне можно также использовать команды
 редактора WordStar.

             Команды в блока запроса и списков истории выполнения              
 -----------------------------------------------------------------

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

      Таблица 13.4    Команды блока диалога
 --------------------------------------------------------------------
 Клавиша                            Назначение
 --------------------------------------------------------------------

 = 196 =

 Стрелка вверх            Перемещает курсор на один элемент списка
                          вверх
 Стрелка вниз             Перемещает курсор на один элемент списка
                          вниз
 Стрелка вправо           Перемещает курсор на один символ вправо
 Стрелка влево            Перемещает курсор на один символ влево
 Ctrl-Стрелка вправо      Перемещает курсор к следующему слову
 Ctrl-Стрелка влево       Перемещает курсор к предыдущему слову
 Home                     Перемещает курсор в начало строки
 End                      Перемещает курсор в конец строки
 PgUp                     Прокрутка на один экран вверх
 PgDw                     Прокрутка на одни экран вниз
 Ctrl-Home                Перемещает курсор к верхней строке окна
 Ctrl-End                 Перемещает курсор к нижней строке окна
 Ctrl-PgUp                Перемещает курсор к первому элементу списка
 Ctrl-PgDn                Перемещает курсор к последнему элементу
                          списка
 Backspace                Удаляет символ до курсора
 Enter                    Принимает введенные данные и продолжает
                          работу
 Del                      Удаляет символ, стоящий за курсором
 Esc                      Отмена запроса и возврат в меню
 Ctrl-N                   Дополняет частично введенное имя в блоке
                          ввода
 --------------------------------------------------------------------
                           Команды перемещения окон                            
 -----------------------------------------------------------------

      Таблица 13.5   Клавиши команд перемещения окна
 -----------------------------------------------------------------
 Клавиша                            Назначение
 -----------------------------------------------------------------
 Ctrl-F5                  Включает и выключает режим перемещения окна
 Стрелка вверх            Перемещает окно на одну строку вверх
 Стрелка вниз             Перемещает окно на одну строку вниз
 Стрелка вправо           Перемещает окно на одну позицию вправо
 Стрелка влево            Перемещает окно на одну позицию влево
 Shift-Стрелка вверх      Изменяет высоту окна; перемещает нижнюю
                          рамку вверх
 Shift-Стрелка вниз       Изменяет высоту окна; перемещает нижнюю
                          рамку вниз
 Shift-Стрелка вправо     Изменяет ширину окна; перемещает правую
                          рамку вправо
 Shift-Стрелка влево      Изменяет ширину окна; перемещает правую
                          рамку влево
 Home                     Сдвигает окно к левой границе экрана
 End                      Сдвигает окно к правой границе экрана
 PgUp                     Сдвигает окно к верхней границе экрана
 PgDw                     Сдвигает окно к нижней границе экрана
 Enter                    Закрепляет окно в выбранной позиции

 = 197 =

 Esc                      Отменяет команду позиционирования окна
 --------------------------------------------------------------------
                                                                               
Шаблоны для поиска
 -----------------------------------------------------------------

      Шаблоны из метасимволов можно использовать для поиска данных
 в следующих случаях:

      - при  вводе  имени  файла,  который требуется загрузить или
 проверить;

      - при вводе текста,  который  требуется  найти  в  текстовом
 подокне.

      Знак вопроса  (?)  соответствует  одному  любому  символу  в
 искомой  строке.  Звездочка  (*)  соответствует  нулю  или  более
 символов в искомой строке.




 = 198 =

                       ГЛАВА 14 Как отлаживать программу                       
 -----------------------------------------------------------------

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

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

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

      Посмотрим, с чего требуется начать, когда вы обнаружили, что
 ваша программа работает неверно.
                    Что делать, если программа не работает?                    
 -----------------------------------------------------------------

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

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

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

      Если же  к  моменту  вызова функции xyz ошибки не произошло,
 значит  исходное  предположение  было   неверным.   Тогда   можно
 предположить,  что  ошибка  возникает где-то после вызова функции
 xyz.  Выполнив несколько подобных проверок,  можно быстро  найти

 = 199 =

 тот фрагмент программы, который вызывает ошибку.

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

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

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

 Проверка работы всей программы   --------------------------------

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

 Последовательное тестирование   ---------------------------------

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

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

      Ошибки в   программах   можно   разделить   на  две  большие
 категории:  ошибки,  характерные для языка,  на котором  написана
 программа  (Си,  Паскаля  или ассемблера),  и ошибки,  являющиеся
 общими для всех языков программирования.

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

      Главное в этом  деле,  постараться  понять,  к  какому  виду
 относится  каждая  конкретная  ошибка и таким образом развивать в
 себе способность писать программы без ошибок.  И  наконец,  лучше
 писать программы без ошибок, чем уметь обнаруживать ошибки.
       Общие ошибки   --------------------------------------------------       

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

 Скрытые эффекты
 ---------------

      При неосторожном   обращении  с  глобальными  переменными  в
 функциях вызов функции может привести  к  неожиданным  изменениям
 переменной или структуры данных:

      char workbuf[20];
      strcpy(workbuf,"all done\n");
      convert("xyz");
      printf(workbuf);
      ...
      convert(char *p)
      {
         strcpy(workbuf, p);
         while (*p)
            ...
      }

      Здесь правильное   решение   заключается   в   использовании
 функцией собственного рабочего буфера.

 = 201 =


 Вы предположили, что данные уже инициализированы
 ------------------------------------------------

      Не полагайтесь    на    то,    что   переменные   уже   были
 инициализированы где-то другой подпрограммой:

      char *workbuf;
      addworkstring(char *s)
      {
         strcpy(workbuf, s);   /* ошибка */
      }

      Здесь нужно записать более определенно:

      if (workbuf == 0) workbuf = (char *)malloc(20);

 Не выполнена очистка памяти
 ---------------------------

      Следующая ошибка  может  привести  к программному сбою из-за
 того, что израсходовано все пространство кучи:

      crunch_string(char *p)
      {
         char *work = (char *)malloc(strlen(p));
         strcpy(work, p);
         ...
         return(p);    /* при этом work еще распределена память */
      }

 Ошибка "последнего столба изгороди"
 -----------------------------------

      Этого рода  ошибки названы в честь старой загадки :  "Если я
 хочу поставить изгородь длиной 100 футов со столбами через каждые
 10 футов,  сколько мне понадобится столбов?" Быстрый, но неверный
 ответ - 10 столбов (однако,  как насчет последнего столба в конце
 изгороди?). Ниже   приводится   пример   такого   рода  ошибки  в
 Си-программе:

      for (n = 1; n < 10; n++)
      {
         ...           /* ошибка - цикл выполнится только 9 раз */
      }

      Здесь фигурируют цифры 1 и 10,  и вам может показаться,  что
 цикл будет выполнен 10 раз.  (Чтобы на самом  деле  так  и  было,
 замените < на <=).
                Ошибки, характерные для программирования на Си                 

 = 202 =


      В Руководстве  пользователя  по  языку  Turbo C есть раздел,
 посвященный "ловушкам" для программистов,  работающих на  Си,  но
 лучше  всего  свои знания о "ловушках" можно пополнить в процессе
 отладки реальной программы.

      Компилятор Turbo C может очень хорошо находить  ряд  ошибок,
 специфичных  для  языка  Си,  которые  другими  компиляторами  не
 обнаруживаются.  Можно сэкономить много времени, требующегося для
 отладки, если включить формирование всех возможных предупреждений
 компилятора.  (Информация  о  формировании  этих   предупреждений
 приведена в Руководстве пользователя по языку Turbo C).

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

 Использование неинициализированных автоматических переменных
 ------------------------------------------------------------

      В языке Си авто-переменная,  описанная внутри функции, имеет
 неопределенное значение,  пока  оно  не  будет  каким-то  образом
 загружено:

      do_ten_times()
      {
         int n;
         while (n < 10)
            {
            ...
            n++;
         }
      }

      В этой  функции цикл while будет выполняться непредсказуемое
 число раз,  поскольку переменная n не  была  установлена  в  ноль
 перед использованием ее в качестве счетчика цикла.

 Использование = вместо ==
 -------------------------

      Язык Си позволяет как присваивать значение (знак =),  так  и
 проверять   равенство   значений   (знак  ==)  внутри  выражений,
 например,

      if (x = y) {
         ...
      }

 = 203 =


      Здесь неумышленно  значение  переменной  y  будет  присвоено
 переменной x и будут выполнены операторы в выражении if, если это
 значение не равно нулю.  Вместо этого скорее  всего  должно  было
 быть записано следующее:

      if (x = = y) {
         ...

 Неправильная расстановка операций в выражении
 ---------------------------------------------

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

      x = 3 << 1 + 1

      будет равно 12,  а не 7,  как могло было быть,  если бы знак
 << стоял перед знаком +.

 Неправильное вычисление указателей
 ----------------------------------

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

      int *intp;
      intp += sizeof(int);

      не дают ожидаемого результата, то есть перемещения указателя
 intp   к   следующему   элементу   массива   целых    чисел.    В
 действительности,  intp будет смещен на два элемента массива. При
 выполнении  операций  сложения  и  вычитания   над   указателями
 компилятор  Си  учитывает  размер элемента,  на который указывает
 указатель,  поэтому все,  что требуется сделать  для  перемещения
 указателя к следующему элементу массива, это записать:

      intp++

 Неожидаемое расширение знака
 ----------------------------

      Необходимо быть   внимательным   при   выполнении   операций
 присваивания  над  целочисленными  переменными,  имеющими  разные
 размеры:


 = 204 =

      int i = OXFFFF;
      long l;
      l = i;
      if (l & 0X80000000) {
         ...                              /* это БУДЕТ выполняться */
      }

      Одно из   строгих  правил  языка  Си  может  вызвать  у  вас
 затруднения, если вы не будете учитывать его важность. В Си можно
 свободно  присваивать  значения  различных скалярных типов (char,
 int  и  т.д.).  Когда  некоторое  целое  значение   присваивается
 переменной  большего размера,  знак сохраняется в этой переменной
 путем размножения знакового (старшего) бита  в  старших  разрядах
 переменной.  Например,  значение  -2 (0xfffe) типа int становится
 значением -2 (0xfffffffe) типа long.

 Неожидаемое отсечение
 ---------------------

      Следующий пример приведен в противоположность предыдущему:

      int i;
      long l = 0X10000;
      i = l;
      while (i > 0) {
         ...                           /* это НЕ БУДЕТ выполняться */
      }

      Здесь присваивание  переменной  i  значения   переменной   l
 приведет  к  тому,  что  старшие  16  разрядов переменной l будут
 отсечены, а переменная i станет равна нулю.

 Лишние точки с запятой
 ----------------------

      Следующий фрагмент   программы  на  первый  взгляд  выглядит
 вполне нормально:

      for (x = 0; x < 10; x++);
      {
         ...                        /* выполняется только один раз */
      }

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

 фрагментов текста программы.

 Макросы с побочными эффектами
 -----------------------------

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

      #define toupper(c) 'a'<= (c)&&(c)<='z' ? (c)-'a'-'A' : (c)
      char c, *p;
      c = toupper(*p++);

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

 Повторение имен автоматических переменных
 -----------------------------------------

      Еще одна ошибка, которую сложно обнаружить:

      myfunc()
      {
         int n;
         for (n = 5; n >= 0; n--)
         {
            int n = 10;
            ...
            if (n == 0)
            {
               ...
            }
         }
      }

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

 Неправильное использование автоматических переменных
 ----------------------------------------------------

      Следующая функция   должна   была    возвращать    указатель
 результата вычисления:

 = 206 =


      int *divide_by_3(int n)

      {
         int i;
         i = n/3;
         return(&i);
      }

      Ошибка состоит   в  том,  при  каждом  возврате  из  функции
 значение автоматической переменной перестает быть  достоверным  и
 вероятнее всего затирается другими данными в стеке.

 Неопределенное значение, возвращаемое функцией
 ----------------------------------------------

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

      char *first_capital_letter(char *p)
      {
         while (*p)
         {
            if ('A' <= *p && *p <= 'Z')
                return(p);
            p++;
         }
                                    /* функция ничего не возвращает*/
      }

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

 Неправильное использование зарезервированного слова break
 ---------------------------------------------------------

      Оператор break   осуществляет   выход   только   из   одного
 вложенного цикла do, for, switch или while:

      for (...)
      {
         while (...)
         {
            if (...)
              break;                /* мы хотим выйти из цикла for */
         }
      }

      Здесь оператор break  осуществляет  выход  только  из  цикла

 = 207 =

 while.  Это  один  из тех немногих случаев,  где вполне оправдано
 использование оператора goto.

 Код работает неправильно
 ------------------------

      Иногда нормально  компилируемые  фрагменты  исходного текста
 дают не тот результат, который ожидался:

      a + b;

      Здесь должна была стоять строка a += b.

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

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

 Использование неинициализированных переменных
 ---------------------------------------------

      Turbo Pascal не может инициализировать переменные за вас; вы
 должны  это  сделать  самостоятельно  либо  с  помощью  оператора
 присваивания,   либо   объявив   их   типизованными  константами.
 Рассмотрим следующую программу.

      program Test;
      var
        I,J,Count : Integer;
      begin
        for I := 1 to Count do begin
          J := I*I;
          Writeln(I:2, ' ',J:4);
        end;
      end.

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

      Кроме того,  переменные, описанные внутри процедур и функций
 создаются заново при каждом входе в подпрограмму  и  уничтожаются
 при  выходе  из нее;  поэтому нельзя рассчитывать на то,  что эти

 = 208 =

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

 Ошибки при работе с указателями
 -------------------------------

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

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

      function FindNode(Head : NodePtr; Val : integer);
      var
        Temp : NodePtr;
      begin
        Temp := Head;
        while (Temp^.Key <> Val) and (Temp <> nil) do
          Temp := Temp^.Next;
        FindNode := Temp
      end.  { функции FindNode }

      Если значение Val не равно значению поля Key любого из узлов
 связного  списка,  эта  подпрограмма  будет  пытаться   вычислить
 значение переменной Temp^.Key, когда Temp равна nil, что приведет
 к непредсказуемому результату. Где же решение проблемы? Перепишем
 условие цикла while следующим образом:

      while (Temp <> nil) and (Temp^.Key <> Val) do

      и включим  режим сокращенного вычисления булевских выражений
 с помощью директивы {$B-} компилятора Turbo  Pascal  или  команды
 Options /Compiler/Boolean .  В результате этого,  если Temp равна
 nil, второй терм выражения никогда не будет вычисляться.

      И наконец,  никогда не следует думать,  что указателю  будет
 присвоено  значение  nil в результате того,  что оно передается в
 качестве параметра в процедуру Dispose  или  FreeMem.  Указатель
 сохранит свое прежнее значение,  но область памяти, на которую он
 указывал,  освободится и может быть занята другими  динамическими

 = 209 =

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

 Ошибки, связанные с областью действия
 -------------------------------------

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

      program Confused;
      var
        A,B : integer;

      procedure Swap(var A,B : integer);
      var
        T : integer;
      begin
        Writeln('2: A,B,T = ', A:3,B:3,' ',T);
        T := A;
        A := B;
        B := T;
        Writeln('3: A,B,T = ', A:3,B:3,' ',T);
      end;  { процедуры Swap }

      begin { основное тело программы Confused }
        A := 10; B := 20; T := 30;
        Writeln('1: A,B,T = ', A:3,B:3,' ',T);
        Swap(B,A);
        Writeln('4: A,B,T = ', A:3,B:3,' ',T);
      end. { программы Confused }

      Что будет выдавать на экран эта  программа?  Нечто  подобное
 приведенному ниже.

      1: A,B,T =  10 20 30
      2: A,B,T =  20 10 22161
      3: A,B,T =  10 20 20
      4: A,B,T =  20 10 30

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


 = 210 =

      В этом примере нет ошибки как таковой, однако проблемы могут
 возникнуть,  когда вы будете думать, что вы модифицируете нечто в
 то время,  как этого не происходит. Например, значение переменной
 T  в  основном теле программы остается без изменений,  хотя можно
 было  бы  подумать,  что  оно  изменяется.  Данный  случай  можно
 рассматривать как противоположность ошибкам, называемым "скрытыми
 эффектами", которые были рассмотрены ранее.

      Если же в программе сделаны приведенные ниже  описания,  это
 может привести к еще большей путанице.

      type
        RecType = record
          A,B : integer;
        end;

      var
        A,B : integer;
        Rec : RecType;

      В пределах оператора with обращения к A и B  будут  являться
 обращениями к полям записи, а не к переменным.

 Лишние точки с запятой
 ----------------------

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

      program Test;
      var
        I,J, : Integer;
      begin
        for I := 1 to 20 do;
        begin
          J := I * I;
          Writeln(I:2,' ',J:4);
        end;
        Writeln('Все сделано!')
      end.

      Эта программа  не  будет  выдавать  на  экран  список первых
 двадцати целых чисел и их квадратов. Она выдаст только

      20 400
      Все сделано!

      Это произошло  потому,  что  оператор  for  I := 1 to 20 do;
 заканчивается точкой с запятой.  Это означает,  что 20 раз  будет

 = 211 =

 выполняться   пустой   оператор.   После  этого  будут  выполнены
 операторы блока begin..end,  а  затем  второй  оператор  Writeln.
 Чтобы  исправить  эту ошибку,  надо просто убрать точку с запятой
 после слова do.

 Неопределенное значение, возвращаемое функцией
 ----------------------------------------------

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

      const
        NLMax = 100;
      type
        NumList = array[1..NLMax] of integer;
        ...
      function FindMax(List : NumList; Count : integer) : integer;
      var
        I,Max : integer;
      begin
        Max := List[1];
        for I := 2 to Count do
          if List[I] > Max then
          begin
            Max := List[I];
            FindMax := Max
          end
      end; { функции FindMax }

      Функция будет   работать   прекрасно   до   тех   пор,  пока
 максимальным не будет значение List[1].  В  этом  случае  функции
 FindMax не будет присвоено никакого значения.  Правильный вариант
 этой функции будет выглядеть так:

      begin
        Max := List[1];
        for I := 2 to Count do
          if List[I] > Max then
            Max := List[I];
            FindMax := Max
      end; { функции FindMax }

 Уменьшение значений переменных типа byte и word
 -----------------------------------------------

      Не следует  допускать  отрицательного  приращения  скалярных
 беззнаковых переменных (типа byte и word) при проверке их  на  >=
 0. В приведенном ниже фрагменте имеется бесконечный цикл.

      var

 = 212 =

        w : word;
      begin
        w := 5;
        while w >= 0 do
          w := w - 1;
      end.

      После пятой итерации значение переменной w становится равным
 нулю.  При следующем проходе ее значение "уменьшается"  до  65535
 (поскольку значения типа word лежат в диапазоне от 0 до 65535), и
 продолжает удовлетворять условию >= 0. В таких случаях необходимо
 использовать переменные типа integer или longint.

 Игнорирование границ или особых случаев
 ---------------------------------------

      Обратите внимание,  что в  обеих  версиях  функции  FindMax,
 приведенных в предыдущем разделе, предполагается, что Count >= 1.
 Однако в некоторых случаях значение Count может быть  равно нулю,
 то  есть  список  будет пуст.  Если в этом случае вызвать функцию
 FindMax,  она возвратит значение,  которое  хранится  в  List[1].
 Аналогично,  если  Count  > NLMax,  вызов функции либо приведет к
 ошибке периода выполнения (если включен режим  контроля  границ),
 либо  поиск  максимального значения будет производиться в ячейках
 памяти, находящихся за пределами массива List.

      В данном случае имеется два возможных решения проблемы. Одно
 из них,  конечно же, заключается в том, чтобы никогда не вызывать
 функцию FindMax,  если Count не находится в  диапазоне  1..NLMax.
 Причем это относится не только к данному примеру;  один из важных
 аспектов  хорошего  программирования   состоит   в   том,   чтобы
 определять  для каждой подпрограммы условия ее вызова и проверять
 эти условия при каждом вызове подпрограммы.

      Другое решение состоит в том, чтобы проверять значение Count
 и  возвращать  некоторое  предопределенное значение,  если оно не
 лежит в диапазоне 1..NLMax.  Например,  можно было бы  переписать
 тело функции FindMax следующим образом:

      begin
        if (Count < 1) or (Count > NLMax) then
          Max := -32768
        else
        begin
          Max := List[1];
          for I := 2 to Count do
            if List[I] > Max then
            Max := List[I];
        end;
        FindMax := Max
      end; { функции FindMax }

 = 213 =


      Эта функция вызовет следующий вид ошибки программирования на
 Паскале: ошибку выхода за границы диапазона.

 Ошибки выхода за границы диапазона
 ----------------------------------

      В языке Turbo Pascal  предусмотрен  режим  контроля  границ,
 который по умолчанию выключен.  Благодаря этому формируется более
 быстрый и компактный код,  но в то же время это может привести  к
 возникновению  ряда  ошибок,  таких  как  присваивание переменной
 значения,   находящегося   вне    допустимого    диапазона    или
 индексирование  несуществующих элементов массива,  как показано в
 приведенном выше примере.

      Первым шагом в нахождении подобных ошибок является включение
 режима  контроля  границ  с  помощью директивы компилятора {$R+},
 помещенной в  текст  программы,  компилирование  программы  и  ее
 повторный   запуск.  Если  вы  знаете  (или  предполагаете),  где
 находится   ошибка,   вы   можете   поместить    эту    директиву
 непосредственно перед этим фрагментом программы и соответствующую
 директиву {$R-} после него, включая таким образом контроль границ
 только  для  данного  фрагмента.  Если возникнет ошибка выхода за
 границы диапазона,  программа будет остановлена  и  будет  выдано
 соответствующее  сообщение об ошибке периода выполнения,  а Turbo
 Pascal покажет вам, где произошла ошибка.

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

      function FindVal(List: NumList; Count,Val: integer) : integer;
      var
        I : integer;
      begin
        FindVal := 0;
        I := 1;
        while (I <= Count) and (List[I] <> Val) do
          Inc(I);
        if I <= Count then
          FindVal := I
      end; { функции FindVal }

      Все здесь очень очень хорошо,  однако функция может  вызвать
 ошибку  периода  выполнения,  если  значение  Val  не находится в

 = 214 =

 пределах массива List и используется режим нормального вычисления
 булевских   выражений.   Почему?  Потому  что  когда  выполняется
 последняя проверка в вершине цикла while,  значение I будет равно
 Count+1.  Если  Count=NLMax,  произойдет выход за границы массива
 List.

      Такая проблеме  может  иметь  два  решения.  Одно   из   них
 заключается в том, чтобы отменить контроль диапазона. Однако, это
 может внести незаметные ошибки, особенно если рассматриваемый код
 фактически изменяет  значения.  Лучшее,  показанное  выше решение
 состоит в том,  чтобы выбрать  вычисление  логического  выражения
 либо при помощи команды Options|Compiler|Boolean, либо при помощи
 директивы {$B-}. Таким образом, если I > Count, то выражение

      List[I] <> Val

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

      Ниже описаны    некоторые    ошибки,     характерные     для
 программирования   на   языке  ассемблера.  Для  получения  более
 подробной информации об этих ошибках  и  способах  их  устранения
 следует  обратиться  к  Руководству  пользователя  по языку Turbo
 Assembler (Turbo Assembler User's Guide).

 Отсутствие команды возврата в DOS
 ---------------------------------

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

 Отсутствие команды RET
 ----------------------

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

 Формирование возврата неправильного типа
 ----------------------------------------

 = 215 =


      Директива PROC  выполняет  два  действия.   Во-первых,   она
 определяет имя, по которому будет вызываться некоторая процедура.
 Во-вторых,  она задает тип процедуры:  дальняя (far) или  ближняя
 (near).  Команды возврата RET в процедурах должны соответствовать
 типу процедуры, не правда ли?

      И да  и  нет.  Проблема состоит в том,  что возможно и часто
 желательно   группировать   отдельные   подпрограммы   в   единую
 процедуру;  и поскольку эти подпрограммы не имеют соответствующей
 директивы  PROC,  их  команды  RET   соответствуют   типу   общей
 процедуры,  который  не  обязательно  соответствует  типу  каждой
 отдельной подпрограммы.

 Неправильная расстановка операндов
 ----------------------------------

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

      mov ax,bx

      означает "переслать AX в BX",  то  эта  строка  будет  точно
 выполняться   слева   направо,  и  именно  таким  образом  многие
 производители микропроцессоров  разрабатывают  языки  ассемблера.
 Однако  фирма Intel при разработке языка ассемблера для процессора
 8086 предпочла другой подход,  и  для  нас  эта  строка  означает
 "переслать  BX  в  AX",  что  в  некоторых  случаях может вызвать
 путаницу.

 Отсутствие стека или резервирование слишком маленького стека
 ------------------------------------------------------------

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

 Вызов подпрограммы, который уничтожает содержимое нужных регистров
 ------------------------------------------------------------------

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

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


 Неправильное использование условных переходов
 ---------------------------------------------

      Обилие команд  условного  перехода  в  языке ассемблера (JE,
 JNE,  JC, JNC, JA, JB, JG и т.д.) обеспечивают большую гибкость в
 написании   программы   и   в   то  же  время  может  привести  к
 использованию не той  команды,  которая  требуется  в  конкретном
 случае.  Кроме  того,  поскольку  для  обработки  условия в языке
 ассемблера требуется как минимум две строки (одна для сравнения и
 одна  для  условного  перехода),  а для обработки сложных условий
 значительно  больше,  обработка  условий   в   ассемблере   менее
 интуитивна и больше подвержена ошибкам, чем в Паскале или Си.

 Ошибки при повторении команд обработки строк
 --------------------------------------------

      Команды обработки строк  имеют  одну  необычную  особенность:
 после  их  выполнения используемые ими указатели сдвигаются таким
 образом,  что указывают на адрес,  отличающийся на 1 байт (или  2
 байта,  если если длина команды равна одному слову) от последнего
 обработанного адреса. Это может привести к некоторой путанице при
 повторении команд обработки строк, особенно команд REP SCAS и REP
 CMPS.

 Неправильный расчет на нулевое значение CX
 ------------------------------------------

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

 Неправильная установка флага направления
 ----------------------------------------

      При выполнении  команды  обработки  строк  связанные  с  ней
 указатели  (SI,  DI   или   оба)   получают   положительное   или
 отрицательное   приращение.   Это   зависит  от  состояния  флага
 направления.  С помощью команды CLD флаг направления  может  быть
 сброшен в 0;  в этом случае при выполнении команд обработки строк
 указатель получает положительное приращение (смещается  в сторону
 старших   адресов).   С  помощью  команды  STD  флаг  направления
 устанавливается  в  1;   в   этом   случае   указатель   получает

 = 217 =

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

 Ошибки при повторении команд сравнения строк
 --------------------------------------------

      Команда CMPS  сравнивает содержимое двух областей памяти,  а
 команда SCAS  сравнивает  содержимое  накапливающего  регистра  с
 содержимым области памяти. Когда перед одной из этих команд стоит
 префикс REPE, она выполняет сравнение, либо пока CX не становится
 равным  нулю,  либо  пока не обнаружится,  что операнды не равны.
 Когда  перед  командой  стоит  префикс   REPNE,   она   выполняет
 сравнение,  либо пока CX не становится равным нулю,  либо пока не
 обнаружится что операнды равны.  К несчастью,  легко  перепутать,
 где какой префикс нужно использовать.

 Ошибки при назначении сегмента строк
 ------------------------------------

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

 Неправильное преобразование из байта в слово
 --------------------------------------------

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

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

      shr cx,l

      приведет к потере байта,  если CX имеет  нечетное  значение,
 поскольку младший значащий бит будет сдвинут за пределы слова.

 = 218 =


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

 Использование нескольких префиксов
 ----------------------------------

      Команды обработки  строк  с  несколькими префиксами работают
 ненадежно, и их следует по возможности избегать.

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

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

 Уничтожение содержимого регистра при умножении
 ----------------------------------------------

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

 Ошибки, связанные с изменением содержимого некоторых
 регистров командами обработки строк
 ----------------------------------------------------

      Команды обработки строк,  такие как MOVS, STOS, LODS, CMPS и
 SCAS,  могут  влиять  на  состояние некоторых флагов и содержимое
 трех  регистров  при   выполнении   единственной   команды.   При
 использовании   команд   обработки  строк  следует  помнить,  что
 содержимое одного из  регистров  SI  или  DI  (или  обоих  сразу)
 получает    положительное   или   отрицательное   приращение   (в
 зависимости от состояния флага направления) при каждом выполнении
 команды  обработки  строк.  Содержимое регистра CX также получает
 отрицательное  приращение  как  минимум  один  раз  и,  возможно,
 уменьшается  до  нуля  при каждом использовании команды обработки
 строк с префиксом REP.

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

      В то время как  одни  команды  неожиданно  для  программиста
 влияют на состояние регистров и флагов,  другие команды не влияют
 даже на те флаги,  состояние которых было бы желательно изменить.

 = 219 =


 Слишком длительное ожидание использования флагов
 ------------------------------------------------

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

 Смешение операндов в памяти и промежуточных операндов
 -----------------------------------------------------

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

 Ошибки, связанные с возвратом в начало сегмента
 -----------------------------------------------

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

 Сохранение содержимого регистров при обработке прерываний
 ---------------------------------------------------------

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

 Ошибки, связанные с игнорированием групп в таблицах
 операндов и данных
 ---------------------------------------------------

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

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

      К сожалению,  тот способ, который используется для обработки
 сегментных групп в языке Macro Assembler фирмы  Microsoft (MASM),
 может  вызвать некоторые проблемы,  и пока не появился язык Turbo
 Assembler,  сегментные  группы  доставляли  программистам   много
 неприятностей.  И  хотя  этих неприятностей практически невозможно
 было  избежать,  сегментные   группы   были   нужны   для   связи
 ассемблерного кода с языками высокого уровня, такими как Си.

      В режиме Quirks языка MASM Turbo Assembler эмулирует MASM, и
 это означает,  что в этом режиме он имеет те же проблемы,  что  и
 MASM. Если вы не собираетесь использовать режим Quirks языка MASM,
 можете больше ничего о нем не читать,  однако если вы  планируете
 работать с этим режимом, вам следует обратиться за дополнительной
 информацией к Руководству пользователя по языку  Turbo Assembler.
                        Проверка программы на точность                         
 -----------------------------------------------------------------

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

 Проверка граничных условий   ------------------------------------

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

 Ошибочные входные данные   --------------------------------------

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


 = 221 =

 Пустые входные данные   -----------------------------------------

      Этот случай   часто   игнорируется  программистами  как  при
 тестировании,  так и при разработке программ.  Если  в  программе
 предусмотрено  разумное  поведение  при  отсутствии части входных
 данных (то есть работа по умолчанию),  это существенно  облегчает
 ее использование.
                    Отладка как стадия разработки программы                    
 -----------------------------------------------------------------

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

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

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

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

      В этом  примере  отладки  используются  некоторые   способы,
 которые  были  рассмотрены в предшествующих разделах.  Программа,
 которую   мы   будем   отлаживать   представляет   собой   версию
 демонстрационной программы, рассмотренной в главе 3 (TCDEMO.C или
 TPDEMO.PAS) с той  лишь  разницей,  что  она  содержит  несколько
 умышленно вставленных ошибок.

 = 222 =


      Убедитесь в том, что в текущей директории имеются два файла,
 необходимые для  выполнения  демонстрационной  отладки.  Если  вы
 собираетесь  отлаживать  программу  на  языке  Turbo Pascal,  вам
 потребуются   файлы   TPDEMOB.PAS   и   TPDEMOB.EXE.   Если    вы
 программируете   на   Си,   вам  понадобятся  файлы  TCDEMOB.C  и
 CDEMOB.EXE (Буква "B" в именах программ означает  "buggy",  т.е.
 "с ошибкой".
                          Сеанс отладки си-программы                           
 -----------------------------------------------------------------

      В этом разделе в качестве примера используется  программа на
 языке  Turbo C.  Если вы программируете на Паскале,  обратитесь к
 разделу , в котором описан сеанс отладки программы на языке Turbo
 Pascal.

 Поиск ошибок    -------------------------------------------------

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

      TCDEMOB

      Программа попросит  вас  ввести   строки   текста.   Введите
 следующие две строки:

      one two three
      four five six

      Ввод данных заканчивается последней  пустой  строкой.  После
 этого  программа TCDEMOB распечатает на экране результаты анализа
 введенного текста:

      Arguments:
      Enter a line (empty line to end): one two three
      (Введите строку (пустую строку для окончания): )
      Enter a line (empty line to end): four five six
      Enter a line (empty line to end):
      Total number of letters = 7
      (Общее количество букв)
      Total number of lines = 6
      (Общее количество строк)
      Total word count = 2
      (Общее количество слов)
      Average number of words per line = 0.3333333
      (Среднее количество слов в строке)
      'E' occurs 1 times, 0 times at start of a word
      ('E' встретилась 1 раз, 0 раз в начале слова)

 = 223 =

      'F' occurs 1 times, 1 times at start of a word
      'N' occurs 1 times, 0 times at start of a word
      '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 1 word 3 characters long
      (Имеется 1 слово длиной в три символа)
      There is 1 word 4 characters long

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

 Разработка плана действий   -------------------------------------

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

      Теперь, после   того,   как   мы  немного  поразмышляли  над
 проблемой и разработали примерный план  действий,  пора  начинать
 отладку  программы.  Теперь  наша  задача  состоит  в том,  чтобы
 проверить подпрограмму makeintwords и  посмотреть,  правильно  ли
 она  разбивает  строку  на  слова  с нулевым окончанием,  а затем
 посмотреть,  правильно  ли  подпрограмма  analyzewords  вычисляет
 количество слов в анализируемой строке.

 Запуск отладчика Turbo Debugger   -------------------------------

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

      TD TCDEMOB

      Turbo Debugger    загрузит    демонстрационную    программу,
 содержащую  ошибки,  и  отобразит  свой  исходный экран.  Если вы
 захотите закончить учебный сеанс и вернуться  в  DOS,  вы  можете
 сделать это в любой момент, нажав клавиши Alt-X. Если вы что-либо
 безнадежно испортите,  вы сможете в  любой  момент  перезагрузить
 демонстрационную  программу  и начать все сначала,  нажав клавиши
 Ctrl-F2.  (Заметим,  что при этом не удаляются точки  останова  и
 выражения, занесенные в окно слежения.)

 = 224 =


      Поскольку, первое,  что  мы  хотели сделать,  это проверить,
 правильно  ли  работает   подпрограмма   makeintwords,   выполним
 программу  до  этой подпрограммы и проверим ее работу.  Это можно
 сделать двумя способами:  выполнять подпрограмму  makeintwords  в
 пошаговом  режиме,  контролируя  при этом правильность ее работы,
 или  остановить  программу  после  того,  как   будет   выполнена
 подпрограмма  makeintwords  и проверить,  насколько правильно она
 сработала.

      Поскольку подпрограмма    makeintwords    выполняет     ясно
 определенную  задачу,  можно  легко определить,  правильно ли она
 работает, просто проверив содержимое ее выходного буфера. Поэтому
 давайте  выберем  второй способ.  Переместите выделяющий курсор к
 строке 42 и нажмите клавишу F4, чтобы выполнить программу до этой
 строки.  Появится  экран  вывода программы,  и вы должны ввести с
 клавиатуры:

      one two three

 а затем нажать клавишу Enter.

 Проверка значений переменных   ----------------------------------

      Теперь программа остановлена на строке,  которая следует  за
 вызовом  подпрограммы  makeintwords.  Давайте проверим содержимое
 массива buffer,  и убедимся в том,  что  он  содержит  правильные
 значения.  Переместите курсор на одну строку вверх, подведите его
 к слову buffer и нажмите клавиши Alt-F10 I  (команда  Inspector),
 чтобы открыть окно проверки и посмотреть в нем содержимое массива
 buffer.  Для  просмотра  в  окне  элементов  массива  используйте
 клавиши перемещения курсора.  Обратите внимание, что makeintwords
 действительно помещает один нулевой символ (()) в  конце  каждого
 обнаруженного слова.  Это означает,  что теперь следует выполнить
 еще один небольшой фрагмент программы  и  убедиться  в  том,  что
 подпрограмма  analyzewords  работает  правильно.  Сначала удалите
 окно проверки,  нажав клавишу Esc.  Затем дважды нажмите  клавишу
 F7,    чтобы   выполнить   программу   до   начала   подпрограммы
 analyzewords.

 Точки останова   ------------------------------------------------

      Убедитесь в том,  что analyzewords была вызвана с правильным
 указателем на буфер,  подведя курсор к слову bufp и нажав клавиши
 Alt-F10 I. Вы увидите, что bufp действительно указывает на строку
 с нулевым окончанием 'one'.  Удалите окно проверки, нажав клавишу
 Esc. Поскольку мы предполагаем, что ошибка возникает при подсчете
 количества  символов  и слов,  давайте установим точку останова в
 тех местах, где производится подсчет символов и слов.

      1. Переместите курсор на строку 93  и  нажмите  клавишу  F2,

 = 225 =

 чтобы установить точку останова.

      2. Переместите  курсор  на  строку  97 и установите еще одну
 точку останова.

      3. И наконец,  установите точку останова на строке  99,  так
 чтобы  вы  смогли  проверить,  какое  количество  символов  будет
 возвращать данная функция.

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

 Окно слежения   -------------------------------------------------

      Запустите программу,  нажав  клавишу  F9.  Работа  программы
 остановится,  когда  будет  достигнута  точка  останова  в строке
 93.Теперь мы хотим посмотреть на значение  переменной  charcount.
 Поскольку  желательно  проверять  ее  значения каждый раз,  когда
 будет достигнута точка  останова,  это  идеальный  случай,  чтобы
 использовать  команду Watch и занести переменную в окно слежения.
 Подведите курсор к слову charcount и нажмите клавиши  Alt-F10  W.
 Теперь  в  окне  слежения,  расположенном  в нижней части экрана,
 отображается текущее значение данной переменной,  равное  0.  Для
 того   чтобы   убедиться,  что  количество  символов  вычисляется
 правильно,  выполним одну строку исходного текста,  нажав клавишу
 F7.   Окно   слежения  покажет,  что  теперь  значение  charcount
 действительно равно 1.

 Блок диалога Evaluate/Modify   ----------------------------------

      Снова запустите  программу,  нажав  клавишу  F9.  Вы   опять
 возвращаетесь  к  строке  93,  добавив  еще один символ.  Нажмите
 клавишу F9 еще два раза,  чтобы ввести последнюю букву в слове  и
 нулевое  окончание.  Теперь charcount правильно содержит значение
 3,  а массив wordcounts готов обновиться,  чтобы сосчитать слово.
 Пока  все прекрасно.  Нажмите клавишу F9,  чтобы начать обработку
 следующего слова в буфере. Ага! Что-то не так.

      Вы ожидали,  что программа снова остановится  на  строке  93
 ,однако этого не произошло. Она выполнилась до оператора, который
 выполняет возврат из функции. На строку 99 можно попасть только в
 том  случае,  если  условие,  проверяемое в цикле while,  который
 начинается на строке 83, больше не выполняется. То есть выражение
 *bufp !=0 должно быть ложным.

      Чтобы проверить   это,  вернитесь  обратно  к  строке  83  и
 пометьте все выражение *bufp !=0,  поместив курсор на его  первый
 символ,  нажав  клавишу  Ins и переместив курсор к его последнему

 = 226 =

 символу.  Теперь вычислите значение этого выражения,  открыв блок
 диалога  Data|Evaluate  Modify  и нажав Enter,  чтобы подтвердить
 помеченное выражение.  Его значение действительно равно 0. Дважды
 нажмите клавишу Esc, чтобы вернуться в окно модуля.

 Эврика!   -------------------------------------------------------

      Теперь пришло время исправлять ошибку.  Причина,  по которой
 bufp указывает на 0,  заключается  в  том,  что  внутренний  цикл
 while,  начинающийся  на  строке  86,  оставляет этот указатель в
 конце  слова.  Чтобы  перейти  к  следующему  слову,   необходимо
 нарастить  значение  bufp  после того,  как он будет указывать на
 нулевое окончание предыдущего  слова.  Чтобы  это  сделать,  надо
 вставить  перед строкой 96 оператор bufp++.  Для этого можно было
 бы перекомпилировать программу  с  вставленным  этим  оператором,
 однако Turbo Debugger позволяет вставлять в программу выражения с
 помощью специальных точек останова.

      Для этого сначала  перезагрузите  программу,  нажав  клавиши
 CtrlF2,  чтобы  эксперимент был чистым.  Теперь удалите все точки
 останова,  установленные вами в предыдущем сеансе,  нажав клавиши
 Alt-B  D.  Перейдите  к строке 97 и снова установите на ней точку
 останова,  нажав клавишу  F2.  Теперь  нажатием  клавиш  Alt-V  B
 откройте  окно  точек останова.  Определите данную точку останова
 таким образом,  чтобы при каждом ее проходе выполнялось выражение
 bufp++.


      1. Выберите View|Breakpoints.

      2. Откройте локальное меню окна Breakpoints, нажав Alt-F10.

      3. Выберите   Set|Options   для   открытия   блока   диалога
 Breakpoint Options.

      4. Установите селективные кнопки  в положение Execute.

      5. Нажмите Tab для перехода к запросу Action Expression.

      6. Введите выражение bufp++.

      7. Нажмите  Esc  для закрытия диалогового блока и Alt-F3 для
 возврата в окно Module.

      Теперь запустите программу,  нажав клавишу F9.  Введите  две
 обычные строки:

      one two three
      four five six

      В ответ на третий запрос  нажмите  Enter,  а  по  завершении

 = 227 =

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

      Обратите внимание,  что программа стала работать значительно
 лучше.  Общее  количество слов и строк осталось неправильным,  но
 таблицы  рассчитываются  верно.  Остановите  программу  в  начале
 функции  printstatistics  и  проверьте,  правильные  ли  исходные
 данные она получает для вывода на  экран.  Сначала  перезагрузите
 программу  нажатием  клавиш Ctrl-F2,  чтобы вернуть ее в исходное
 состояние.  Затем перейдите к строке 104 и  нажмите  клавишу  F4,
 чтобы  выполнить  программу  до  этой  точки.  Подведите курсор к
 аргументу nlines и нажмите клавиши Alt-F10 I, чтобы проверить его
 значение. Оно равно 6, хотя должно быть равно 2.

      Теперь вернитесь к тому месту,  где происходит вызов функции
 из main и снова проверьте значение nlines.  Переместите курсор  к
 строке 36, подведите его к слову nlines и нажмите клавиши Alt-F10
 I,  чтобы проверить значение.  Здесь значение nlines равно 2, что
 является  правильным.  Если  вы  спуститесь ниже к строке 46,  вы
 заметите,  что аргументы  nwords  и  nlines  поменялись  местами.
 Компилятор никак не мог знать, что вы собирались использовать эти
 аргументы в другой последовательности.

      Если вы  исправите эти две ошибки,  программа будет работать
 правильно.  Файл TCDEMO.EXE  содержит  исправленную  версию  этой
 программы, и, если хотите, вы можете запустить ее.
                        Сеанс отладки паскаль-программы                        
 -----------------------------------------------------------------

      Оставшаяся часть  данной  главы  посвящена  описанию  сеанса
 отладки демонстрационной программы на языке Turbo Pascal. Если вы
 программируете  на  Си,  вы  должны  были  просмотреть предыдущие
 разделы,  в которых описан сеанс отладки программы на языке Turbo
 C.

 Поиск ошибок   --------------------------------------------------

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

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

      TPDEMOB first second third

      Программа попросит   вас   ввести  несколько  строк  текста.
 Введите две строки,  которые в точности совпадают в  приведенными
 ниже:

 = 228 =


      ABC DEF GHI
      abc def ghi

      Последняя пустая строка завершает ввод данных.  После  этого
 программа   TPDEMOB  распечатает  на  экране  результаты  анализа
 введенных данных:

      9 letter(s) in 3 word(s) in 2 lines
      (9 букв в 3 словах в 2 строках)
      Average of 0.67 words per line
      (В среднем 0.67 слов на строку)
      Word length:  1  2  3  4  5  6  7  8  9  10
      (Длина слова)
      Frequency:    0  0  3  0  0  0  0  0  0  0
      (Частота)

      Letter:       M
      (Буква)
      Frequency:    1   1   1   1   1   1   1   1   1   0   0   0   0
      (Частота)
      Word starts:  1   0   0   1   0   0   1   0   0   0   0   0   0
      (В начале слова)

      Letter        Z
      Frequency:    0   0   0   0   0   0   0   0   0   0   0   0   0
      Word starts:  0   0   0   1   0   0   0   0   0   0   0   0   0

      Program name: C:\td\tpdemob.ex?
      (Имя программы)
      Command line parameters: firs? secon? third
      (параметры командной строки)

      Проанализировав результаты  работы программы,  можно выявить
 пять самостоятельных ошибок:

      1. Неправильно подсчитано количество слов (3 вместо 6);

      2. Неправильно вычислено среднее количество  слов  в  строке
 (0.67 вместо 3);

      3. В  заголовках второй и третьей таблиц указана только одна
 буква (вместо A..M и N..Z);

      4. Вы ввели две строки,  каждая из которых содержит буквы от
 A до I, однако в таблицах частоты употребления букв для каждой из
 них указано единичное значение.

      5. Последние символы введенных параметров  командной  строки
 были  утеряны  и  вместо них отображаются случайные символы (хотя
 последний параметр отображается правильно).

 = 229 =


 Разработка плана действий   -------------------------------------

      Прежде всего  вы  должны  решить,  какую  ошибку   атаковать
 первой.  Здесь можно воспользоваться хорошо проверенным правилом,
 которое  гласит,  что  начинать  надо  с  той   ошибки,   которая
 предположительно   возникает   первой.  В  этой  программе  после
 инициализации данных с помощью процедуры Init данные, введенные с
 клавиатуры,  считываются функцией GetLine, а затем обрабатываются
 процедурой  ProcessLine,  пока  пользователь  не  введет   пустую
 строку. Процедура ProcessLine проверяет каждую введенную строку и
 изменяет значения глобальных счетчиков.  Затем результаты анализа
 отображаются  на  экране  процедурой  ShowResults.  И наконец,  в
 полностью независимой подпрограмме процедура ParamsOnHeap создает
 в динамической памяти связный список параметров командной строки,
 а затем разделяет его на элементы и печатает список  параметров в
 конце программы.

      Среднее количество  слов  в  строке  вычисляется  процедурой
 ShowResults  на  основе  количества  строк  и  количества   слов.
 Поскольку количество слов по-видимому вычисляется неправильно, вы
 должны,  прежде   всего   проверить   процедуру   ProcessLine   и
 посмотреть,  как  изменяется  значение переменной NumWords.  Даже
 если взять неверное значение NumWords,  среднее количество слов в
 строке, равное 0.67, является совершенно бессмысленным. Возможно,
 ошибка   допущена   в   вычислениях,    выполняемых    процедурой
 ShowResults, которая также заслуживает вашего внимания.

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

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

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

 Запуск отладчика Turbo Debugger   -------------------------------

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


 = 230 =

      TD TPDEMOB first second third

      Turbo Debugger    загрузит    демонстрационную    программу,
 содержащую ошибки,  и отобразит свой исходный экран,  меню и т.д.
 Если вы захотите закончить учебный сеанс и вернуться  в  DOS,  вы
 можете сделать это в любой момент,  нажав клавиши Alt-X.  Если вы
 что-либо  безнадежно  испортите,  вы  сможете  в   любой   момент
 перезагрузить  демонстрационную  программу  и начать все сначала,
 нажав клавиши CtrlF2.  (Заметим,  что при этом не удаляются точки
 останова и выражения, занесенные в окно слежения.)

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

 Навигация по программе   ----------------------------------------

      Итак, мы решили запустить программу и проследить в пошаговом
 режиме   выполнение   процедуры   ProcessLine.   Для  этого  надо
 воспользоваться одним из нескольких способов.  Можно четыре  раза
 нажать  клавишу F8 (чтобы выполнить вызовы процедур и функций, не
 заходя в них),  а затем один раз нажать клавишу F7 (чтобы войти в
 процедуру  ProcessLine  и начать ее пошаговое выполнение).  Можно
 также переместить курсор к строке 231, нажать клавишу F4 (команда
 Go to Cursor),  а затем нажать клавишу F7, чтобы начать пошаговое
 выполнение процедуры ProcessLine.

      Верится в это или нет,  но этот список можно еще продолжить,
 однако  вы  попытайтесь  воспользоваться  только  одним  из  них:
 нажмите клавиши Alt-F9 и  на  экране  появится  поле  запроса,  в
 которое  надо  ввести  адрес кода,  к которому требуется перейти.
 Введите  слово  processline  и  нажмите  Enter.  Программа  будет
 выполняться  до тех пор,  пока управление не перейдет к процедуре
 ProcessLine.  Введите те же данные, что и раньше, когда программа
 просила ввести строку (то есть ABC DEF GHI).

      В этой  подпрограмме имеется несколько циклов.  Внешний цикл
 проверяет всю строку.  Внутри этого цикла имеется  цикл,  который
 служит для пропуска символов,  которые не являются буквами, и еще
 один  цикл,  в  котором  производится  обработка  слов  и   букв.
 Переместите курсор к строке 133, в которой начинается цикл while,
 и нажмите клавишу F4 (команда Go to Cursor).

      В этом цикле производится проверка введенных данных  до  тех
 пор,  пока  не  будет достигнут конец строки или не будет найдена
 буква.  Последнее  условие  проверяется  путем  вызова  булевской

 = 231 =

 функции  IsLetter.  Нажмите  клавишу F7,  чтобы войти внутрь этой
 функции.  IsLetter является  вложенной  функцией,  которая  берет
 символьное  значение  и  возвращает  True,  если  символ является
 буквой,  и False в противном случае.  Даже  не  очень  тщательная
 проверка  позволяет  обнаружить,  что  она проверяет только буквы
 верхнего  регистра.  Она  должна  была  бы  проверять  символы  в
 диапазонах  'A'..'Z'  и  'a'..'z'  или  преобразовывать  символ в
 символ верхнего регистра прежде чем выполнять проверку.

      Беглый анализ введенных  строк  текста  дает  дополнительный
 ключ к нахождению источника ошибки.  Вы ввели буквы от 'A' до 'I'
 как верхнего,  так и нижнего регистров,  однако лишь половина  из
 них  была отражена при распечатке результатов.  Теперь вы знаете,
 почему это произошло.

      Вернитесь обратно к строке,  в  которой  вызывается  функция
 IsLetter,  воспользовавшись  еще  одним приемом отладки:  нажмите
 клавиши Alt-F8,  по которым программа выполняется до возврата  из
 текущей  процедуры или функции.  Поскольку вторая строка исходных
 данных,  abc def ghi,  содержит только символы нижнего  регистра,
 каждый  из  них  был воспринят программой как пустой (не буква) и
 был пропущен.  Это объясняет получение неверных  результатов  при
 подсчете  количества  букв  и слов и открывает первой и четверной
 ошибок.

 Блок диалога Evaluate/Modify   ----------------------------------

      Между прочим,  существует еще один способ,  который позволит
 выявить  неправильную  работу  функции  IsLetter.  Откройте  блок
 диалога  Evaluate/Modify,  нажав  клавиши  Alt-D  E   и   введите
 следующее выражение:

      IsLetter('a') = IsLetter('A')

      Оба этих символа,  A и a,  являются буквами,  однако функция
 возвращает  значение  False,   которое   говорит   о   том,   они
 обрабатываются   функцией  IsLetter  неодинаково.  (Блок  диалога
 Evaluate/Modify и окно слежения можно использовать для вычисления
 выражений, выполнения присваиваний или вызова процедур и функций.
 Для получения более подробной информации обратитесь к главе 6).

 Проверка значений переменных   ----------------------------------

      Две ошибки позади и три впереди. Ошибку #2 найти значительно
 проще, чем две предыдущие. Нажмите клавиши Alt-F8, чтобы выйти из
 процедуры ProcessLine,  затем переместите курсор к строке  234  и
 нажмите клавишу F4, чтобы выполнить программу до этой строки.

      Программа попросит вас ввести строку.  Введите abc def ghi и
 нажмите Enter,  затем нажмите Enter еще раз, когда появится новый
 запрос. Теперь нажмите F7, чтобы войти в процедуру ShowResults.

 = 232 =


      Напомним, что   мы   пытаемся   определить,  почему  среднее
 количество слов в строке отображается неправильно.  Первая строка
 в  процедуре  ShowResults  вычисляет  количество  строк  в слове,
 вместо того,  чтобы вычислять количество слов  в  строке.  Теперь
 понятно: эти два терма надо поменять местами.

      Теперь хорошо бы убедиться в том,  что переменные NumLines и
 NumWords содержат те  значения,  которые  вы  ожидаете.  Значение
 NumLines  должно быть равно 2,  а значение NumWords (поскольку мы
 еще не исправили ошибку в функции IsLetter) должно быть  равно 3.
 Подведите  курсор  к  слову NumLines и нажмите клавиши Alt-F10 I,
 чтобы проверить значение этой переменной.  В окне проверки  будет
 показан  адрес  переменной NumLines,  ее тип и текущее значение в
 десятичном   и   шестнадцатиричном    форматах.    Ее    значение
 действительно  равно  2,  поэтому  можно  оставить  его в покое и
 проверить значение NumWords.  Нажмите  Esc,  чтобы  закрыть  окно
 проверки, затем подведите курсор к слову NumWords и снова нажмите
 клавиши Alt-F10 I (вместо этого можно было  использовать активную
 клавишу  Ctrl-I).  Переменная  NumWords  действительно  имеет  то
 значение (неправильное),  которое мы ожидали,  то есть 3, поэтому
 ее тоже можно оставить в покое.

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

      Чтобы убедиться в этом,  нажмите клавишу Esc,  чтобы закрыть
 окно проверки,  нажмите клавиши Alt-R P,  чтобы завершить текущий
 сеанс  отладки,  нажмите клавишу F9,  чтобы запустить программу с
 начала,  а затем в ответ  на  запрос  программы  TPDEMOB  нажмите
 Enter.  Работа  программы  будет остановлена и на экране появится
 сообщение об ошибке периода выполнения.  Чтобы исправить  ошибку,
 вы должны модифицировать данный оператор следующим образом:


      if NumLines <> 0 then
        AvgWords := NumWords / NumLines
      else
        AvgWords := 0;

      Теперь покончено  с  ошибками #2 и #2б.  Но раз уж вы начали
 работать  с  окном  слежения,  попробуйте  использовать  его  для
 просмотра  содержимого  структуры  данных.  Переместите  курсор к
 описанию массива LetterTable в  строке  50.  Подведите  курсор  к
 слову  LetterTable и нажмите клавиши Alt-F10 I.  Вы увидите,  что
 это массив записей,  содержащий 26 элементов. Для просмотра всего

 = 233 =

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

 Слежение за переменными   ---------------------------------------

      Теперь перейдем  к  поиску  ошибки  в процедуре ShowResults,
 которая приводит к неправильному отображению  заголовков столбцов
 в  таблицах  (ошибки  #3).  Поскольку  работа  программы уже была
 остановлена в результате возникновения ошибки  деления  на  ноль,
 подготовьте ее к следующему сеансу,  нажав клавиши Alt-R P (чтобы
 вернуть программу в исходное состояние).  Затем  нажмите  клавиши
 AltF9, введите showresults и нажмите Enter. Теперь введите все те
 же данные ABC DEF GHI и нажмите Enter еще раз. И наконец, введите
 abc def ghi и дважды нажмите Enter.  Теперь Turbo Debugger должен
 остановить программу в начале процедуры ShowResults.

      ShowResults использует вложенную  процедуру  ShowLetterInfo,
 которая отображает таблицы букв. Переместите курсор вниз к строке
 103, нажмите клавишу F4, а затем нажмите клавишу F7, чтобы начать
 выполнение процедуры ShowLetterInfo в пошаговом режиме.

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

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

 И еще одна ошибка...   ------------------------------------------

      Теперь пришло   время  взяться  за  эту  странную  ошибку  в

 = 234 =

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

      Для поиска  ошибки  воспользуемся  окном  слежения.  Нажмите
 клавиши Alt-F9,  введите parmsonheap и нажмите Enter. В цикле for
 просматриваются все параметры командной строки, создается связный
 список,  и  каждая  строка  копируется  в  динамическую  область.
 Указатель Head указывает на  начало  списка,  Tail  указывает  на
 последний узел списка,  а Temp используется в качестве временного
 буфера для  выделения  и  инициализации  нового  узла.  Поскольку
 данные строки были запорчены,  нажмите клавишу Ctrl-F7 и занесите
 следующее выражение в окно слежения:

      Tail^.Parm^

      Оно позволит нам следить за данными строки, которые хранятся
 в   последнем   узле  списка.  Конечно  же,  это  значение  будет
 бессмысленным,  пока переменная Tail не будет инициализирована  в
 строке 207.

      Вместо того,  чтобы  выполнять процедуру в пошаговом режиме,
 просто будем проверять значение  в  окне  слежения  после  каждой
 итерации.  Переместите  курсор к строке 208 и нажмите клавишу F2,
 чтобы установить на ней точку останова.  Теперь  нажмите  клавишу
 F9, чтобы выполнить программу до этой строки. Если вы используете
 операционную систему DOS версии 3.x,  вы увидите в окне  слежения
 полный  маршрут  программы  TPDEMOB.EXE  (если вы используете DOS
 версии 2.x,  вы увидите пустую строку;  в этом случае просто  еще
 раз нажмите клавишу F9,  чтобы возобновить выполнение программы).
 Данные строки выглядят очень хорошо.

      Нажмите клавишу F9,  чтобы выполнить цикл еще раз.  И  снова
 данные выглядят хорошо. Теперь вы знаете, что данные копируются в
 динамическую область  правильно.  Чтобы  проверить,  не  были  ли
 данные уже запорчены, можно использовать окно проверки. Подведите
 курсор к слову Head в строке 203 и нажмите клавиши Alt-F10 I.

      Нажав клавишу  Enter  и  затем  "стрелку  вниз",   проверьте
 значение,   на  которое  указывает  переменная  Parm.  Вы  видите
 содержимое первого узла списка,  и данные  строки  уже  искажены.
 Если вы нажмете клавиши Esc, "Стрелка вниз", а затем снова Enter,
 вы откроете окно проверки для второго узла списка. Нажмите Enter,
 чтобы проверить данные строки.  Данные остались нетронутыми и это
 именно  тот  узел,  на   который   указывает   переменная   Tail.
 Определенно происходит что-то странное с концом строки.

      По мере  пошагового  выполнения  цикла  с помощью клавиши F7
 следите за содержимым окна слежения.  "Виновником" является вызов

 = 235 =

 функции GetMem в строке 199. До этого вызова значение Tail^.Parm^
 равно first.  Сразу же  после  вызова  GetMem,  последний  символ
 строки пропадает.

      Что же  происходит?  Для  каждого параметра командной строки
 цикл for выделяет сначала запись,  затем строковые данные,  затем
 следующую запись и т.д.  Функция GetMem, вызываемая в строке 199,
 должна выделять достаточно места для размещения самой строки и ее
 байта  длины,  однако,  как  вы  можете видеть,  она не добавляет
 единицы к значению Length(s).  И  хотя  оператор  присваивания  в
 строке 200 правильно выполняет копирование строки,  он фактически
 берет на 1 байт больше чем  было  выделено  памяти.  Поэтому  при
 вызове   процедуры   New(Temp)  последний  символ  каждой  строки
 перекрывается  первым  байтом  следующей  записи,  размещенной  в
 памяти. Последний параметр остается нетронутым, потому что за ним
 не следует еще одна запись ParmRec.

      Вот и все ошибки в этой программе (известные).  Возможно,  с
 помощью  пошаговой отладки вам удастся обнаружить еще что-нибудь.
 Вы можете исправить ошибки (для удобства они  помечены  в  тексте
 двумя звездочками) и перекомпилировать программу,  либо запустить
 программу TPDEMO.PAS,  описанную в главе 3, в которой отсутствуют
 указанные ошибки.



 = 236 =

          ГЛАВА 15 Виртуальная отладка на машине с процессором 80386           
 -----------------------------------------------------------------

      Отладчик Turbo  Debugger  позволяет  использовать все мощные
 возможности компьютера  на  базе  процессора  80386.  Виртуальная
 отладка   позволяет   отлаживаемой   программе  использовать  все
 адресное пространство  в  пределах  640К,  как  если  бы  не  был
 загружен   отладчик.  (При  этом  Turbo  Debugger  загружается  в
 расширенную (extended) память, находящуюся за пределами 1МБ.)

      Отладка выполняется  точно  так  же,  как  и   при   обычном
 использовании отладчика Turbo Debugger,  за исключением того, что
 отлаживаемая программа загружается  и  выполняется  точно  в  той
 области памяти,  которая используется при запуске программы не из
 отладчика.  Это может  быть  особенно  полезно  как  для  отладки
 больших  программ,  так  и для поиска ошибок,  которые невозможно
 обнаружить,  если  программа  загружена  не  в  реальную  область
 памяти, как это происходит при обычной отладке.

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

 Пользователям 80286
 -------------------

      В случае  процессора 80286 объем доступной памяти может быть
 больше по  сравнению  с  Turbo  Debugger  за  счет  использования
 отладчика защищенного  режима  TD286.  Более подробную информацию
 см. в главе 16.
                                                                               
Аппаратные средства, необходимые для виртуальной отладки
 ---------------------------------------------------------

      Для того  чтобы использовать виртуальную отладку,  вы должны
 иметь компьютер на базе процессора 80386.  Кроме того,  вы должны
 иметь  700К  доступной  расширенной  памяти.  Если вы используете
 расширенную  память  под  RAM-диски,  кэш-память  и  т.д.,   вам,
 возможно,  потребуется  создать  специальный  файл CONFIG.SYS или
 AUTOEXEC.BAT,  который позволит удалять из  памяти  некоторые  из
 этих   программ,   когда  вы  захотите  использовать  виртуальную
 отладку.
                                                                               
Установка драйвера устройства для виртуального отладчика
 -------------------------------------------------------

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

 Чтобы  это  сделать,  надо  включить  в файл CONFIG.SYS следующую
 строку:

      DEVICE = TDH386.SYS

      Если вы поместили драйвер TDH386.SYS  не  в  корневую,  а  в
 какую-то другую директорию, включите маршрут этой директории в имя
 файла драйвера устройства.

      Обычно виртуальный отладчик позволяет иметь  до  256  байтов
 для  строк  окружения  DOS.  Если  этого недостаточно,  либо если
 столько не требуется,  и желательно сохранить  как  можно  больше
 памяти,  используйте в файле CONFIG.SYS параметр -e, чтобы задать
 количество байтов для окружения DOS. Например, строка

      DEVICE = TDH386.SYS -e2000

 будет резервировать 2000 байтов для переменных окружения DOS.
                         Запуск виртуального отладчика                         
 -----------------------------------------------------------------

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

      TD386 [параметры] программа [параметры программы]

      Другими словами,  вместо  TD  вам  надо просто ввести TD386.
 TD386 сам найдет исполняемую программу отладчика Turbo Debugger и
 загрузит ее в расширенную память.

      Если у  вас имеются другие программы или драйверы устройств,
 которые  используют  расширенную  память,  например,   RAM-диски,
 кэш-память  и  т.д.,  вы должны сообщить программе TD386,  сколько
 расширенной памяти она должна оставить  для  этих  программ.  Это
 делается  с  помощью  параметра -e командной строки.  После этого
 параметра указывается количество килобайтов  расширенной  памяти,
 используемое другими программами, например,

      TD386 -e512 myprog

      Эта команда   информирует   программу   TD386   о  том,  что
 необходимо зарезервировать первые  512К  расширенной  памяти  для
 других программ.

      Обычно, если  ваша  система  поддерживает стандарт XMS,  нет
 необходимости информировать  TD386  о  том,  сколько  расширенной
 памяти осталось  для  программ;  программы уже сообщили TD386 эту
 информацию. Вы должны использовать -e только с такими программами
 (как VDISK),  которые  не  поддерживают коммуникаций по стандарту

 = 238 =

 XMS.

      Поскольку, скорее всего,  вы будете всегда резервировать для
 других  программ  одинаковый объем расширенной памяти,  вы можете
 задать его один раз при запуске отладчика  и  затем  использовать
 постоянно.  Для этого вместе с параметром -e надо задать параметр
 -w,  который указывает,  что  значение,  заданное  параметром  -e
 должно   быть  запомнено  в  исполняемом  файле  TD386  и  должно
 использоваться постоянно.

      После этого у вас будет запрошено имя исполняемой программы.
 Если  вы используете DOS версии 3.х или более поздней,  в запросе
 будет  указан  полный  маршрут  и  имя  файла,  который  содержит
 программу TD386.  Вы можете принять это имя, нажав клавишу Enter,
 или ввести новое имя исполняемого  файла.  Файл  с  новым  именем
 должен уже существовать и быть копией программы TD386, которую вы
 предварительно сделали.

      Если вы работаете в DOS версии 2.х,  вы должны задать полный
 маршрут и имя файла исполняемой программы TD386.

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

      -?,-h     Обращается к подсказке по TD386.

      -b        Разрешает прерывать выполнение программ нажатием
                Ctrl-Break, даже когда прерывания запрещены.

      -e####    Задает количество килобайтов расширенной памяти,
                используемое другими программами или отлаживаемой
                программой. (Если ваша система поддерживает
                стандарт XMS, то данный параметр не нужен).

      -f####    Разрешает использовать эмуляцию расширенной памяти
                типа EMS посредством замещения страниц (в расширенной
                памяти) и устанавливает для сегмента страничного
                блока значение #### (в шестнадцатиричном формате).
                Последние три цифры этого значения должны быть
                нулями, например, C000 или E000. Заметим, что эта
                возможность может использоваться только для обращений
                отладчика к расширенной памяти типа EMS.
                Если вы   не   можете   загрузить   вашу   таблицу
                символических имен, попробуйте воспользоваться
                параметром -f, чтобы "занять" место из расширенной
                памяти.

                     Нет расширенной памяти:          -fD000
                     Расширенная память в D000:       -fE000
                     Расширенная память в E000:       -fD000


 = 239 =


      -f-       Запрещает эмуляцию расширенной памяти типа EMS
                (предположительно, используется для отмены
                предыдущего параметра -f командной строки).

      -w        Модифицирует файл TD386, записывая в него новое
                значение, заданное параметром -e или -f, которое
                должно использоваться по умолчанию. Вы можете ввести
                имя нового исполняемого файла, которого еще не
                существует. В этом случае TD386 создаст новый
                исполняемый файл.

      Обратите внимание,  что параметры программы TD386.EXE должны
 указываться в командной строке перед параметрами  отладчика Turbo
 Debugger и именем программы. Например, команда

      TD386 -e1024 -fD000 -w


      резервирует первые  1024К  расширенной   памяти,   разрешает
 эмуляцию  расширенной памяти типа EMS со страничным блоком D000 и
 записывает эти значения в файл TD386.EXE.

      Чтобы посмотреть список всех параметров командной строки для
 программы  TD386.EXE,  просто введите имя программы TD386 -?  или
 TD386 -h и нажмите клавишу Enter.

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

      Большинство функций    отладчика    выполняется   одинаково,
 независимо  от  того,  используется  ли  обычная   отладка,   или
 виртуальная   отладка   на   машине  с  процессором  80386.  Ниже
 перечислены все различия между обычной и виртуальной отладкой.

      - При использовании команды  File/OS  Shell  для  выполнения
 команды  DOS  отлаживаемая  программа никогда не "выгружается" на
 диск.  Это означает,  что не  всегда  может  хватить  памяти  для
 запуска других программ из DOS.

      - В   программе   могут  использоваться  почти  все  команды
 процессора 80386,  за исключением  некоторых  команд  защищенного
 режима: CLTS, LMSW, LTR, LGDT и LLDT.

      - Даже  если  вы  используете  при  виртуальной  отладке все
 режимы расширенной  адресации  процессора  80386  и  32-разрядные
 регистры, вы не можете получить доступ к памяти за пределами 1МБ.

 = 240 =

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

      - Нельзя использовать виртуальную отладку, если до этого уже
 была  запущена  программа   или   драйвер   устройства,   которые
 используют  защищенные или виртуальные режимы процессора 80386. К
 таким программам относятся следующие:

         - Рабочая среда DesqView;

         - Рабочая среда Windows 386;

         - Эмулятор EMS CEMM.SYS фирмы Compaq;

         - 386^MAX.

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

      - При виртуальной отладке TD386 может  перехватывать  особые
 ситуации, генерируемые   вашей   программой.  В  этом  случае  ее
 выполнение останавливается,  и TD386 сообщает об особой ситуации.
 Появляющееся сообщение  об ошибке конкретизирует суть этой особой
 ситуации, а стрелка в подокне Code окна CPU - или курсор  в  окне
 Module -  помечает  команду,  послужившую  причиной данной особой
 ситуации.

      - Неожиданных прерываний при этом возникать не  должно. Если
 они произойдут, обратитесь на фирму Borland.
                     Сообщения об ошибках программы TD386                      
 -----------------------------------------------------------------

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

      TD386 error: 80386 device driver missing or wrong version
      (Отсутствует драйвер  виртуального отладчика  или  неправильная
 версия)
      Прежде чем  вызывать программу  TD386 из  командной строки DOS,
 необходимо установить драйвер TDH386.SYS с помощью файла CONFIG.SYS.

      TD386 error: Can't enable the A20 address line
      (Не допускается строка адреса A20)
      Программа TD386  не может обращаться к памяти за пределами 1МБ.
 Это может  произойти, если  вы работаете на компьютере, не полностью
 совместимом с IBM PC.


 = 241 =

      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: Environment too long; use -e#### switch with
      TDH386.SYS
      (Строка окружения слишком длинная; используйте при установке
      драйвера TDH386.SYS параметр -e####)
      Необходимо изменить  длину строки окружения с помощью параметра
 -e, как было описано в разделе 14.2.

      TD386 error: Not enough Extended Memory available
      (Недостаточный объем доступной расширенной памяти)
      Программе TD386  не хватает  памяти. Необходимо  установить  на
 машину дополнительную  память, либо  освободить имеющуюся, уменьшив,
 например, размер RAM-диска.

      TD386 error: Wrong CPU type (not a 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
      (Файл программы испорчен или неправильной версии)
                                                                               
Сообщения об ошибках драйвера TDH386.SYS
 -----------------------------------------------------------------

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

      Wrong CPU type: TDH386 driver not installed
      (Неправильный тип процессора: драйвер TDH386 не установлен)

      Invalid command line: TDH386 driver not installed
      (Неверная командная строка: драйвер TDH386 не установлен)

 = 242 =

                                                                               
ГЛАВА 16 Отладка в защищенном режиме при помощи TD286
 --------------------------------------------

      Отладчик защищенного  режима  TD286  использует преимущество
 процессора 80286,  позволяющее   освобождать   для   отлаживаемой
 программы дополнительную  память.  TD286  помещает саму программу
 отладчика Turbo Debugger в расширенную память с адресом выше 1Мб,
 а в  памяти  с  адресом  ниже  640К оставляет только сравнительно
 небольшой загрузчик.  Это освобождает дополнительную  память  для
 отлаживаемой программы и ее таблицы символических имен.

      Turbo Debugger    используется   при   этом,   как   обычно.
 Единственное различие состоит  только  в  наличии  дополнительной
 памяти. Более подробную информацию см. в главе 15.
                                                                               
Аппаратное обеспечение отладчика защищенного режима
 ---------------------------------------------------

      Для того,  чтобы  воспользоваться   отладчиком   защищенного
 режима TD286,  ваш  компьютер  должен  иметь  процессор 80286 или
 80386. При этом должно быть не менее 640К доступной памяти.
                                                                               
Установка отладчика защищенного режима
 --------------------------------------

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

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

      TD286 [параметры] программа [параметры программы]

      TD286 имеет те же параметры командной строки,  что и обычный
 TurboDebugger, за  исключением  того,   что   он   не   позволяет
 использовать параметр   -y,  который  устанавливает  размер  пула
 оверлейных кодов.  Этот параметр не  нужен,  поскольку  TD286  не
 поддерживает оверлейных структур.
                                                                               
Различия между Turbo Debugger и TD286
 -------------------------------------

      Имеется несколько средств Turbo Debugger, которые недоступны
 при работе с TD286:


 = 243 =

      - При  использовании  команды  File|DOS Shell для выполнения
 команды DOS отлаживаемая программа не перекачивается на диск. Это
 означает, что   вам  может  не  хватить  памяти  для  запуска  по
 приглашению DOS других программ.

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

      TD286 известны аппаратные характеристики множества различных
 машин.  Если при запуске TD286INS вы получили сообщение  "Machine
 already  in file's database" ("Машина в файле базы данных"),  это
 означает,  что  данная  машина  уже  известна  TD286,  и  никаких
 модификаций не требуется.

      Если TD286INS   выполнит   свои   проверки,   то  аппаратные
 характеристики машины будут  записаны  в  TD286,  а  также  будет
 создан файл  с  расширением  .DB.  Этот файл следует отправить на
 Borland или передать в сеть Compuserve,  с тем, чтобы последующие
 версии TD286 автоматически распознавали аппаратные характеристики
 вашего компьютера.  TD286  может  хранить  характеристики  до  10
 машин, кроме тех, с которыми он поставлен первоначально.




 = 244 =

                                                                               
ГЛАВА 17 Отладка резидентных программ и драйверов устройств
 --------------------------------------------------

      Turbo Debugger    2.0   позволяет   отлаживать   резидентные
 программы и драйверы устройств,  так же как и обычные выполняемые
 файлы. Turbo Debugger сам тоже может быть запущен как резидентная
 программа, и вы параллельно сможете  выполнять  команды  DOS  или
 другие программы.

      Turbo Debugger  2.0  имеет  три  новые  команды меню файлов,
 специально предназначенные   для   использования   при    отладке
 резидентных программ   и   драйверов   устройств.   Это   команды
 File|Resident, File|Symbol Load и File|Table Relocate.

      В данной главе дается краткое  объяснение  того,  что  такое
 резидентная программа и драйвер устройства, а также информация об
 отладке их с помощью Turbo Debugger 2.0.
                     Что такое резидентная программа (TSR)                     
 -----------------------------------------------------------------

      TSR означает   "terminate   and   stay   resident"   ("после
 завершения остается   резидентной").   Резидентными    называются
 программы, которые после завершения работы остаются в оперативной
 памяти. Примерами  резидентных  программ  являются   SideKick   и
 SuperKey; они   все   время  находятся  в  оперативной  памяти  и
 активизируются при  нажатии  соответствующих   активных   клавиш.
 Другие резидентные программы активизируются из программ, выдающих
 соответствующие программные прерывания.  Turbo  С  имеет  функцию
 geninterrupt, генерирующую такие программные прерывания.

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

      После завершения  временной  части   резидентной   программы
 запускается функция   DOS,  которая  позволяет  части  .EXE-файла
 оставаться резидентной  в  оперативной  памяти  после   окончания
 программы -   отсюда  и  термин  "terminate  and  stay  resident"
 ("после завершения  остается   резидентной").   Временная   часть
 резидентной программы знает размер резидентной части,  а также ее
 адрес в памяти,  и передает эту информацию DOS.  Тогда DOS делает
 соответствующий участок памяти неприкосновенным,  тогда как любая
 другая, не защищенная таким образом область оперативной  памяти в

 = 245 =

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

      Сложность отладки резидентной программы состоит в  том,  что
 требуется отладить как временную, так и резидентную ее части. При
 выполнении .EXE-файла единственный  выполняемый  код  -  это  код
 временной части   резидентной   программы.  Поэтому  при  обычном
 запуске Turbo Debugger,  с заданием имени файла,  вы увидите лишь
 временную часть   заданной   программы,  а  именно  то,  как  она
 инсталлирует резидентную  часть  и  соответствующие   обработчики
 прерываний. Для  отладки  резидентной  части вы должны установить
 точку останова  отладчика  и  сделать   резидентным   сам   Turbo
 Debugger. Ниже это описано более подробно.

 Отладка резидентной программы  ----------------------------------

      Отладка временной   части  резидентной  программы  ничем  не
 отличается от отладки любого другого  файла.  Отличия  начинаются
 при отладке резидентной ее части.

      Ниже описан процесс отладки резидентной программы:

      1. Компилируйте  или ассемблируйте резидентную программу, не
 забыв включить  информацию  о  символических  именах  (отладочную
 информацию). Используйте  для  этого  параметры  командной строки
 TASM /ZI, TCC -v или TPC /V.

      2. При необходимости компоновки  резидентной  программы  для
 включения информации о символических именах используйте опцию /v.
 Для помещения символической информации  в  отдельный  файл  можно
 воспользоваться опцией TDSTRIP -s,  хотя этот файл не нужен, если
 отлаживается .EXE-файл.

      3. Теперь загрузим резидентную программу в Turbo  Debugger и
 запустим временную  ее  часть,  используя  для  этого  как обычно
 команду Run|Run.  Отладьте временную часть программы, как обычно.
 После того, как выполнение временной части завершено, резидентная
 часть инсталлируется  в  оперативной  памяти.   Сложность   далее
 заключается в отладки резидентной части.

      4. Установите точку останова в начале резидентной части кода
 при помощи F2.  При желании точки останова могут быть установлены
 и в других частях резидентной части программы.

      5. Для того,  чтобы сделать резидентным сам Turbo Debugger ,
 выберите команду  File|Resident.  Это  не   имеет   отношения   к
 резидентности отлаживаемой   программы;   последняя  делает  себя
 резидентной сама, при выполнении ее в Turbo Debugger, так же, как
 и при  запуске из командной строки.  Причина,  заставляющая иметь
 Turbo Debugger в качестве резидентной программы,  состоит в  том,
 что это позволяет вернуться в DOS и оттуда запустить отлаживаемую

 = 246 =

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

      6. Когда вы возвратились в командную строку  DOS,  выполните
 резидентную часть отлаживаемой программы,  нажав активную клавишу
 и выполнив любые другие действия для ее запуска.  Далее выполните
 эту программу, как обычно.

      7. Когда программа доходит до точки останова, Turbo Debugger
 перехватит управление,  а  отлаживаемая  программа   окажется   в
 соответствующем окне. Теперь вы можете начать отладку резидентной
 части кода.  (Можно повторить вход в Turbo Debugger  из  DOS  при
 помощи двойного нажатия Ctrl-Break).

      Второй метод  отладки  резидентной части программы состоит в
 том, чтобы запустить программу из командной строки DOS,  а  затем
 при помощи  Turbo  Debugger  отладить область оперативной памяти,
 где находится резидентная программа.

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

      Для того, чтобы воспользоваться данным методом,

      1. Выполните  шаги  1  и 2 первого метода для компиляции или
 ассемблирования вашего  кода,  также  для  того,  чтобы  вырезать
 оттуда таблицу  символических  имен  и  поместить ее в .TDS-файл.
 Если это  необходимо  для  вашей  прикладной   программы,   также
 запустите TDSTRIP  с  опцией -c,  чтобы преобразовать резидентную
 программу из .EXE-файла в .COM-файл.

      2. Запустите резидентную программу из командной  строки DOS,
 введя для этого ее имя. Например, если ваша резидентная программа
 называется TSR.EXE,  введите по приглашению  DOS  TSR  и  нажмите
 Enter.

      3. Запустите   TDMEM,  чтобы  получить  карту  распределения
 оперативной памяти  компьютера.  Отметьте  адрес  сегмента,  куда
 загружена резидентная  часть  вашей программы.  Мы будем называть
 этот сегмент Seg.

      4. Затем вам необходимо  определить  размер  памяти  таблицы
 символических имен,  которую  Turbo  Debugger должен распределять
 при его  запуске.  Для  этого  отметьте  размер   файла   таблицы
 символических имен   вашей   резидентной  программы  (.TDS-файл),
 выполнив для этого команду DOS DIR.
      Данный размер  представляет  собой  нижнюю  границу  размера
 памяти таблицы   символических   имен,   которая   должна    быть
 распределена при   загрузке  Turbo  Debugger,  поскольку,  помимо
 хранимой здесь информации,  Turbo Debugger при  загрузке  таблицы

 = 247 =

 символических имен  создает еще некоторое число таблиц, временных
 переменных и т.д.  Полезно распределять хотя бы  в  полтора  раза
 больше памяти,  чем  занимает  .TDS-файл  на  диске,  хотя иногда
 памяти требуется  больше,  а  иногда  достаточно  меньше.   Turbo
 Debugger сообщает    вам,   если   таблице   символических   имен
 распределено слишком мало памяти,  "Not  enough  memory  to  load
 symbol table",  поэтому  с  командой  File|Symbol  Load  (которая
 обсуждается н\иже) нужно поэкспериментировать.

      5. Загрузите  Turbo  Debugger,   не   задавая   имя   файла,
 распределив при    помощи    параметра   командной   строки   -sm
 соответствующее количество памяти для таблицы символических имен.
 Параметр -sm   задает  в  килобайтах  размер  распределяемой  для
 таблицы символических имен  памяти.  Например,  если  вы  желаете
 зарезервировать для  таблицы  символических  имен 3К,  введите TD
 -sm3 по приглашению DOS. При загрузке Turbo Debugger не задавайте
 имя файла, поскольку то, что вы собираетесь отлаживать, и так уже
 находится в оперативной памяти.  Исходные файлы и .TDS-файлы  для
 отлаживаемой резидентной программы должны находиться в директории
 по умолчанию, чтобы соответствующая символическая информация была
 доступна отладчику.

      6. Теперь  вы  можете  начать отладку резидентной программы,
 установив точки останова,  сделав Turbo  Debugger  резидентным  и
 выполняя некоторые действия на уровне команды DOS,  которые будут
 приводить к срабатыванию этих точек останова. Этим Turbo Debugger
 будет открыт   на  соответствующей  точке  кода.  Однако,  задача
 отладки может  быть  упрощена,  если  сначала  вызвать  в  память
 символическую информацию,  находящуюся  в  таблице  символических
 имен и в исходных файлах.

      7. При загрузке Turbo Debugger уберите загрузочное сообщение
 нажатием Esc,  загрузите  таблицу  символических имен резидентной
 программы командой File|Symbol Load,  задав  соответствующее  имя
 таблицы символических  имен.  При получении сообщения о том,  что
 для загрузки  таблицы  символических  имен  не  хватает   памяти,
 выйдите из  Turbo Debugger и перезапустите его по приглашению DOS
 с большим значением аргумента -sm.

      8. Таблица символических имен содержит  набор  символических
 имен, привязанных  к  относительным  адресам  памяти вашего кода.
 Символическим именам  в   этой   таблице   предшествуют   символы
 #имя_файла#, где  имя_файла  это  имя исходного файла резидентной
 программы. Например, если ваш исходный файл называется TSR.ASM, и
 содержит метку  Intr,  то  символическое имя #TSR#INTR обозначает
 адрес памяти.
      Символические имена  в  таблице  смещены  друг  от  друга на
 необходимое число   байтов,   но   абсолютный    адрес    первого
 символического имени не определен,  поскольку DOS может загрузить
 символическое имя в адрес,  отличный от адреса, используемого при
 ассемблировании. Поэтому   вы  должны  использовать  команду  для

 = 248 =

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

      9. Используйте команду  File|Table  Relocate  для  помещения
 первого символического  имени  из  таблицы  символических  имен в
 память. Таким образом, символическая информация в отладчике будет
 соответствовать вашему коду.  Для этого по запросу Turbo Debugger
 задайте адрес сегмента Seg вашей резидентной  программы,  который
 был определен в TDMEM.
      Дисассемблированные операторы из памяти  синхронизируются  с
 информацией из таблицы символических имен.  При наличии исходного
 файла исходные операторы из  этого  файла  печатаются  в  той  же
 строке, что и информация из таблицы символических имен.

      10. Для  перехода к сегменту оперативной памяти, содержащему
 резидентную программу,  используйте команду  Goto  (Ctrl-G).  Для
 этого задайте  адрес  сегмента  резидентной  программы,  а  затем
 смещение 0000H, либо перейдите к конкретной символической метке в
 коде.

      Далее все выполняется,  как и для первого метода,  начиная с
 шага 4.
                         Что такое драйвер устройства                          
 -----------------------------------------------------------------

      Драйверы устройств - это набор подпрограмм, используемых DOS
 для управления    функциями    ввода/вывода    низкого    уровня.
 Инсталлируемые драйверы  устройств  (по  сравнению  с встроенными
 драйверами DOS) устанавливаются путем вставки в  файл  CONFIG.SYS
 строк типа

      device = clock.sys

      Когда DOS  должен  выполнить  операцию  ввода/вывода  одного
 символа, она сканирует скомпонованный список заголовков устройств
 в поисках   устройства   с   соответствующим   логическим  именем
 (например, COM1).  В  случае  драйверов   устройств,   работающих
 поблочно, DOS следит за тем,  сколько таких устройств установлено
 в системе,  и назначает каждому из них букву,     A  для  первого
 драйвера блочного  устройства,  B  для  второго,  и  т.д.  Когда,
 например, вы обращаетесь к дисководу С,  например, DOS знает, что
 должен быть вызван драйвер третьего блочного устройства.

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

      Когда DOS  определяет,  что данный драйвер устройства должен
 быть вызван,  то вызов  выполняется  дважды.  При  первом  вызове
 драйвера DOS  обращается  к  подпрограмме стратегии и передает ей
 указатель на  буфер,  называемый  заголовком  запроса.  Заголовок

 = 249 =

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

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

      Проблема с отладкой драйверов устройств состоит в том, что в
 данном случае  выполняемый  .EXE-файл отсутствует,  поскольку для
 правильной работы  драйвер  должен  устанавливаться  при   помощи
 команды DEVICE = ДРАЙВЕР.РАСШИРЕНИЕ,  где .РАСШИРЕНИЕ - это .SYS,
 .COM или .BIN.  Это означает, что отлаживаемый драйвер устройства
 уже находится в оперативной памяти до запуска отладчика,  как это
 требуется для  правильной  работы   драйвера.   Поэтому   большое
 значение имеют    функции    загрузки    и   перемещения   таблиц
 символических имен,  поскольку  они   позволяют   восстанавливать
 символическую информацию  в  дисассемблированном сегменте памяти,
 куда загружается драйвер устройства. Как мы увидим далее, полезно
 использовать команду File | Resident.

 Отладка драйвера устройства   -----------------------------------

      Ниже показано,  как отлаживать драйверы устройств при помощи
 TDREMOTE:

      1. Компилируйте или  ассемблируйте  драйвер  устройства,  не
 забыв  включить  информацию  о  символических  именах (отладочную
 информацию).  Используйте для этого  параметры  командной  строки
 TASM /ZI, TCC -v или TPC /V.

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

      3. Введите TDSTRIP -s -c имя_файла,  где имя_файла - это имя
 отлаживаемого    драйвера,    чтобы   вырезать   оттуда   таблицу
 символических имен  и  поместить  ее   в   .TDS-файл,   а   также
 преобразовать существующий .EXE-файл в .COM-файл.

      TDSTRIP -s -c имя_файла

      где имя_файла  -  это имя отлаживаемого драйвера устройства.
 Скопируйте .COM-файл  на удаленную систему.

      4. Модифицируйте файл CONFIG.SYS удаленной  системы, добавив
 туда строку

 = 250 =


      device = имя_файла.COM

      5. Убедитесь,   что  в  имени_файла  правильно  указан  путь
 доступа к драйверу устройства.

      6. Перезагрузите удаленную систему для того,  чтобы  драйвер
 устройства был загружен.

      7. Запустите  TDDEV,  чтобы  узнать адрес в памяти удаленной
 системы, куда DOS  загрузила  ваш  драйвер  устройства.  Заметьте
 адрес, в который загружен драйвер.  Сегментную часть этого адреса
 мы будем обозначать как Seg.

      8. Затем вам необходимо  определить  размер  памяти  таблицы
 символических  имен,  которую  Turbo Debugger должен распределять
 при  его  запуске.  Для  этого  отметьте  размер  файла   таблицы
 символических   имен   вашего  драйвера  устройства  (.TDS-файл),
 выполнив для этого команду DOS DIR.
      Данный размер  представляет  собой  нижнюю  границу  размера
 памяти таблицы   символических   имен,   которая   должна    быть
 распределена при   загрузке  Turbo  Debugger,  поскольку,  помимо
 хранимой здесь информации,  Turbo Debugger при  загрузке  таблицы
 символических имен  создает еще некоторое число таблиц, временных
 переменных и т.д.  Полезно распределять хотя бы  в  полтора  раза
 больше памяти,  чем  занимает  .TDS-файл  на  диске,  хотя иногда
 памяти требуется  больше,  а  иногда  достаточно  меньше.   Turbo
 Debugger сообщает    вам,   если   таблице   символических   имен
 распределено слишком мало памяти,  "Not  enough  memory  to  load
 symbol table",  поэтому  с  командой  File|Symbol  Load  (которая
 обсуждается ниже) нужно поэкспериментировать.

      9. Загрузите на удаленной системе TDREMOTE.

      10. Загрузите Turbo  Debugger,   не   задавая   имя   файла,
 распределив при    помощи    параметра   командной   строки   -sm
 соответствующее количество памяти для таблицы символических имен.
 Параметр -sm   задает  в  килобайтах  размер  распределяемой  для
 таблицы символических имен  памяти.  Например,  если  вы  желаете
 зарезервировать для  таблицы  символических  имен 3К,  введите TD
 -sm3 по приглашению DOS. При загрузке Turbo Debugger не задавайте
 имя файла, поскольку то, что вы собираетесь отлаживать, и так уже
 находится в оперативной памяти.  Исходные файлы и .TDS-файлы  для
 отлаживаемого драйвера устройства  должны находиться в директории
 по умолчанию, чтобы соответствующая символическая информация была
 доступна отладчику.

      11. Теперь  вы  можете  начать  отладку драйвера устройства,
 установив точки останова,  сделав Turbo  Debugger  резидентным  и
 выполняя некоторые действия на уровне команды DOS,  которые будут
 приводить к срабатыванию этих точек останова. Этим Turbo Debugger

 = 251 =

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

      12.При загрузке Turbo Debugger уберите загрузочное сообщение
 нажатием Esc,   загрузите  таблицу  символических  имен  драйвера
 устройства командой File|Symbol Load, задав  соответствующее  имя
 таблицы символических  имен.  При получении сообщения о том,  что
 для загрузки  таблицы  символических  имен  не  хватает   памяти,
 выйдите из  Turbo Debugger и перезапустите его по приглашению DOS
 с большим значением аргумента -sm.

      13.Таблица символических имен содержит  набор  символических
 имен,  привязанных  к  относительным  адресам памяти вашего кода.
 Символическим  именам  в  этой   таблице   предшествуют   символы
 #имя_файла#,  где  имя_файла  это  имя  исходного  файла драйвера
 устройства Например, если ваш исходный файл называется TSR.ASM, и
 содержит  метку  Intr,  то символическое имя #TSR#INTR обозначает
 адрес памяти.
      Символические имена  в  таблице  смещены  друг  от  друга на
 необходимое число   байтов,   но   абсолютный    адрес    первого
 символического имени не определен,  поскольку DOS может загрузить
 символическое имя в адрес,  отличный от адреса, используемого при
 ассемблировании. Поэтому   вы  должны  использовать  команду  для
 явного определения адреса первого символического имени в памяти.

      14. Используйте команду  File|Table Relocate  для  помещения
 первого  символического  имени  из  таблицы  символических имен в
 память. Таким образом, символическая информация в отладчике будет
 соответствовать вашему коду.  Для этого по запросу Turbo Debugger
 задайте адрес сегмента Seg вашего  драйвера  устройства,  который
 был определен в TDMEM.
      Дисассемблированные операторы из памяти  синхронизируются  с
 информацией из таблицы символических имен.  При наличии исходного
 файла исходные операторы из  этого  файла  печатаются  в  той  же
 строке, что и информация из таблицы символических имен.

      15. Установите в вашем коде необходимые точки останова.

      16. Для того, чтобы сделать резидентным сам Turbo Debugger ,
 выберите  команду  File|Resident.  Это  не  имеет   отношения   к
 резидентности   отлаживаемого  драйвера;  последний  делает  себя
 резидентной  сам,  при  загрузке  удаленной  системы,  вследствие
 команды  device  в  файле CONFIG.SYS удаленной системы.  Причина,
 заставляющая  иметь  Turbo  Debugger   в   качестве   резидентной
 программы,  состоит  в  том,  что это позволяет вернуться в DOS и
 оттуда выполнить действия по запуску драйвера устройства.

      17. Когда вы вернетесь к  командной  строке  DOS  удаленной
 системы, сделайте   все   необходимое  для  активизации  драйвера

 = 252 =

 устройства. Например,  пошлите информацию на  управляемое  данным
 драйвером устройство.

      18. Когда   программа   доходит  до  точки  останова,  Turbo
 Debugger перехватит управление, а отлаживаемый драйвер окажется в
 соответствующем  окне.  Теперь вы можете начать отладку его кода.
 (Можно повторить вход в Turbo Debugger из DOS при помощи двойного
 нажатия Ctrl-Break).

                                                                               
Конец сеанса отладки
 -----------------------------------------------------------------

      Для того,  чтобы  завершить сеанс отладки,  выйдите из Turbo
 Debugger обычным образом, выбрав команду File|Quit или нажав Alt-
 X. При  отладке  резидентной  программы  она  будет автоматически
 выгружена.



