2017-03-02 9 views
2

浮動小数点演算を使用せずにMIPSアセンブリで2つのIEEE 754数値を掛けようとしています。MIPSで2つのIEEE 754浮動小数点数を掛ける

私は私が考える仮数セクションとのトラブルを抱えています2つの浮動小数点の$ A0に保存されている数字と$ A1

multiply_fp: #$s0 = final sign bit, $s1 = final exponent, $s2 = final mantissa 

    #check the sign bit 
    srl $t1, $a0, 31 # leave just sign bit 
    srl $t2, $a1, 31 # leave just sign bit 

    bnez $t1, negative # check if sign bit is 1 
    bnez $t2, negative # check if sign bit is 1 
positive: 
    addi $s0, $zero, 0 # set sign bit to 0 
    j exponent 
negative: 
    addi $s0, $zero, 10000000000000000000000000000000 #set sign bit to 1 
exponent: 
    andi $t1, $a0, 01111111100000000000000000000000  #get exponent bits from fp1 
    andi $t2, $a1, 01111111100000000000000000000000  #get exponent bits from fp2 
    srl $t1, $t1, 23     #move them all the way to the right 
    srl $t2, $t2, 23 
    add $s1, $t1, $t2     #add them together 
    addi $s1, $s1, -127     #subtract 127 from the sum 
    sll $s1, $s1, 23     #move them back to the right position 

mantissa: 
    andi $t1, $a0, 00000000011111111111111111111111  #get the mantissa bits from fp1 
    andi $t2, $a1, 00000000011111111111111111111111  #get the mantissa bits from fp2 
    ori $t1, $t1, 00000000100000000000000000000000  #add a 1 at the msb 
    ori $t2, $t2, 00000000100000000000000000000000 
    mul $s2, $t1, $t2     #multiply the mantissas 
    andi $s2, 00000000011111111111111111111111  #cut the 1 back off 

combine: 
    or $v0, $s0, $s1 
    or $v0, $v0, $s2 

    jr $ra 

を持っています。私の論理によれば、小数部分を掛けて1を取り除くことになります。例えば1.011 * 1.010 = 1.10111とすると、先頭の1を切り捨てて10111を新しい仮数にします。小数点を削除するだけで1011 * 1010 = 110111となり、先頭の1を切り捨てて10111になります。

しかし、mul関数は非常に奇妙な結果を出しています。理由はわかりません。誰も私の論理でエラーを見ることができますか?

+4

_ "非常に奇妙な結果" _は良い問題の説明ではありません。インプットとアウトプット(予想と実際)は何でしたか?問題が 'mul'であると主張しているので、その命令の値を表示してください。PS:仮数が24ビットであることは分かりますので、64ビットの乗算が必要ですか? – Jester

+1

ヒント:製品の符号は2つのオペランドの符号のXORです – Nayuki

+2

一般に、正規化、オーバーフロー、アンダーフロー、サブノーマル、無限大、NaNに対処する必要があるため、ビットレベルの浮動小数点操作は非常に困難です。私は完全に機能する乗算ルーチンがあなたが示したように3倍のコードを取ることを期待しています – Nayuki

答えて

2

残念ながら、あなたは2つの負の数値でそれを入力すると、それはnegative:にジャンプします私はいくつかの勉強せずにMULを修正するためにIEEE 754で良いことないんだけど、関数プロローグは私が興味を持った...

一方、答えは肯定的でなければならない。

あなたはこのように例えばターゲットサインを計算することができます。

multiply_fp: 
    xor  $s0, $a0, $a1 # multiply sign bits 
    andi $s0, 0x80000000 # extract sign bit to s0 

そして、私はあなたが使用しているものアセンブラわからないんだけど、私はここでのみMARSがあり、その一つが誤ってこれらの二進数をコンパイルします。私はその構文のための助けを見つけることができませんでした(含まれているヘルプは非常に数値定数と可能な書式についてはあいまいです)。

ので、代わりの:私は古き良きヘキサに固執するだろう

andi $t1, $a0, 01111111100000000000000000000000  #get exponent bits from fp1 
andi $t2, $a1, 01111111100000000000000000000000  #get exponent bits from fp2 

:私は結果が andiた後、両方の a0, a1~0であなたのコードを呼び出すためにMARSにしようとした

andi $t1, $a0, 0x7F800000  #get exponent bits from fp1 
andi $t2, $a1, 0x7F800000  #get exponent bits from fp2 

0x9D800000、これは間違っています。 MARSで完全にボルケートされた仮説andiも同様です。

あなたのアセンブラはそれらを理解していることがありますが、確認することをお勧めします。

おそらく指数部の下/オーバーフローを処理する必要がありますか?その部分$t1

# calculate exponent - extract exponents to t1, t2 
    srl  $t1, $a0, 23 
    srl  $t2, $a1, 23 
    andi $t1, $t1, 0xFF 
    andi $t2, $t2, 0xFF 
    addu $s1, $t1, $t2  # add exponents together 
    bltu $s1, 127, exp_too_small # if exp is less than 127 => too small 
    addiu $s1, $s1, -127 # subtract 127 from the sum 
    sll  $s1, $s1, 23  #move exp back to the right position 
    bltz $s1, exp_too_big # if sign bit is set, exponent is too big 
+0

ありがとう!それはより大きな問題を解決するものではありませんが、それは大きなインプットであり、潜在的な問題を解決するのに役立ちました。私はあなたの助けに感謝します! – Tom

0
srl  $t1, $a0, 23 //This take the exponent part 
andi $t1, $t1, 0xFF 

誰もが、彼らはそれを使用することができ、それの指数部分を見つけたい場合は、この数の指数部です。

私はラボの課題で指数部を見つけなければならないので、これを書いたのですが、これで私の問題を理解することができます。

誰かが上記のコードを使用できるような問題がある場合。

関連する問題