Перейти на главную   
  helloworld.ru - документация и книги по программированию  
helloworld.ru - документация и книги по программированию
    главная     хостинг    
Поиск по сайту:  
Смотрите также
Языки программирования
C#
MS Visual C++
Borland C++
C++ Builder
Visual Basic
Quick Basic
Turbo Pascal
Delphi
JavaScript
Java
PHP
Perl
Assembler
AutoLisp
Fortran
Python
1C

Интернет-технологии
HTML
VRML
HTTP
CGI
FTP
Proxy
DNS
протоколы TCP/IP
Apache

Web-дизайн
HTML
Дизайн
VRML
PhotoShop
Cookie
CGI
SSI
CSS
ASP
PHP
Perl

Программирование игр
DirectDraw
DirectSound
Direct3D
OpenGL
3D-графика
Графика под DOS

Алгоритмы
Численные методы
Обработка данных

Сис. программирование
Драйверы

Базы данных
MySQL
SQL

Другое

Хостинг


Друзья
demaker.ru
Реклама

Лучший хостинг. Аренда серверов




helloworld.ru

Глава 15. Использование сопроцессора 80x87

             В Borland Pascal вы можете работать с двумя типами  чисел  -
        целыми (короткими целыми - Shortint,  целыми - Integer,  длинными
        целыми - Longint,  целыми длиной в байт - Byte,  целыми длиной  в
        слово - Word) и вещественными (вещественными - Real, вещественны-
        ми одинарной точности - Single,  вещественными двойной точности -
        Double, повышенной точности - Extended, сложными - Comp). Вещест-
        венные числа называют также числами с плавающей точкой (плавающей
        запятой). Для облегчения работы с целыми числами создан процессор
        8086,  но для работы с вещественными числами на  этом  процессоре
        затрачивается гораздо больше времени и усилий. Для семейства про-
        цессоров 8086 предназначено соответствующее  семейство  вспомога-
        тельных  специализированных процессоров для математических вычис-
        лений (сопроцессоров) 80x87.

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

             Borland Pascal построен таким образом,  что он  обеспечивает
        оптимальное  выполнение операций с плавающей точкой независимо от
        наличия сопроцессора 80x87.

             * Для программ,  работающих на компьютере РС,  независимо от
               того,  оснащен  он сопроцессором 80x87 или нет,  в Borland
               Pascal предусмотрено использование  вещественных  чисел  и
               соответствующая библиотека программ, которые предназначены
               для выполнения операций с плавающей точкой.  Числа вещест-
               венного типа занимают 6 байт памяти.  При этом обеспечива-
               ется представление чисел  в  диапазоне  от  2.9х10^-39  до
               1.7х10^38 с 11-12 значащими цифрами. Программы в библиоте-
               ке программ для работы с плавающей  точкой  оптимизированы
               по  скорости  и  по  размеру  и  используют самые новейшие
               средства процессора 80x87.

             * Если вы пишете программы,  использующиеся только на компь-
               ютерах,  оснащенных сопроцессором 80x87, то вы можете ука-
               зать Borland Pascal на необходимость получения выполняемо-
               го  кода,  в  котором используется плата процессора 80x87.
               Это даст вам возможность  использования  четырех  дополни-
               тельных типов вещественных чисел (одинарной и двойной точ-
               ности,  повышенной точности,  сложного типа) и расширенный
               диапазон  представления  чисел  с  плавающей  точкой  - от
               1.9х10^-4951 до 1,1х10^4943 с 19-20 значащими цифрами.

             С помощью  директивы  компилятора  $N  или  параметра   меню
        Options¦Cоmpiler  (Параметры¦Компилятор) 80x87/80287 можно перек-
        лючаться между различными моделями  генерации  кода  с  плавающей
        точкой. По умолчанию используется состояние {$N-}. В этом состоя-
        нии компилятор использует 6-байтовую библиотеку с плавающей  точ-
        кой, что позволяет вам работать только с переменными типа Real. В
        состоянии {$N+} компилятор генерирует код для сопроцессора 80x87,
        что  дает вам дополнительную точность и доступ к 4 дополнительным
        вещественным типам.

             В Windows при компиляции с режимом  числовой  обработки,  то
        есть  с  директивой {$N+},  убедитесь,  что в вашей системе можно
        найти библиотеку эмуляции Windows 8087 - WIN87EM.DLL. Эта библио-
        тека   обеспечивает  необходимый  интерфейс  между  сопроцессором
        80х87,  Windows и вашей прикладной программой.  Если  сопроцессор
        80х87 в вашей системе отсутствует,  то библиотека WIN87EM.DLL бу-
        дет эмулировать его программно.  Эмуляция  существенно  замедляет
        работу по сравнению с реальным сопроцессором 80х87,  но обеспечи-
        вает выполнение вашей прикладной программы на любой машине.

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

             Для разрешения и запрещения эмуляции сопроцессора  8087  ис-
        пользуются директива компилятора $E и параметр Emulation  (Эмуля-
        ция)  меню Options¦Compiler (Параметры¦Компилятор).  По умолчанию
        используется состояние {$E+}.  В этом состоянии в программу авто-
        матически включается полная эмуляция сопроцессора 8087. В состоя-
        нии {$E-} используется существенно  меньшая  часть  библиотеки  с
        плавающей точкой, а полученный в результате файл .EXE будет рабо-
        тать только на машинах с сопроцессором 8087.

             В приложении  Windows директива компилятора $E не действует.
        Не действует она также в модуле.  Более того, если программа ком-
        пилировалась с директивой {$N-},  а все модули программы компили-
        ровались с директивой {$N+},  то библиотека  исполняющей  системы
        для  сопроцессора  8087 не требуется,  и директива компилятора $E
        игнорируется.

             Прикладной программе Windows не требуется библиотека  испол-
        няющей системы 80x87. Вместо этого ей нужно поддерживающая библи-
        отека WIN87EM.DLL,  поставляемая с Windows,  которая обеспечивает
        необходимый интерфейс между вашей прикладной программой,  Windows
        и сопроцессором.  Таким образом, в Windows даже при наличии в ва-
        шей системе сопроцессора 80х87 для выполнения программ, скомпили-
        рованных в состоянии {$N+}, должна присутствовать библиотека эму-
        ляции WIN87EM.DLL  (данная  библиотека - это часть Windows,  а не
        Borland Pascal).  При отсутствии сопроцессора  WIN87EM.DLL  будет
        эмулировать его операции программным путем,  что замедляет выпол-
        нение программы и не гарантирует,  что  использующая  сопроцессор
        80x87 программа сможет работать на любой машине.

             Когда вы запускаете прикладную программу Windows,  cкомпили-
        рованную в состоянии {$N+}, убедитесь, что она может найти в сис-
        теме файл WIN87EM.DLL.

             Когда вы выполняете компиляцию в режиме кода 80х87 (директи-
        ва {$N+}),  то возвращаемые подпрограммы модуля Systем (Sqrt, Рi,
        Sin и т.д.) значения представляют собой не вещественные числа,  а
        числа типа Extended (с повышенной точностью).

               {$N+}

               begin
                 Writeln(Pi);                 { 3.14159265358979E+0000 }
               end.

               {$N-}

               begin
                 Writeln(Pi);                 { 3.1415926536E+00 }
               end.

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

