2017-03-02 75 views
2

我试图在MIPS程序集中乘以两个IEEE 754数字而不使用浮点运算。在MIPS中乘以两个IEEE 754浮点数

我获得存储在$ 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.

然而,多功能是给出了非常奇怪的结果,我不知道为什么。任何人都可以看到我的逻辑错误?

+4

_“非常奇怪的结果”_不是一个很好的问题描述。输入和输出是什么(预期和实际)?由于您声称问题出现在'mul'中,请显示该指令的值。PS:你知道尾数是24位,所以你需要64位乘法? – Jester

+1

提示:产品符号是两个操作数符号的异或运算 – Nayuki

+2

一般而言,位级浮点操作相当困难,因为您需要处理归一化,上溢,下溢,低于正常,无穷大和NaN。我期望一个全功能的乘法程序能够像你所显示的那样获得3倍的代码 – Nayuki

回答

2

可惜我没那么好与IEEE 754修复您的MUL没有一些研究,但功能开场白让我感兴趣......

如果你有两个负数进入它,它就会跳到negative: ,而答案应该是积极的。

可以计算目标的标志,例如像这样:

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 $t1, $a0, 0x7F800000  #get exponent bits from fp1 
andi $t2, $a1, 0x7F800000  #get exponent bits from fp2 

当我在MARS试图在这两个a0, a1~0打电话给你的代码,andi后的结果是0x9D800000,这显然是错误的。尾数相同的是andi,完全在MARS中。

也许你的汇编程序确实理解这些,但我建议验证。

你应该像下面这样处理溢出下的指数?

# 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 

在该部分$t1是这个数的指数部分,如果有人想找到它的指数部分,他们可以使用它。

我写了这个,因为在我的实验室任务中我必须找到指数部分,这要归功于我能弄清楚我的问题。

如果有人有这样的问题,他们可以使用上面的代码。