Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 添加两个不带浮点寄存器的双精度浮点数的MIPS_Assembly_Double_Mips_Add - Fatal编程技术网

Assembly 添加两个不带浮点寄存器的双精度浮点数的MIPS

Assembly 添加两个不带浮点寄存器的双精度浮点数的MIPS,assembly,double,mips,add,Assembly,Double,Mips,Add,我正在编写一个程序,在不使用浮点寄存器的情况下添加两个double。这是一种工作现在,但一些数字给我错误的结果。例如,1+1和2.5+2.4都有效,但1+2给了我7,或者1001.5+8998.4给了我26383.8999,我想我已经确定了问题,那就是:在添加数字后,我移动(标准化)结果,这只应该是在形式中的情况,例如10.0110。问题是我不知道如何检查总和是否为10。(某些东西)然后继续标准化,或1.(某物),然后直接显示结果。如果有人能帮我找到答案或更正代码,我将非常感激。 编辑:多亏了帮

我正在编写一个程序,在不使用浮点寄存器的情况下添加两个double。这是一种工作现在,但一些数字给我错误的结果。例如,1+1和2.5+2.4都有效,但1+2给了我7,或者1001.5+8998.4给了我26383.8999,我想我已经确定了问题,那就是:在添加数字后,我移动(标准化)结果,这只应该是在形式中的情况,例如10.0110。问题是我不知道如何检查总和是否为10。(某些东西)然后继续标准化,或1.(某物),然后直接显示结果。如果有人能帮我找到答案或更正代码,我将非常感激。 编辑:多亏了帮助,我成功地解决了加法的问题,但现在我注意到了用不同符号添加数字的问题。当有不同的符号数字被减除时,我就这样做了。它适用于整数和一些双倍数,但例如33.5-23.2的结果是0.110100110011。。。标准化为1.10110100110011…=27.3,而它应该是1.01100110011…=11.3更新代码:

.data
text1:  .asciiz "Enter first double: "
text2:  .asciiz "Enter second double: "
text3:  .asciiz "Result: "
quest:  .asciiz "\nIf you want to continue enter 1, otherwise enter 0: "
num1a:  .word       0           # sign, exponent and part of the mantissa 
num1b:  .word       0           # second part of the mantissa
num2a:  .word       0           # sign, exponent and part of the mantissa
num2b:  .word       0           # second part of the mantissa
    .text
    .globl input    
input:  
    #print "Enter first double: "
    la  $a0, text1
    li  $v0, 4
    syscall
    # saving input double into num1
    li  $v0, 7
    syscall                 
    swc1    $f0, num1b
    swc1    $f1, num1a
    #print "Enter second double: "
    la  $a0, text2
    li  $v0, 4
    syscall
    # saving input double into num2
    li  $v0, 7
    syscall                 
    swc1    $f0, num2b
    swc1    $f1, num2a

    # loading data to registers
    lw  $t0, num1a
    lw  $t1, num1b
    lw  $t2, num2a
    lw  $t3, num2b


#########################################################sign
sign:       
    move    $t4, $t0
    andi    $t4, $t4, 0x80000000    #preserve sign, zero the rest

    move    $t5, $t2
    andi    $t5, $t5, 0x80000000    #preserve sign, zero the rest

    bne     $t4, $t5, same
    j       extract

same:
    bne     $t0, $t2, extract
    beq     $t1, $t3, zero

extract:    
################################################checking for zero
    or   $s2, $t0, $t1       #if both part of double are equal to zero we skip all the calculation
    or  $s3, $t2, $t3
    beqz    $s2, first_zero
    beqz    $s3, output

###############################sign, exponent and mantissa
    move    $t6, $t0    
    andi    $t6, $t6, 0x7FF00000    #extracting exponent to $t6 
    move    $a0, $t6

    move    $t7, $t0
    andi    $t7, $t7, 0x000FFFFF    #extracting first part of mantissa
    ori     $t7, $t7, 0x00100000    #adding prefix one to mantissa
    #remaining mantissa stays in register $t1

    move    $t8, $t2    
    andi    $t8, $t8, 0x7FF00000    #extracting exponent to $t8
    move    $t9, $t2
    andi    $t9, $t9, 0x000FFFFF    #extracting first part of mantissa
    ori     $t9, $t9, 0x00100000    #adding prefix one to mantissa
    #remaining mantissa stays in register $t3