Типы данных процессора 80x87

В дополнение к вещественному типу для программ, использующих средства процессора 80x87, предусматривается четыре новых вещест- венного типа: 1. Тип с одинарной точностью Single, представляющий собой наименьший формат, который вы можете использовать для чисел с плавающей точкой. Он занимает 4 байта памяти обеспечивает диапазон представления чисел от 1.5х10^-45 до 3.4х10^48 с 7-8 значащими цифрами. 2. Тип с двойной точностью Double, занимающий 8 байт памяти и обеспечивающий представление чисел в диапазоне от 5.0х10^-334 до 1.7х10^308 с 15-16 значащими цифрами. 3. Тип с повышенной точностью Extended представляет собой наибольший формат представления чисел с плавающей запя- той, обеспечиваемый процессором 8087. Он занимает 10 байт памяти и обеспечивает диапазон представления чисел от 1.9х10^-4952 до 1.1х10^4932 с 19-20 значащими цифра- ми. Любые арифметические операции, в которых участвуют числа вещественного типа, выполняются с точностью и диа- пазоном представления, соответствующими типу с повышен- ной точностью. 4. Числа сложного типа Comp используются для предварительно объединенных значений в 8 байтах памяти, обеспечивая при этом диапазон представления от -2^63+1 до 2^63-1, что составляет приблизительно от -9.2х10^18 до 9.2х10^18. Сложный тип можно сравнить с длинным целым типом (двой- ная точность), но он считается вещественным типом, пос- кольку при операциях с числами этого типа используется сопроцессор 8087. Сложный тип хорошо подходит для предс- тавления значений денежных единиц, представляющих собой сотни и тысячи, которые используются в прикладных ком- мерческих программах. Независимо от того, используете вы сопроцессор 80x87 или нет, 6-битовый вещественный тип является допустимым. Таким обра- зом, при переходе к использованию сопроцессора 80 x87 вам не пот- ребуется изменять исходный текст программы, и вы можете использо- вать файлы данных, созданные программами, которые работают с программно обеспечиваемыми операциями с плавающей точкой. Отметим, однако, что аппаратные вычисления с переменными ве- щественного типа выполняются несколько медленнее, чем с перемен- ными другого типа. Это связано с тем, что сопроцессор 80x87 не может непосредственно обрабатывать вещественный формат. Вместо этого, перед выполнением операций, для преобразования веществен- ных значений в числа с повышенной точностью требуются обращения к библиотечным программам. Если вы заинтересованы в максимальной скорости выполнения и не собираетесь использовать свою программу на системах без сопроцессора 80x87, то возможно вы захотите ис- пользовать вещественный тип с одинарной точностью, вещественный тип с двойной точностью, вещественный тип с повышенной точностью и сложный типы явным образом.

