06.1 Conspect (ru)
Современная эксплуатация компьютеров просто построена примерно по одному и тому же принципу - появляется некоторая задача ее решают какими-то современными к тому времени способами и вот в таком виде эти решения залипают лет на 50 неизменно.
Пришлось придумать некий механизм когда у вас вычислением специальных функций занимается вообще другой процессор – соседний. У нас есть основной процессор который заведует выполнением программ а ещё у нас есть
сопроцессор у которого свои тайминги который может работать медленнее быстрее дороже дешевле иметь свою собственную структуру.
Типичный сопроцессор на самом деле - графические видеокарты. Задача графических видеокарт обрабатывать безумное количество вообще говоря однотипных операций.
Никогда при вычислениях не используется вещественные числа всегда используются их модели потому что их представить практически невозможно. Вот эти модели разумеется представляют числа с какой-то точностью. Думая про пи и е мы можем думать до какого-то знака после запятой.
Давайте вспомним что есть два вида представления вещественных чисел - с фиксирующей точкой и с плавающей точкой.
Но мы не избавились от проблемы пресловутых нулей – не очень понятно с какой точностью все это может существовать.
Числа хранятся в двоичном виде в памяти, не в десятичном. В том числе и числа вещественные - их модели хранятся в двоичном виде.
Пример моделирования реальных чисел:
$$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
128 + 0 + 0 + 16 + 8 + 0 + 2 + 1 + 0,5 + 0 + 0,125 155.62510
= $$10011011.101_2$$
Первый бит означает знак. Вот следующие восемь битов это собственно
экспонента, по-русски порядок, оставшиеся двадцать три бита это мантисса
Если вы посмотрите на знаковый бит вы увидите что отрицательные числа начинаются на 1 а положительно на 0.
У нас есть ячейка памяти 32 бита в который внезапно лежит вещественное число мы хотим понять что это за число и какие части этой ячейки чему соответствует.
НО иногда, некоторые сочетания мантиссы и порядка дают число когда дают нечто что не является числом. Вы можете что-то такое записать в память откуда нельзя будет прочитать в виде вещественного числа - возникнут исключения.
Предусмотрен математический сопроцессор у которого есть 32 своих собственных регистра. Хранят они их там по стандарту е754. У нас есть 32 регистра float то есть одинарной точности и 16 регистров двойной точности.
Операции с числами float и double:
mul.s $f1 $f2 $f8 add.d $f0 $f0 $f2
mov.s $f4 $f7 sqrt.d $f0 $f4
l.s $f1 40($t4) s.d $f6 ($t5)
mtc1.s $t1 $f3 mfc1.d $t2 $f4
cvt.w.s $f1 $f1 floor.w.d $f2 $f4
Результат сравнения кладется в специальный регистр флагов:
c.le.s $f0 $f1 movt $t4 $t3 movt.s $f1 $f0
Посмотрим на примеры - пример как вычислить квадратный корень
.data src: .word 100 dst: .float 0 idst: .word 0 .text lw $t0 src # source integer mtc1 $t0 $f2 # store to FPU cvt.s.w $f2 $f2 # convert to single-sized float mtc1 $zero $f0 # zero in $f0 (non need to convert) c.lt.s $f2 $f0 # check if <0 … bc1t nosqrt # no root then sqrt.s $f2 $f2 nosqrt: s.s $f2 dst # store float result cvt.w.s $f2 $f2 # convert to integer mfc1 $t0 $f2 # get from FPU sw $t0 idst # store integer result
Cчитаем $$e$$ как $$ \sum_{n=1}^{\infty} \frac{1}{n!}$$
.data one: .double 1 ten: .double 10 .text l.d $f2 one # 1 sub.d $f4 $f4 $f4 # n mov.d $f6 $f2 # n! mov.d $f8 $f2 # here will be e l.d $f10 ten # here will be ε mov.d $f0 $f2 # decimal length K li $v0 5 syscall enext: blez $v0 edone # 10**(K+1) mul.d $f0 $f0 $f10 subi $v0 $v0 1 b enext edone: div.d $f10 $f2 $f0 # ε loop: add.d $f4 $f4 $f2 # n=n+1 mul.d $f6 $f6 $f4 # n!=(n-1)!*n div.d $f0 $f2 $f6 # next summand add.d $f8 $f8 $f0 c.lt.d $f0 $f10 # next summand < ε bc1f loop li $v0 3 # output a double mov.d $f12 $f8 # $f12 by syscall standard syscall