Математический сопроцессор

IEEE 754

Базовая лекция

Вещественные числа и их запись

Несколько слов о представлении вещественных чисел.

Хотелось бы напомнить, что мы имеем дело не с реальными вещественными числами, а с их (рациональным) представлением, в этом смысле любое вещественное число может быть представлено в привычном нам виде ( в виде числа с "фиксированной точкой"), например 1234.5 или 0.012345 или в научном (экспонециальном) виде (в виде числа с "плавающей точкой"). Например, 1234.5 = 1.2345*103, 0.012345 = 1.2345*10-2. Часто эти числа записываются в виде 1,2345·exp103 и 1,2345·exp10-2 , а в тексты программы (и при вводе-выводе) — 1.2345E3 и 1.2345-E2 соответственно. Таким образом вещественное число состоит из двух частей: мантиссы (в примере 1.2345) и показателя степени — порядка (в примере 3 и -2 соответственно). Одно и то же число можно записать несколькими способами, в зависимости от того, чему равна мантисса. Например, все эти записи соответствуют одному и тому же числу 155.625:

Хранение вещественных чисел в памяти

Представим число 155.625 в виде двоичного числа с плавающей точкой, для этого разложим заданное число по двоичным разрядам:

155.625 = 1·27 +0·26+0·25+1·24+1·23+0·22+1·21+1·20+1·2-1+0·2-2+1·2-3 155.625 =128 + 0 + 0 + 16 + 8 + 0 + 2 + 1 + 0,5 + 0 + 0,125 155.62510 = 10011011,1012 - число в десятичной и в двоичной системе с плавающей точкой

Полученное число в экспоненциальном виде в двоичной системе будет иметь вид: 1,55625·exp10+2 = 1,0011011101·exp2+111

То есть его мантисса имеет вид 1.0011011101, а порядок — exp2= +111

В действительности все несколько хитрее. Согласно стандарту IEEE 754, в памяти вещественные числа одинарной точности представляются в следующем виде (стандарт IEEE 754)

Понятно, что число может быть либо неотрицательным, либо отрицательным, поэтому один бит на знак нам придется использовать, и это самый старший бит. 0 - число неотрицательное, 1 - число отрицательное (Область S на картинке)

В IEEE754 порядок (который может быть и положительным, и отрицательным, и нулём) хранится в виде всегда неотрицательного числа, для чего к нему добавляют «смещение» размером в половину допустимого диапазона. Например, в стандарте на 32-разрядное целое порядку отведено 8 битов (область E), в которых можно хранить числа 0…255. Допустимый порядок числа, таким образом, колеблется от -127 до 127, а при записи в ячейку к нему добавляется 127. В примере порядок = +7 (+111 в двоичной), соответственно, смещённый порядок = 7+127=134 ( 10000110 ). А если бы порядок был -7 , то смещенный порядок = 127-7 =120. Чтобы узнать истинный порядок, надо вычесть 127 из содержимого области E.

Если вспомнить, что «вещественные» числа IEE754 — на самом деле целочисленные двоичные дроби, каждое число можно представить себе в виде мантиссы, сдвинутой влево на соответствующее порядку число разрядов. Сдвиг на 0 разрядов будет соответствовать наименьшему по модулю числу, а сдвиг на 254 — наибольшему. Таким образом, для сравнения и проведения арифметических операций это представление наиболее удобно.

В 32 битном представлении на мантиссу (область M) приходится 23 бита. Это обеспечивает довольно низкую точность: 223=8388608, все числа, по модулю большие, будут терять значимые знаки до запятой. В IEE754 используется хитрость, позволяющая сэкономить ещё один бит мантиссы:

Число

1 бит

8 бит

23 бит

Шестнадцатеричное

знак числа

смещённый порядок

мантисса

155.625

0

10000110

00110111010000000000000

431BA000

-5.23E-39

1

00000000

01110001111001100011101

8038f31d

Второй пример — это близкое к нулю число, мантисса которого хранится в денормализованом виде.

Вещественные числа двойной точности занимают 64 бита. Поле S в них такое же однобитное, на поле E (порядок) отводится 11 битов, а остальные 52 — на поле M (мантисса).

Дело в том, что 24 бита на мантиссу — это очень мало. Например TODO

Более подробно смотрите основную статью Стандарт IEEE 754

В Mars есть хороший инструмент для изучения числа в формате IEEE754: «Tools → Floating Point Representation». В частности, легко проверить, что когда в мантиссу записаны одни только нули, это соответствует близкому к нулю числу в денормализованной форме.

А чему соответствует мантисса, состоящая из всех 1?

FPU, он же C1

Базовая лекция

Сопроцессоры

Инструкции FPU-сопроцессора

Вопрос: чем плохо было бы объединить инструкции преобразования плавающего в целое и обратно с инструкциями обмена между регистрами общего назначения и регистрами FPU?

Особенности работы с сопроцессором

Сопроцессор FPU в MIPS использует биты состояния, которые хранит в специальном регистре. Этот регистр доступен побитно основному процессору.

Так же, как, например, в УМ-2, операции условного перехода становятся неатомарными:

Пример вычислений с плавающей точкой

Вычисление числа e как бесконечной суммы 1/(n!) при n→∞, т. е. Σn=01/(n!)

   1 .data
   2 one:    .double 1
   3 ten:    .double 10
   4 .text
   5         l.d     $f2 one         # 1
   6         sub.d   $f4 $f4 $f4     # n
   7         mov.d   $f6 $f2         # n!
   8         mov.d   $f8 $f2         # здесь будет e
   9         l.d     $f10 ten        # здесь будет ε
  10         mov.d   $f0 $f2         # количество знаков после запятой K
  11         li      $v0 5
  12         syscall
  13 
  14 enext:  blez    $v0 edone       # посчитаем 10**(K+1)
  15         mul.d   $f0 $f0 $f10
  16         subi    $v0 $v0 1
  17         b       enext
  18 edone:  div.d   $f10 $f2 $f0    # посчитаем ε
  19 
  20 loop:   add.d   $f4 $f4 $f2     # n=n+1
  21         mul.d   $f6 $f6 $f4     # n!=(n-1)!*n
  22         div.d   $f0 $f2 $f6     # очередное слагаемое
  23         add.d   $f8 $f8 $f0
  24         c.lt.d  $f0 $f10        # очередное слагаемое < ε
  25         bc1f    loop
  26 
  27         mov.d   $f12 $f8        # выведем результат
  28         li      $v0 3
  29         syscall

Для того, чтобы гарантировать попадание приближения в ε-окрестность результата, надо убедиться, что всякое очередное приближение будет отстоять не больше, чем на ε от текущего. В нашем случае это просто:

Д/З

LecturesCMC/ArchitectureAssembler2019/05_FloatingPiont (last edited 2019-05-17 12:20:30 by FrBrGeorge)