Арифметические операции с повышенной точностью

При использовании сопроцессора 80x87 тип с повышенной точ- ностью Extended является основой всех операций с плавающей точ- кой. В Турбо Паскале тип с повышенной точностью используется для представления всех нецелых числовых констант, а также при вычис- лении всех выражений нецелого типа. Например, в следующих опера- циях присваивания все правые части выражений будут вычисляться, как выражения с повышенной точностью, а затем их тип будет преоб- разован к типу соответствующей левой части: {$N+} var X, AA, B, C : real; begin X := (B + Sqrt(B*B - A*C))/A; end; Borland Pascal выполняет вычисления с точностью и диапазоном представления чисел, соответствующими типу с повышенной точ- ностью, без дополнительных усилий программиста. Дополнительная точность приводит к меньшим ошибкам округления, а дополнительный диапазон означает, что ситуации переполнения и потери значимости будут встречаться в программах реже. Вы можете обойтись и без дополнительных автоматических воз- можностей вычислений с повышенной точностью Borland Pascal. Нап- ример, описать переменные, использующиеся для промежуточных вы- числений, как переменные с повышенной точностью. В следующем при- мере вычисляется сумма произведений: var Sm : single; X,Y array[1..100] of single; I : integer; T : extended; { для промежуточных результатов } begin T := 0.0; for I := 1 to 100 do T := T + X[I] * Y[I] Sum := T; end; Если бы переменная T была описана, как переменная с одинар- ной точностью, то при каждом цикле операции присваивания для пе- ременной T были бы выполнены с ошибкой округления и ограничения- ми, соответствующими одинарной точности. Но, поскольку переменная T является переменной с повышенной точностью, то все ошибки ок- ругления (кроме операции, при которой значение переменной T прис- ваивается переменной Suм) имеют ограничения, соответствующие по- вышенной точности. Меньшие ошибки округления означают более точ- ный результат. Для значений формальных параметров и результата функции вы также можете задать повышенную точность. Это поможет избежать не- нужных преобразований типов чисел, приводящих к потере точности. Например: function Area(Radius: extended): extended; begin Area := Pi * Radius * Radius; end;

Сравнение вещественных чисел

Поскольку значения вещественного типа являются приблизитель- ными, результат сравнения значений различного вещественного типа не всегда можно предсказать. Например, если Х - переменная ве- щественного типа с одинарной точностью, а Y - переменная вещест- венного типа с двойной точностью, то результатом выполнения сле- дующих операторов будет значение False: X := 1/3; Y := 1/3; Writeln(X = Y); Причина этого состоит в том, что Х имеет точность только до 7-8 цифр, а Y - точность до 15-16 цифр, и когда оба значения пре- образуются к типу с повышенной точностью, то после первых 7-8 цифр остальные цифры будут различаться. Аналогично, результатом выполнения операторов: X := 1/3; Writeln(X = 1/3); будет значение False, результат 1/3 в операторе Writeln вычисля- ется с точностью до 20 значащих цифр.

