[TulaAnti&ViralClub] PRESENTS ...
MooN_BuG, Issue 8, Nov 1998                                           file 00A

                 Встроенные средства отладки процессора 80386
                                                              by Тед Мирецки

        Важнейшей особенностью процессора 80386 является наличие  восьми
   отладочных  регистров,  обозначаемых  DR0-DR7. Два из этих регистров,
   DR4 и DR5, зарезервированы для внутренних нужд микропроцессора и  яв-
   ляются  недоступными для программ. К остальным доступ может осуществ-
   ляться с помощью команд пересылки следующего вида:

           MOV     DRx, zzz
           MOV     zzz, DRx

        где х может принимать значения 0, 1, 2, 3, 6 или 7, а zzz  явля-
   ется одним из 32-разрядных регистров EAX, EBX, ECX, EDX, EDI или ESI.
   Эти  команды выполнимы как в REAL-, так и в защищенном режиме, причем
   в последнем случае они должны выполняться только на высшем  (нулевом)
   уровне приоритета.
        Каждый  из четырех регистров DR0-DR3 может содержать адрес точки
   останова. Этот адрес должен быть представлен в 32-разрядной  линейной
   форме, возникающей уже после осуществления сегментных адресных преоб-
   разований,  но до использующего страничный механизм перехода с вирту-
   ального адреса на физический. Если страничный механизм не использует-
   ся, то линейный адрес совпадает с физическим; в REAL-режиме он вычис-
   ляется путем сдвига адреса сегмента на четыре бита влево с  последую-
   щим добавлением величины смещения.
        Отладочный  управляющий регистр DR7 (см. рис.1 ) служит для опи-
   сания характера точек останова, а также  для  выборочного  разрешения
   и/или  запрещения этих остановов. Hа каждый из четырех отладочных ад-
   ресных регистров DR7 содержит по два бита разрешения:  локальный  бит
   разрешения и глобальный бит разрешения. Если какой-либо из этих битов
   установлен,  то  соответствующий адрес останова считается активным, и
   обращение к участку памяти по этому адресу будет инициировать  преры-
   вание  INT 1. Биты чтения/записи указывают способ обращения к памяти,
   вызывающий прерывание: выполнение машинной инструкции, только  запись
   данных,  запись или чтение данных. Для обращения, связанного с данны-
   ми, используются биты длины, указывающие длины областей памяти, начи-
   нающиеся с адреса останова (максимум 4 байта), при обращении к  кото-
   рым  происходит останов. Для остановов, связанных с выполнением инст-
   рукций, биты длины должны содержать 0; если инструкция имеет  префик-
   сы, то специфицированный адрес должен быть адресом первого префикса.


         Рис.1. Управляющий регистр и регистр состояния


      Отладочный управляющий регистр (DR7)
     ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
     │LEN│R/W│LEN│R/W│LEN│R/W│LEN│R/W│ 0 │G│  0  │G│L│G│L│G│L│G│L│G│L│
     │ 3 │ 3 │ 2 │ 2 │ 1 │ 1 │ 0 │ 0 │   │D│     │E│E│3│3│2│2│1│1│0│0│
     └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
     31              23              15              7               0

     LENn - длина останова n: 00 = 1 байт
                              01 = 2 байта
                              10 = неопределена
                              11 = 4 байта
     R/Wn - тип останова:     00 = выполнение инструкции
                              01 = запись данных
                              10 = неопределен
                              11 = чтение и/или запись данных
     GD - генерировать INT 1 при обращении к отладочным регистрам
     GE - глобальный бит "точного соответствия"
     LE - локальный бит "точного соответствия"
     Gn - глобальный бит разрешения останова с номером n
     Ln - локальный бит разрешения останова с номером n


      Отладочный регистр состояния (DR6)
     ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
     │               0               │В│В│В│        0        │В│В│В│В│
     │                               │T│S│D│                 │3│2│1│0│
     └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
     31              23              15              7               0

     BT - переключение контекстов (установлен бит Т в сегменте
          состояния задачи)
     BS - пошаговое выполнение (установлен бит Т в регистре флагов)
     BD - обращение к отладочным регистрам (установлен GD в DR7)
     Bn - точка останова с номером n


        Двухуровневая  система разрешения/запрещения остановов предпола-
   гает, что отладка происходит в многозадачной среде с виртуальной  па-
   мятью.  В момент переключения контекста с одной задачи на другую про-
   цессор автоматически очищает четыре локальных бита разрешения  преры-
   вания;  при этом нежелательные для новой задачи неглобальные отладоч-
   ные прерывания происходить не будут. В случае, когда некоторый  оста-
   нов  остается активным, могут возникать нежелательные отладочные пре-
   рывания, поскольку линейный адрес, содержащийся в отладочном  регист-
   ре,  не  является по отношению к задаче уникальным. При использовании
   страничного механизма различные задачи могут обращаться  к  различным
   физическим  адресам  памяти,  используя  один и тот же линейный адрес
   (для этого достаточно изменить информацию  в  таблицах  постраничного
   соответствия).  Глобальные биты разрешения останова обычно устанавли-
   ваются в случае отладки общедоступных  программ,  например  драйверов
   устройств.
        Заметим, однако, что переключение контекстов автоматически обну-
   ляет  локальные  биты  разрешения  останова регистра DR7, при этом не
   сохраняя их содержимого; эти биты остаются очищенными и в тот момент,
   когда управление получает задача-отладчик. Для устранения этого  неу-
   добства  программа  отладчика должна устанавливать бит отладочной ло-
   вушки в своем сегменте переключения контекстов (TSS), что вызовет вы-
   полнение прерывания INT 1 всякий раз, когда эта программа  будет  во-
   зобновлять  работу.  Когда обработчик прерывания определит, что INT 1
   вызвано преключением контекстов, он может установить по своему усмот-
   рению локальные биты разрешения, после чего передать управление в  ту
   точку, где отладчик был в последний раз приостановлен.
        Hазначение  битов  GE  и  LE регистра DR7 состоит в установлении
   точного соответствия между моментом выполнения инструкции,  вызвавшей
   прерывание,  и  моментом  возникновения  прерывания.  Дело в том, что
   обычно 386-й процессор осуществляет физическую запись данных в память
   уже после того, как была выполнена инициировавшая эту запись машинная
   инструкция, причем эта задержка может оказаться довольно  большой.  В
   связи с этим прерывание, вызванное записью данных по одному из актив-
   ных  адресов останова, может произойти в тот момент, когда регистр IP
   указывает совсем не на ту инструкцию,  которая  осуществляла  запись.
   Однако, если по крайней мере один из битов GE или LE установлен, про-
   цессор  приостановит  свою работу с тем, чтобы дождаться фактического
   завершения операции записи. Руководство  программиста  по  процессору
   Intel  386  рекомендует устанавливать какой-либо из этих битов в слу-
   чае, если используется останов по обращению к  данным.  Отметим,  что
   переключение контекстов обнуляет бит LE, но не влияет на бит GE.
        Установка  битов  "точного  соответствия"  несколько увеличивает
   время выполнения отлаживаемой программы по сравнению с реальным  вре-
   менем, однако возникающее замедление несравнимо с замедлением, проис-
   ходящим из-за пошагового выполнения или вызова отладочных подпрограмм
   сравнения для отслеживания записи в память. Это замедление составляет
   всего 25 процентов, в то время как пошаговое выполнение ухудшает вре-
   мя в несколько раз.
        Последний используемый регистром управления флаг - бит GD - слу-
   жит для защиты отладочных регистров от какого бы то ни было доступа в
   любом режиме работы процессора и на любых уровнях приоритетов. В слу-
   чае,  если этот бит установлен, любая попытка чтения или записи в лю-
   бой из отладочных регистров вызовет прерывание INT 1. Отладчик  может
   устанавливать бит GD с тем, чтобы зарезервировать отладочные регистры
   для  своих  целей и защитить их от воздействия прочих программ. INT 1
   очищает бит GD, поэтому обработчик прерывания, находящийся в отладчи-
   ке, всегда будет иметь доступ к отладочным регистрам.
        Бит GD описан в дополнительных руководствах фирмы Intel  по  386
   процессору;  в  общедоступном Руководстве программиста описания этого
   бита нет. Версии микросхемы 80386, ориентированные на частоты 16  МГц
   и  20  МГц,  поддерживают  работу с битом GD, однако использовать эту
   особенность, как и любое другое недокументированное средство, следует
   с осторожностью, т.к. в последующих версиях микропроцессора она может
   не поддерживаться.
        Все аппаратно реализуемые  отладочные  средства  микропроцессора
   386  используют  для  входа в среду отладчика прерывание INT 1. Кроме
   того, это прерывание, как и в предшествующих  микропроцессорах  фирмы
   Intel,  может  вызываться  выполнением  инструкций в пошаговом режиме
   (для этого должен быть установлен бит пошагового выполнения в регист-
   ре флагов). Таким образом, имеем семь возможных причин  возникновения
   прерывания  INT  1:  останов по одному из четырех адресов в регистрах
   DR0-DR3; переключение контекстов при  установленном  бите  отладочной
   ловушки в TSS; попытка доступа к отладочным регистрам при установлен-
   ном  бите GD в DR7; останов, связанный с пошаговым выполнением (уста-
   новлен бит останова в регистре флагов).
        Для того, чтобы обработчик прерывания мог определить,  по  какой
   из  этих  семи  причин произошло прерывание, аппаратура устанавливает
   соответствующие биты в отладочном регистре состояния DR6. Эти биты не
   очищаются процессором автоматически,  поэтому  обработчик  прерывания
   должен обнулить их перед завершением своей работы, для того, чтобы не
   возникало недоразумений при последующих прерываниях.
        В  момент достижения точки останова по выполнению машинной инст-
   рукции процессор инициирует соответствующее прерывание непосредствен-
   но перед выполнением инструкции по адресу останова. В момент входа  в
   обработчик прерывания адрес возврата из прерывания, записанный в сте-
   ке, указывает на инструкцию по адресу останова. Когда обработчик воз-
   вратит  управление,  процессор снова попытается выполнить ту же самую
   инструкцию; если к этому моменту останов все еще активен, то произой-
   дет повторное прерывание. Обработчик прерывания INT 1 может запретить
   останов, однако это может сказаться  на  работе  отладчика,  которому
   последовательно  возникающие в одной точке остановы могут требоваться
   для отслеживания последовательных циклов в  отлаживаемых  программах.
   Аппаратура процессора 386 предлагает следующий реальный выход из это-
   го тупика.
        В  защищенном  режиме  при возникновении прерывания в стек перед
   адресом возврата помещается 32-разрядный  регистр  флагов.  В  случае
   возникновения INT 1 процессор устанавливает бит, соответствующий фла-
   гу  возобновления,  в образе регистра флагов, находящегося в стеке. В
   момент выхода из прерывания с помощью инструкции IRET для защищенного
   режима флаги восстанавливаются из стека, таким образом флаг возобнов-
   ления окажется установленным. Hазначение этого флага состоит в запре-
   щении прерываний до момента выполнения следующей инструкции;  процес-
   сор автоматически обнуляет флаг возобновления в тот момент, когда лю-
   бая  из инструкций, за исключением инструкций установки флагов (SETF,
   POPF или переходов и вызовов, связанных с переключением  контекстов),
   будет выполнена.
        В  REAL-режиме  при  возникновении  прерывания в стек помещается
   только 16-битовый регистр флагов; исходя из этого в REAL-режиме инст-
   рукция IRET не может воздействовать на флаг возобновления, находящий-
   ся в 16-м бите 32-разрядного регистра EFLAGS. Однако, обработчик пре-
   рывания INT 1 может установить этот флаг путем изменения  содержимого
   стека  таким  образом, чтобы он содержал полные 32-разрядные варианты
   регистра флагов и адреса возврата, после чего можно осуществить выход
   из прерывания инструкцией IRETD вместо IRET.
        В случае, когда останов возникает вследствие доступа  к  данным,
   прерывание  происходит  после  выполнения  инструкции, осуществляющей
   этот доступ. Если установлены биты GE или LE, в стек прерывания будет
   помещен адрес инструкции, непосредственно следующей вслед за инструк-
   цией, вызвавшей прерывание. Следует иметь в виду, что в  момент  воз-
   никновения останова по записи ячейка памяти, вызвавшая останов, будет
   содержать обновленное значение; если желательно сохранить старое зна-
   чение  этой  ячейки, то отладчик должен это сделать (тем же способом,
   которым DEBUG сохраняет содержимое ячейки,  когда  записывает  на  ее
   место  инструкцию INT 3) еще до момента передачи управления в отлажи-
   ваемую программу.