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

HSE/ArchitectureASM/06_MathCoprocessor/Conspect (последним исправлял пользователь FrBrGeorge 2020-06-24 20:12:29)