Стек вычислений сопроцессора 80x87

У сопроцессора 80x87 имеется внутренний стек вычислений, ко- торый может быть глубиной до восьми уровней. Доступ к значению, находящемуся в стеке сопроцессора 80x87 осуществляется намного быстрее, чем доступ к переменной в памяти, поэтому для достижения максимально возможной производительности в Borland Pascal внут- ренний стек сопроцессора 80x87 используется для хранения времен- ных результатов и для передачи параметров процедурам и функциям. Теоретически, слишком сложные выражения вещественного типа могут вызвать переполнение стека сопроцессора 80x87. Однако этого не может случиться, поскольку для этого потребовалось бы, чтобы в выражении получалось более восьми промежуточных результатов. Более весомая опасность таится во вложенных вызовах функций. Если такие конструкции составлены некорректно, то они, вполне ве- роятно, могут привести к переполнению стека сопроцессора 80x87. Рассмотрим, следующую функцию, в которой с помощью рекурсии вычисляются числа Фибоначчи: function Fib(N: integer): extended; begin if N = 0 then Fib := 0.0 else if N = 1 then Fib := 1.0 else Fib := Fib(N-1) + Fib(N-2); end; Обращение к данной версии процедуры Fib приведет к перепол- нению стека сопроцессора 80x87, так как значений N больше, чем 8. Причина заключается в том, что последний оператор присваивания требует временного сохранения результата выполнения процедуры Fib (N-1) в стеке сопроцессора 80x87. Каждое рекурсивное обращение выделяется одна ячейка стека и на девятом обращении произойдет переполнение стека. Корректной конструкцией в этом случае будет: function Fib(N : integer) : extended; var F1,F2 : Extended; begin if N = 0 then Fib := 0.0 else if N = 1 then Fib := 1.0 else begin F1 := Fib(N-1); F2 := Fib(N-2); Fib := F1 + F2; end; end; Временные результаты теперь сохраняются в переменных, для которых отводится стек процессора 8086. (Стек процессора 8086 ко- нечно тоже может переполниться, но это обычно требует гораздо большего числа рекурсивных вызовов).

Запись вещественных чисел при использовании сопроцессора 80x87

Если была указана директива {$N+}, то стандартные процедуры Write и Writeln, чтобы обеспечить представление в расширенном ди- апазоне, выводят в строке с десятичными числами с плавающей точ- кой четыре цифры для показателя степени вместо двух. Аналогично, стандартная процедура Str при выборе формата с плавающей точкой возвращает значение показателя степени, состоящее из четырех цифр.

Модули, в которых используется сопроцессор 80x87

Модули, в которых используется сопроцессор 80x87, могут вы- зываться другими модулями или программами только в том случае, если эти модули или программы были скомпилированы с директивой {$N+}. То, что модуль использует сопроцессор 80x87, определяется наличием в нем инструкций сопроцессора 80x87, а не директивой $N во время компиляции. Это позволяет компилятору быть более "снис- ходительным", когда вы случайно компилируете модуль (в котором используется сопроцессор 80x87), не указав директиву {$N+}. Когда вы выполняете компиляцию в режиме кода 80х87 (директи- ва {$N+}), то возвращаемые подпрограммами модуля Systем (Sqrt, Рi, Sin и т.д.) значения представляют собой не вещественные чис- ла, а числа типа Extended (с повышенной точностью).

Распознавание сопроцессора 80х87 в программах DOS

