我试图在不使用浮点运算的情况下在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函数给出了非常奇怪的结果,我不知道为什么。任何人都可以看到我的逻辑错误?
答案 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
是这个数字的指数部分,如果有人想找到它的指数部分,他们可以使用它。
我写过这个是因为在我的实验室任务中我必须找到指数部分,多亏了这个我能解决我的问题。
如果有人有这样的问题,他们可以使用上面的代码。