在MIPS中乘以两个IEEE 754浮点数

时间:2017-03-02 00:01:29

标签: assembly binary logic mips floating

我试图在不使用浮点运算的情况下在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。

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

2 个答案:

答案 0 :(得分: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中尝试在~0中使用a0, a1来调用您的代码时,andi之后结果为0x9D800000,这是完全错误的。尾数andi同样适用于MARS。

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

你应该在/溢出下处理exponent,像这样吗?

    # 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

答案 1 :(得分:0)

(004026579154BP05000004026579154111213V0000.0000N00000.0000E000.0000000000.0010000000L0000021C)

在那个部分srl $t1, $a0, 23 //This take the exponent part andi $t1, $t1, 0xFF 是这个数字的指数部分,如果有人想找到它的指数部分,他们可以使用它。

我写过这个是因为在我的实验室任务中我必须找到指数部分,多亏了这个我能解决我的问题。

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