Автор работы: Пользователь скрыл имя, 11 Января 2011 в 19:34, лекция
Язык ассемблера - это один из самых старых из всех существующих языков программирования. Когда-то это был один из основных языков программирования, без знания которого нельзя было заставить компьютер сделать что-либо полезное. Появились более удобные средства общения с компьютером. Но в отличии от других языков ассемблер не умирал, более того он это не смог сделать в принципе.
Старший байт регистра состояния содержит:
Младший байт регистра состояния содержит флажки особых случаев сопроцессора: переполнение стека, потеря точности, потеря значащих разрядов, численное переполнение, деление на ноль, денормализация, недействительная операция. Если соответствующий особый случай возник и не был замаскирован (в слове управления), это приведет к генерации центральным процессором особого случая сопроцессора (#16).
Младшее слово регистра управления содержит биты масок особых случаев. Сопроцессор допускает индивидуальное маскирование особых случаев. Если тот или иной особый случай замаскирован, при возникновении соответствующей ситуации сопроцессор выполняет некоторые заранее определенные внутренние действия, которые зачастую приемлемы для большинства применений. Например, если замаскирован особый случай деления на ноль, то выполнение операции 85,32/0 даст результат + ∞.
Старшее слово регистра управления содержит два поля: управление точностью PC (биты 8 и 9) и управление округлением RC (биты 10 и 11). Биты управления точностью можно использовать для понижения точности вычислений. По умолчанию используется расширенная точность (PC = 112), можно также использовать двойную точность (PC = 102) и одинарную точность (PC = 002) по стандарту IEEE-754.
Если результат численной операции не может быть точно представлен в выбранном формате, сопроцессор выполняет округление в соответствии с полем RC (табл. 8.3). По умолчанию RC = 00. В примерах в табл. 7.3 сделана попытка представить числа +2,23 и +2,05 в виде двоичных вещественных чисел с 3-битной дробной частью мантиссы. В этом формате нельзя подобрать точное двоичное значение для этих чисел. Ближайшие к ним представимые числа - +2,00 (+1,000E21) и +2,25 (+1,001E21).
Таблица 8.3. Режимы округления сопроцессоров Intel x87 | |||
RC | Режим | Пример
1
1,000E21 < 2,23E100 < 1,001E21 -1,001E21 < -2,23E100 < -1,000E21 |
Пример
2
1,000E21 < 2,05E100 < 1,001E21 -1,001E21 < -2,05E100 < -1,000E21 |
00 | Округление к ближайшему (или четному) | 2,23E100
≈ 1,001E21
-2,23E100 ≈ -1,001E21 |
2,05E100
≈ 1,000E21
-2,05E100 ≈ -1,000E21 |
01 | Округление вниз (к ∞) | 2,23E100
≈ 1,000E21
-2,23E100 ≈ -1,001E21 |
2,05E100
≈ 1,000E21
-2,05E100 ≈ -1,001E21 |
10 | Округление вверх (к +∞) | 2,23E100
≈ 1,001E21
-2,23E100 ≈ -1,000E21 |
2,05E100
≈ 1,001E21
-2,05E100 ≈ -1,000E21 |
11 | Округление к нулю (усечение) | 2,23E100
≈ 1,000E21
-2,23E100 ≈ -1,000E21 |
2,05E100
≈ 1,000E21
-2,05E100 ≈ -1,000E21 |
Регистр
тегов содержит 8 тегов - признаков,
характеризующих содержимое соответствующего
численного регистра сопроцессора. Тег
может принимать следующие
00 - в регистре находится действительное число;
01 - нулевое число в регистре;
10
- недействительное число (
11 - пустой регистр.
Сопроцессор использует теги, чтобы определить переполнение или опустошение стека. Если при помещении в стек очередного числа окажется, что декрементированный TOS указывает на непустой регистр (соответствующий тег не равен 112), сопроцессор сигнализирует о переполнении стека. Если при извлечении из стека числа окажется, что инкрементированный TOS указывает на пустой регистр (соответствующий тег равен 112), сопроцессор сигнализирует об опустошении стека.
Указатель команд и указатель данных содержат логические адреса (селектор сегмента и смещение) последней команды и ее операнда. (это 32-битные регистры у 8087 и 80287 и 48-битные - у 80387 и FPU). Эта информация используется обработчиком особых случаев сопроцессора.
Для команд сопроцессора выделена группа кодов, начинающаяся с 11011ххх. В ассемблерах мнемоники команд сопроцессора начинаются с "F": FADD (сложение), FCOM (сравнение), FCOS (косинус), FDIV (деление) и т.п.
Параллельная работа ЦП и сопроцессора ставит перед программистом проблемы синхронизации. Например:
mem DW 0
:
FILD mem
INC mem
FSQRT
В данном примере, команда FILD преобразует 16-битное целое число в памяти в формат сопроцессора и сохраняет его в ST, затем целочисленная команда INC увеличивает это значение на 1, после чего сопроцессор вычисляет квадратный корень ST (FSQRT).
Для внешних сопроцессоров (8087, 80287, 80387) ЦП начнет выполнять команду INC раньше, чем сопроцессор закончит FILD, а, следовательно, в стек сопроцессора может попасть неверное значение. Встроенный блок FPU у IA-32 лишен этого недостатка, т. к. ЦП отслеживает обращения к памяти и не начнет выполнять целочисленную команду, если она обращается к ячейке памяти, с которой в данный момент работает блок FPU. Однако остается нерешенной другая проблема. Если при выполнении инструкции FPU возникает ситуация, соответствующая одному из незамаскированных особых случаев, FPU прекращает выполнение инструкции и сигнализирует об особом случае. Однако соответствующее исключение процессора будет вызвано только при очередном обращении процессора к блоку FPU, а до этого момента целочисленный блок может изменить ячейку памяти, значение которой привело к исключению, так что обработчик исключения не сможет правильно интерпретировать причину особого случая.
Описанная ситуация говорит о необходимости использовать в таких случаях средства синхронизации. Например, команда FWAIT приостанавливает работу целочисленного устройства до тех пор, пока не будет завершена работа выполняемой сопроцессором инструкции или не будет вызвано исключение, если при выполнении последней инструкции FPU возник особый случай. Для этих же целей можно использовать любую другую инструкцию сопроцессора, кроме специальных "неожидающих" инструкций: FNINIT - сброс сопроцессора без ожидания, FNSTCW/FNSTSW - сохранение регистра управления/состояния без ожидания, FNCLEX - сбросить флаги особых случаев без ожидания, FNSAVE/FNSTENV - сохранение состояния (контекста) сопроцессора без ожидания.
Таким образом, для решения проблемы синхронизации приведенный выше пример следует переписать так:
FILD mem
FSQRT
INC mem
Команды ззагрузки в стек (Fpu LoaD):
При выполнении этих команд операнд считывается из оперативной памяти, преобразуется в формат с расширенной точностью. Затем поле ST регистра состояния уменьшается на единицу и выполняется запись операнда в численный регистр, определяемый новым значением поля ST. То есть операнд записывается в стек численных регистров, а указатель стека (поле ST) уменьшается на единицу. По своему действию эти команды напоминают команду PUSH центрального процессора.
Непосредственно перед загрузкой численного регистра проверяется содержимое поля TAG0. Если это содержимое не равно 11 (пустой регистр), в регистре состояния устанавливается флаг IE (недействительная операция) и вырабатывается прерывание (если в регистре управления не установлена маска IM - маска недействительной операции).
Команды сохранения и извлечения из стека (Fpu STore and Pop):
Эти
команды сначала сохраняют
После записи содержимое поля ST увеличивается на единицу. Эти действия аналогичны выполняемым командой POP центрального процессора.
В зависимости от команды (FSTP, FISTP или FBSTP) производится преобразование формата (из расширенного в вещественный, целый или десятичный, соответственно). В процессе преобразования для команд FSTP и FISTP выполняется округление в соответствии с содержимым поля RC регистра управления. Для команды FBSTP округление всегда выполняется следующим образом - прибавляется число 0.5, затем дробная часть результата отбрасывается.
Команды копирования данных (Fpu STore):
Эти команды пересылают данные из верхушки стека в область памяти, указанную операндом команды. При этом содержимое указателя стека (поля ST) не изменяется.
Команда FST в качестве операнда может использовать ссылку на численный регистр ST(i), поэтому эту команду можно использовать для копирования верхушки стека в любой другой численный регистр.
При записи данных в оперативную память выполняется преобразование формата (в вещественный для FST, в целый для FIST и в десятичный для FBST.
Команда обмена (Fpu eXCHange):
Команды загрузки констант:
Загрузка констант выполняется намного быстрее специальными командами, нежели командами загрузки данных из оперативной памяти.
Сопроцессор использует шесть основных типов арифметических команд:
Первый операнд берется из верхушки стека (источник), второй - следующий элемент стека. Результат выполнения команды записывается в стек
Источник берется из памяти, приемником является верхушка стека ST(0). Указатель стека ST не изменяется, команда действительна только для операндов с одинарной и двойной точностью
Аналогично предыдущему типу команды, но операндами могут быть 16- или 32-разрядные целые числа