Assembler для начинающих






      Перед тем, как мы окончим обсуждение процессора 8087, хотелось
    бы немного поговорить об отладке написанных для него программ.
    Проблема, с которой мы сталкиваемся здесь, заключается в том, что
    утилита DEBUG (отладчик) в DOS не поддерживает процессор 8087.
    Это означает, что при обнаружении отладчиком контрольной точки он
    не отображает на экране содержимого регистров сопроцессора 8087.
    Это сильно затрудняет отладку программы, изменяющей регистры
    сопроцессора 8087.
 
      В книге предлагается метод, который можно применять для отладки
    программ сопроцессора 8087, используя отладчик DOS.  Этот метод
    может быть и не наилучший, но он использовался при отладке программ
    приведенных в этой главе.
 
      Основное препятствие заключается в неспособности программы
    DEBUG показывать содержимое регистрового стека сопроцессора 8087.
    Без переписывания заново программы DEBUG этот метод дает
    существенную иинформацию, необходимую при отладке программы
    сопроцессора 8087.  Этот метод отладки требует, чтобы программа
    была написана, как отдельно выполняемая, либо как файл типа .EXE,
    либа типа .COM.  Даже если вы пишете подпрограмму, отладьте ее
    сначала, как головную программу.  Одной из первых команд программы
    должна быть команда FINIT, сбрасывающая процессор 8087 в состояние,
    в которое он попадает при включении питания.  Это надо сделать,
    чтобы можно было прогонять программу снова и снова, всегда начиная
    сначала.  Рассматриваемый здесь метод отладки не позволит вам
    остановиться, проанализироваь регистры сопроцессора 8087, а затем
    продолжить программу с этого же места.  Этот метод основывается на
    возможности начинать все сначала после каждой контрольной точки.
 
      Вы должны организовать все параметры подпрограммы в виде ячеек
    памяти, и программа должна загружать все эти числа в
    соответствующие регистры вслед за командой FINIT.  Это необходимо,
    даже если идет работа с программой, принимающей параметры,
    переданные через стековые регистры.  Сначала отлаживаемая программа
    работает с параметрами, лежащими в памяти.  После того, как
    арифметика и логика программы будет отлажена, можно будет изменить
    программу так, чтобы она принимала параметры из регистрового стека.
      Цель всех этих действий - позволить программе выполняться без
    внешнего вмешательства.  Это означает, что можно запустить
    программу сначала и выполнять ее до некоторой команды, и перезапуск
    программы приведет к точно такому же ее выполнению.  Такое свойство
    необходимо, так как предлагаемый метод индикации регистров
    разрушает содержимое стека процессора 8087, и когда это произошло,
    продолжать выполнение программы с этого же места уже нельзя.
    Программу надо перезапустить с самого начала и остановить ее уже в
    другом месте, а это возможно благодаря принятым мерам.  Последние
    два примера, квадратное уравнение и функция синуса, устроены именно
    таким образом:  их параметры находятся в памяти, и программы
    начинаются с команды FINIT.
 
      Следующий этап процедуры отладки требует размещения
    специального программного фрагмента в заранее фиксированном месте
    вашей программы.  Для отладки примеров был выбран адрес 200, так
    как ни один из этих примеров не занимает более 500 байт.  Этот
    программный фрагмент предназначен только для отладки, и вы удалите
    его перед получением окончательной версии программы.  Такой
    фрагмент показан на Фиг. 7.29.  Как вы видите, он очень короток и
    содержит только три команды и два поля данных.  Первое поле данных
    содержит константу, в данном случае 106, или 1000000.  Выбор этого
    значения остается за вами; другое значение может оказаться
    подходящим, если ваша программа работает с числами, меньшими 10-6,
    или большими 1012.
 
      Смысл этого программного фрагмента заключается в том, что он
    преобразует содержимое вершины стека в число, которое вы сможете
    увидеть.  Этот фрагмент умножает содержимое текущей вершины стека
    на число с массой нулей, а это эквивалентно сдвигу десятичной точки
    вправо.  В данном случае, если вершина стека содержит 1/2,
    умножение преобразует ее в 500000.
 
      После того, как число преобразовано в большое целое (вместо
    дробного), команда FBSTP записывает его в упакованной десятичной
    форме в поле, также находящееся в этом специальном программном
    фрагменте.    Затем команда INT 3 возвращает управление программе
    DEBUG.  Теперь можно использовать команду Display программы DEBUG,
    чтобы посмотреть на 10 байт, записанных командой FBSTP.  Конечно,
    читать показанное значение нужно наоборот, так как это - способ,
    которым сопроцессор 8087 записывает десятичные числа.  Также надо
    учесть модификацию десятичнлй точки, которую выполнило умножение.
 
      ------------------------------
      TEN6  DD    1000000
            ORG   200H
      BCD_TEMP    DT    ?
            ORG   210H
            FIMUL TEN6
            FBSTR BCD_TEMP
            INT   3
      --------------------------- Фиг. 7.29 Отладка процедуры
                              для числового сопроцессора
      Отладка программы для сопроцессора 8087 осуществляется
    следующим образом.  Как только вы решили, что программа работает
    неверно, вы находите место контрольной точки по листингу программы.
    Использование команды Unassemble многого не даст, так как все
    команды сопроцессора 8087 дезассемблируются как команды ESC.  Так
    что использование литсинга программы существенно.
 
      Теперь вы выполняете программу с начала до контрольной точки;
    именно для этого вы сконструировали программу так, чтобы ее можно
    было перезапустить с начала баз какой=либо подготовки.  Всякий раз,
    когда вы вновь устанавливаете контрольную точку, нужно выполнять
    программу с начала.
 
      Когда программа попадает на контрольную точку, управление
    передается в отладчик.  Теперь вы можете выполнить тот специальный
    фрагмент кода, который помещен в программу.  Команда INT 3 в конце
    этого фрагмента возвращает управление в программу DEBUG, так что вы
    можете увидеть, что за число находилось в вершине стека, когда
    выполнялась исходная контрольная точка.  Так как была использована
    команда FBSTP, она извлекла число из вершины стека, записав аго в
    память.  Поэтому, чтобы увидеть второе число стека, ST1, вы можете
    еще раз выполнить отладочный фрагмент; все это можно повторять
    столько раз, сколько вы хотите.  Когда по этому методу будет
    получено десятичное число, содержащее значение 0FFH как в старшем,
    так и в знаковом байтах, знайте, что из стека извлеклось пустое
    значение.  Далее в программе можно установить новую контрольную
    точку, и снова выполнить программу сначала.  Таким образом вы
    можете пройти путь по всей программе, пока не найдется место
    ошибки.  Как только ошибка найдена, можно либо исправить ее на
    месте ("залатать" ошибку), или выйти назад в DOS, чтобы
    отредактировать и заново ассемблировать программу.      Когда, наконец,
    программа выполняется верно, и вам больше уже не нужна программа
    DEBUG, можно удалить отладочный фрагмент из программы.  В этот же
    момент вы можете изменить программу так, чтобы принимать параметры
    через регистры стека, а не через память.