#########################################################
exp_check:
    #beq    $t6, $t8, adding
    bgt    $t6, $t8, exp1 #exponent $t8 smaller than $t6
    bgt    $t8, $t6, exp2

    bgt     $t4, $t5, sub_first
    blt     $t4, $t5, sub_second

add:

    addu   $t7, $t7, $t9 #add first parts of mantissas
    addu   $t1, $t1, $t3 #add the rest of the mantissas

    move   $s1, $t4      #move sign of the first double to $s1

    j      shift 

sub_first:
    bgt    $t9, $t7, sub_second
    bgt    $t3, $t1, sub_second

    subu   $t7, $t7, $t9 #sub first parts of mantissas
    subu   $t1, $t1, $t3 #sub the rest of the mantissas

    move   $s1, $t4

    j      shift2 

sub_second:
    subu   $t7, $t9, $t7 #sub first parts of mantissas
    subu   $t1, $t3, $t1 #sub the rest of the mantissas

    move   $s1, $t5      #move sign of the secon double to $s1

    j      shift2 

exp1:
    sll    $s4, $t9, 31 #copy lsb of m1
    sll    $s5, $t3, 31 #copy lsb of m2

    srl    $t9, $t9, 1 #shift first part of the mantissa
    srl    $t3, $t3, 1 #shift the rest of the mantissa

    or     $t9, $t9, $s4 #put lsb in m1
    or     $t3, $t3, $s5 #put lsb in m2

    addiu  $t8, $t8, 0x00100000 #increase exponent $t8

    j      exp_check
exp2:
    sll    $s4, $t7, 31 #copy lsb of m1
    sll    $s5, $t1, 31 #copy lsb of m2

    srl    $t7, $t7, 1 #shift first part of the mantissa
    srl    $t1, $t1, 1 #shift the rest of the mantissa

    or     $t7, $t7, $s4 #put lsb in m1
    or     $t1, $t1, $s5 #put lsb in m2

    addiu  $t6, $t6, 0x00100000 #increase exponent $t6

    j      exp_check

shift:

    #andi    $t8, $t7, 0x80000000
    #li    $t4, 0
    #bne    $t8, $t4, result

    andi     $t4, $t7, 0x00200000
    beqz     $t4, result

    sll    $s2, $t7, 31 #copy least significant bit of m1
    #sll    $s3, $t1, 31 #copy lsb of m2

    srl    $t7, $t7, 1 #shift right m1
    srl    $t1, $t1, 1 #shift right m2

    or     $t1, $t1, $s2 #put m1's lsb in m2 msb
    #or     $t1, $t1, $s3 #put lsb in m2

    add    $t6, $t6, 0x00100000 #increase exp
    j result

shift2:
    andi     $t4, $t7, 0x00100000
    bnez     $t4, result

    srl     $s3, $t1, 31 #copy most significant bit of m2
    #sll    $s2, $t7, 31 #copy most significant bit of m2
    #sll    $s3, $t1, 31 #copy lsb of m2

    sll    $t7, $t7, 1 #shift right m1
    sll    $t1, $t1, 1 #shift right m2

    or     $t7, $t7, $s3 #put m2's msb in m1 lsb
    #or     $t1, $t1, $s3 #put lsb in m2

    sub    $t6, $t6, 0x00100000 #increase exp

result:
    andi   $t7, $t7, 0x000FFFFF    #preserve mantissa, zero the rest(cut the prefix - one)

    move   $t0, $s1       #copy propoer sign
    or     $t0, $t0, $t6      #add exponent
    or     $t0, $t0, $t7       #add mantissa part1
    b      output