Исполняющая библиотека Borland Pascal, встроенная в вашу программу (скомпилированную с директивой {$N+}) включает в себя код инициализации, который автоматически распознает наличие в системе микросхемы сопроцессора 8087. Если сопроцессор 8087 име- ется, то программа будет его автоматически использовать. В случае же его отсутствия программа будет использовать эмулирующую библи- отеку исполняющей системы. Если программа компилировалась с ди- рективой {$E-} и по время начала ее работы сопроцессор не обнару- живается, то программа завершает работу с сообщением Numeric coprocessor required ("Требуется сопроцессор арифметических вы- числений"). Есть несколько случаев, когда вы возможно захотите изменить такую принятую по умолчанию логику автоматического обнаружения сопроцессора. Например, в вашей системе может присутствовать соп- роцессор 8087, но вы захотите проверить, как будет работать прог- рамма, предназначенная для функционирования на системах без соп- роцессора. Или же потребуется запустить вашу программу на системе, совместимой с компьютером РС, но на этой системе при ра- боте алгоритма автообнаружения будет выводиться некорректная ин- формация (например, будет сообщаться о наличие сопроцессора, ког- да на самом деле его нет, или наоборот). В Borland Pascal предусмотрена возможность отмены принятой по умолчанию логики автоматического распознавания. Эта возмож- ность задается переменной операционной среды 87. Вы можете установить переменную операционной среды 87 в от- вет на подсказку DOS с помощью команды SET, например, следующим образом: SET 87=Y или SET 87=N Установка для переменной операционной среды 87 значения N (Нет) указывает коду инициализации, что вы не хотите использовать сопроцессор 8087, хотя он может и присутствовать в системе. И на- оборот: установка для переменной 87 значения Y (Да) означает, что сопроцессор имеется, и вы хотите, чтобы ваша программа его ис- пользовала. Однако при этом нужно помнить о том, что установка для переменной 87 значения Y при отсутствии в системе сопроцессо- ра 8087 приведет к тому, что ваша программа аварийно завершит ра- боту или "зависнет". Если переменная операционной среды 87 определена, а вы хоти- те, чтобы она стала неопределенной, то можно ввести в ответ на подсказку DOS: SET 87= и нажать клавишу Enter. Если в операционной среде DOS присутствует запись 87=Y, или если код инициализации успешно распознает сопроцессор, то далее код инициализации выполняет последующие проверки, чтобы опреде- лить, какой это сопроцессор (8087, 80287 или 80387). Это необхо- димо для того, чтобы Турбо Паскаль мог корректно работать с от- дельными несовместимостями, которые имеются между сопроцессорами различных типов. Результат автоматического распознавания наличия сопроцессора и его модели сохраняется в переменной Test8087 (которая описыва- ется в модуле System). Для нее определены следующие значения: ---------------T-------------------------------- ¦ Значение ¦ Определение ¦ +--------------+--------------------------------+ ¦ 0 ¦ сопроцессор не обнаружен ¦ ¦ 1 ¦ обнаружен сопроцессор 8087 ¦ ¦ 2 ¦ обнаружен сопроцессор 80287 ¦ ¦ 3 ¦ обнаружен сопроцессор 80387 ¦ L--------------+--------------------------------- Чтобы определить характеристики системы, на которой работает ваша программа, вы можете в программе проверить содержимое пере- менной Test8087. В частности, эту переменную можно проанализиро- вать для того, чтобы определить, эмулируются инструкции работы с плавающей точкой, или они действительно выполняются.

Распознавание сопроцессора 80x87 в программе Windows

Операционная среда Windows и библиотека эмуляции WIN87EM.DLL автоматически распознает наличие в системе платы сопроцессора 80x87. Если сопроцессор 80x87 имеется, то программа будет его ав- томатически использовать. В случае же его отсутствия программа будет использовать эмуляцию с помощью WIn87EM.DLL. Чтобы опреде- лить наличие в системе сопроцессора 80х87, вы можете использовать функцию GetWinFlags (которая определена в модуле WinProcs) и би- товую маску wf_80x87 (определенную в модуле WinTypes). Например: if GetWinFlags and wf_80x87 <> 0 then Writeln('80x87 присутствует') else Writeln('80x87 отсутствует');

Использование эмуляции сопроцессора 80x87 на языке ассемблера

Когда компоновка объектных файлов выполняется с директивой {$L имя_файла}, необходимо обеспечить, чтобы эти файлы компилиро- вать с разрешением эмуляции сопроцессора 80x87. Например, если вы используете инструкции сопроцессора 80x87 во внешних процедурах на языке ассемблера, необходимо убедиться, что при ассемблирова- нии файлов .ASM в файлы .OBJ эмуляция разрешена. В противном слу- чае инструкции сопроцессора 80x87 не могут эмулироваться на маши- нах без сопроцессора 80x87. Для разрешения эмуляции используйте параметр командной строки Турбо Ассемблера /E.

[ Назад | Оглавление | Далее ]










helloworld.ru © 2001-2021
Все права защищены