Перед тем, как мы окончим обсуждение процессора 8087, хотелось бы немного поговорить об отладке написанных для него программ. Проблема, с которой мы сталкиваемся здесь, заключается в том, что утилита DEBUG (отладчик) в DOS не поддерживает процессор 8087. Это означает, что при обнаружении отладчиком контрольной точки он не отображает на экране содержимого регистров сопроцессора 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, можно удалить отладочный фрагмент из программы. В этот же момент вы можете изменить программу так, чтобы принимать параметры через регистры стека, а не через память.