first_zero:
    move  $t0, $t2
    move  $t1, $t3
    j     output

zero:
    li  $t0, 0x00000000
    li  $t1, 0x00000000

output:
    sw  $t0, num1a
    sw  $t1, num1b
    #print "Result: "
    la  $a0, text3
    li  $v0, 4
    syscall
    lwc1    $f12, num1b
    lwc1    $f13, num1a
    #print double - the result
    li  $v0, 3
    syscall
question:
    la  $a0, quest          #Do you want to enter new numbers or finish?
    li  $v0, 4
    syscall
    li  $v0, 5           #reads the answer (integer)
    syscall
    beq $v0, 1, input           #if input =1, continue, if 0 finish, otherwise ask again
    beqz    $v0, fin
    b   question
fin:
    li  $v0, 10             #exit
    syscall

算法应遵循以下原则:

假设我们想添加1234和567,但要以浮点方式进行。对于这个非二进制示例,假设1234为1.234*10^3,567为5.67*10^2

10^3是较大的指数,所以我们需要对齐小数点,所以我们移动较小的数字,直到小数点与尾数下端的位/数对齐,因为较小的数字可能会落在尾数的末尾,您可能希望保留一些粘性位或不保留一些粘性位

 1.23400*10^3
+5.67000*10^2
-------------
 1.23400*10^3
+0.56700*10^3
-------------
现在指数匹配,我们可以加上

 011000
 123400*10^3
+056700*10^3
------------
 180100*10^3
这就是答案1.8100*10^3

如果我们有车怎么办

5678+9876

 1 11000  
 5.67800*10^3
+9.87600*10^3
=============
15.55400*10^3
我们知道变量的大小,它们比尾数大一点(或者尾数被分成几个部分,这样我们就可以有一些执行的空间,在操作之间级联)

在二进制和十进制之间混合数据流,但如果在小数点上加1、2,在小数点上加0,则在小数点右侧加0。如果这不是零,那么右移一,从尾数的右端抛出位

   15.55400*10^3
&1110.00000
===========
    1.55540*10^4
&1110.00000
===========
现在它已经正常化了。在循环中执行不一定有效。对于直接正数加法,在最坏的情况下,只能有一个额外的位移位。所以你只需要检查一位的位置,如果零,没有移位。但对于负数的减法或加法,则从小数点上方的一堆非零位开始,而不仅仅是一位。你可能需要向左或向右移动,所以你必须搜索第一个非零数(这取决于搜索结果是正的还是负的,假设是正的),你可能需要向左或向右移动,每次移动减少指数,向右增加指数。当然,先做一个零检查

不是说你还不知道,我没有仔细阅读你的代码。但是如果你遵循一个通用算法,那么它就会起作用,例如,当你自己加上一个正数时,那么任何两个正数都会起作用


我建议用C语言或您最喜欢的高级语言实现,然后如果需要汇编(这里需要汇编吗?

不确定您的问题是什么,您可以简单地将尾数与
10
的等效值进行比较。添加1+1得到10.000。。。然后移到1.0000…,但1+2等于1.100。。。不能移动,因为我得到1.1100…=7.我想我需要找到方法来选择哪些结果需要改变,哪些不需要。你的意思是将尾数的第一部分(前20位)与10或11进行比较,如果它们相等,则移位,如果不相等,则不移位?尾数有53位,你需要保持这种方式。所以你需要测试的就是你是否得到一个54位的进位。你可以通过一个简单的按位
或者一个普通的比较来实现这一点。不是1位表示符号,11位表示指数,52位表示尾数吗?或者说是1。一开始也算吗?它存储在两个32位寄存器中,所以它被分成20位和32位两部分。仅检查前20位部分是否足够?所以我应该在尾数和寄存器之间使用按位的and,21位为1,如果它是1,那么将它移位?好的,这就行了。我在结果的尾数和0x00100000之间使用“andi”(这里是1.应该是),如果是1,则显示结果,如果不是1,则移动尾数。谢谢你,杰斯特。