不使用MULT或DIV MIPS的32位无符号乘法 [英] MIPS 32-bit unsigned multiplication without using mult or div

查看:323
本文介绍了不使用MULT或DIV MIPS的32位无符号乘法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在一个程序做两个32位无符号整数乘法,而无需使用MIPS MULT(multu)或DIV(DIVU)命令。
我所要的输出看起来就像是怎么multu功能将作为64位高字/低字组合。
我已经用一个模型,其中所述乘数是产品的右手侧为这样:

 为(i = 0; I< 32;我++)
{
   如果LSB(乘数)== 1
   {
       LH产品+ =被乘数;
   }
   右移产品乘数1;
}

目前在我的code我不确定如果我从32位加法妥善照顾的可能进位位。

我目前得到的0的输出,无论我选择什么样的整数值进行操作。

在我的code我打电话最右位的LSB(低位字),最左边的MSB(高位字)。

我的code:

 。数据    promptStart:.asciiz这prrogram确实AXB不使用MULT或DIV
           木屐:.asciiz请输入第一个数字(乘数):
           getB:.asciiz请输入第二个数字(乘数):          空间:.asciiz         结果:.asciiz产品,用我的计划是:
         mipMult:.asciiz的产品,采用的MIP multu是:       底线:.asciiz\\ n。文本主要:
    #欢迎屏幕
    为print_string李$#v0,4 code
    LA $ A0,promptStart#$点A0提示字符串
    系统调用#打印提示
    为print_string李$#v0,4 code
    LA $ A0,底线#$点A0提示字符串
    系统调用#打印提示    #prompt的被乘数
    为print_string李$#v0,4 code
    LA $ A0,木屐#$点A0提示字符串
    系统调用#打印提示    #acquire被乘数
    李$#v0,5 code表示read_int
    系统调用#得到用户一个int - >在$ V0返回
    此举$ S0,$#V0产生的INT移动到$ S0    此举$ S4,$ S0被乘数在multu使用的#copy    #prompt的乘数
    为print_string李$#v0,4 code
    LA $ A0,getB#$点A0提示字符串
    系统调用#打印提示    #acquire倍增
    李$#v0,5 code表示read_int
    系统调用#得到用户一个int - >在$ V0返回
    此举$ S1,$#V0产生的INT移动到$ S0    此举$ S5,$ S1乘数multu使用的#copy    日航MyMult
    j打印MyMult:    #$ S2 - > LW产品,$ S1 - >硬件乘法器,$ S0 - >被乘数    BEQ $ S1,$ 0,完成#如果乘数= 0 - > MULT给出0
    BEQ $ S0,$ 0完成    此举$ T0,$ 0个#initialize'反'= 31
    加$ T0,T0 $ 31    移动$ S2,$ 0 #initialize产品= 0    LOOPOUT:
        BEQ $ T0,$ 0做#LOOP检查        安迪$ T1,$ S1,1 LSB #Stores(MSB?)的$ S1在$ T1
        BNE $ T1,$ 0 loopIn#检查如果LSB为等于1
        SRL $ S1,S1 $ 1
        SRL $ S2,S2 $,1 #right转向产品和放大器;乘数        加$ T0,$ T0,-1#柜台=柜台-1
        ĴLOOPOUT    loopIn:
        阿杜$ S2,S2 $,$ S0 #Lw产品($ S2 / $ S1)+ =被乘数($ S0)
        sltu $ t2时,$ S2,$ S0 #catch进位输出(0或1),并存储在$ t2的        SRL $ S1,S1 $ 1
        SRL $ S2,S2 $,1 #right转向亲plier..how节省的LSB $ S2?        #将开展出$ t2到LSB的产品$ S2
        阿杜$ S2,S2 $,$ T0 #IS这个权利?        阿杜$ T0,$ T0,-1#柜台=柜台-1
        ĴLOOPOUT    完成:
        JR $ RA打印:
    #打印结果字符串
    为print_string李$#v0,4 code
    LA $ A0,结果#$点A0串
    系统调用#打印结果字符串    #打印出的结果
    李$#v0,1 code表示print_int
    此举$ A0,$ S2#把在$ A0
    系统调用#打印出结果    为print_string李$#v0,4 code
    LA $ A0,空间#$点A0串
    系统调用#打印结果字符串    李$#v0,1 code表示print_int
    此举$ A0,$#S1摆在$ A0
    系统调用#打印出结果
    #打印换行
    为print_string李$#v0,4 code
    LA $ A0,底线#$点A0串
    系统调用#打印换行doMult:
使用MULT #Do相同的计算
    multu $ S4,S5 $
    MFHI $ T0
    MFLO $ T1    为print_string李$#v0,4 code
    LA $ A0,mipMult#$点A0串
    系统调用    #打印出的结果
    李$#v0,1 code表示print_int
    移动$ A0,$#T0投入$ A0高
    系统调用#打印出结果    为print_string李$#v0,4 code
    LA $ A0,空间#$点A0串
    系统调用#打印结果字符串    #打印出的结果
    李$#v0,1 code表示print_int
    移动$ A0,$ T1#$中把A0低
    系统调用#打印出结果    #打印换行
    为print_string李$#v0,4 code
    LA $ A0,底线#$点A0串
    系统调用#打印换行    #全部完成,谢谢!
    李$#v0,10 code出境
    系统调用#出口程序


解决方案

据我所知,甚至你的算法被破解。你应该移位被乘数向左(为加),和因子向右(用于位测试)。该产品不应该被移动。此外,被乘数需要扩展到64位,你需要一个64位的转变,跨越字边界正确传输位。

 。数据    promptStart:.asciiz这个项目确实AXB不使用MULT或DIV
           木屐:.asciiz请输入第一个数字(乘数):
           getB:.asciiz请输入第二个数字(乘数):          空间:.asciiz         结果:.asciiz产品,用我的计划是:
         mipMult:.asciiz的产品,采用的MIP multu是:       底线:.asciiz\\ n。文本主要:
    #欢迎屏幕
    为print_string李$#v0,4 code
    LA $ A0,promptStart#$点A0提示字符串
    系统调用#打印提示
    为print_string李$#v0,4 code
    LA $ A0,底线#$点A0提示字符串
    系统调用#打印提示    #prompt的被乘数
    为print_string李$#v0,4 code
    LA $ A0,木屐#$点A0提示字符串
    系统调用#打印提示    #acquire被乘数
    李$#v0,5 code表示read_int
    系统调用#得到用户一个int - >在$ V0返回
    此举$ S0,$#V0产生的INT移动到$ S0
    此举$ S5,$#S0在被乘数向multu使用拷贝    #prompt的乘数
    为print_string李$#v0,4 code
    LA $ A0,getB#$点A0提示字符串
    系统调用#打印提示    #acquire倍增
    李$#v0,5 code表示read_int
    系统调用#得到用户一个int - >在$ V0返回
    此举$ S1,$#V0产生的INT移动到$ S0    此举$ S6,S1 $#乘数multu使用的副本    日航MyMult
    j打印MyMult:
    移动$ S3,$ 0#LW产品
    移动$ S4,$ 0#硬件产品    BEQ $ S1,$ 0完成
    BEQ $ S0,$ 0完成    移动$ S2,$ 0#被乘数到64位扩展循环:
    安迪$ T0,S0 $ 1#LSB(乘数)
    BEQ $ T0,$ 0#旁边则跳过零
    阿杜$ S3,S3 $,$ S1#LW(产品)+ = LW(被乘数)
    sltu T0,$ S3,$ S1#抓进位输出(0或1)
    阿杜$ S4,S4 $,$#T0硬件(产品)+ =进
    阿杜$ S4,S4 $,$ S2#硬件(产品)+ = HW(被乘数)
下一个:
    #转移被乘数左
    SRL $ T0,$ S1,31#复制从LW位HW
    SLL $ S1,S1 $ 1
    SLL $ S2,S2 $ 1
    阿杜$ S2,S2 $,$ T0    SRL $ S0,S0 $ 1#转向乘数权
    BNE $ S0,$ 0环完成:
    JR $ RA打印:
    #打印结果字符串
    为print_string李$#v0,4 code
    LA $ A0,结果#$点A0串
    系统调用#打印结果字符串    #打印出的结果
    李$#v0,1 code表示print_int
    此举$ A0,$#S4把在$ A0
    系统调用#打印出结果    为print_string李$#v0,4 code
    LA $ A0,空间#$点A0串
    系统调用#打印结果字符串    李$#v0,1 code表示print_int
    此举$ A0,$#S3摆在$ A0
    系统调用#打印出结果
    #打印换行
    为print_string李$#v0,4 code
    LA $ A0,底线#$点A0串
    系统调用#打印换行doMult:
使用MULT #Do相同的计算
    multu $ S5,S6 $
    MFHI $ T0
    MFLO $ T1    为print_string李$#v0,4 code
    LA $ A0,mipMult#$点A0串
    系统调用    #打印出的结果
    李$#v0,1 code表示print_int
    移动$ A0,$#T0投入$ A0高
    系统调用#打印出结果    为print_string李$#v0,4 code
    LA $ A0,空间#$点A0串
    系统调用#打印结果字符串    #打印出的结果
    李$#v0,1 code表示print_int
    移动$ A0,$ T1#$中把A0低
    系统调用#打印出结果    #打印换行
    为print_string李$#v0,4 code
    LA $ A0,底线#$点A0串
    系统调用#打印换行    #全部完成,谢谢!
    李$#v0,10 code出境
    系统调用#出口程序

I have been working on a program does multiplication of two 32-bit unsigned integers without using the MIPS mult(multu) or div(divu) commands. I want the output to look just like how the multu function would, as a 64-bit high word/low word combo. I have been using a model where the multiplier is the right hand side of the product as so:

for (i=0; i<32; i++)
{
   if LSB(multiplier)==1
   {
       LH product += multiplicand;
   }
   right shift product-multiplier 1;
}

Currently in my code I am unsure if I am taking care of the possible carry-out bit from the 32-bit addition properly.

I am currently getting an output of "0 0" no matter what integer values I choose to operate on.

In my code I am calling the right most bit the LSB(low word), left most the MSB(high word).

My code:

.data

    promptStart:    .asciiz "This prrogram does AxB without using mult or div"
           getA:    .asciiz "Please enter the first number(multiplicand): "
           getB:    .asciiz "Please enter the second number(multiplier): "

          space:    .asciiz " "

         result:    .asciiz "The product, using my program is: "
         mipMult:   .asciiz "The product, using MIPs multu is: "

       endLine: .asciiz "\n"

.text

main:
    #"welcome" screen
    li  $v0,4           # code for print_string
    la  $a0,promptStart     # point $a0 to prompt string
    syscall             # print the prompt


    li  $v0,4           # code for print_string
    la  $a0,endLine     # point $a0 to prompt string
    syscall             # print the prompt

    #prompt for multiplicand
    li  $v0,4           # code for print_string
    la  $a0,getA        # point $a0 to prompt string
    syscall             # print the prompt

    #acquire multiplicand
    li  $v0,5           # code for read_int
    syscall             # get an int from user --> returned in $v0
    move    $s0,$v0         # move the resulting int to $s0

    move    $s4,$s0         #copy of multiplicand to use in multu

    #prompt for multiplier
    li  $v0,4           # code for print_string
    la  $a0,getB        # point $a0 to prompt string
    syscall             # print the prompt

    #acquire multiplier
    li  $v0,5           # code for read_int
    syscall             # get an int from user --> returned in $v0
    move    $s1,$v0         # move the resulting int to $s0

    move    $s5,$s1         #copy of multiplier to use in multu 

    jal MyMult
    j   print

MyMult:

    #$s2 -> lw product, $s1 -> hw multiplier, $s0 -> multiplicand

    beq $s1, $0, done       # if multiplier=0--> mult gives 0
    beq $s0, $0, done

    move    $t0, $0         #initialize 'counter'= 31
    add $t0, $t0, 31

    move    $s2, $0         #initialize product = 0

    loopOut:
        beq $t0, $0, done   #loop check

        andi    $t1, $s1, 1 #Stores LSB(MSB?) of $s1 in $t1
        bne $t1, $0, loopIn #check if LSB is equal to 1
        srl $s1, $s1, 1
        srl $s2, $s2, 1 #right shift product & multiplier

        add $t0, $t0,-1 # counter = counter -1
        j   loopOut

    loopIn:
        addu    $s2, $s2, $s0   #Lw product($s2/$s1)+= multiplicand($s0)
        sltu    $t2, $s2, $s0   #catch carry-out(0 or 1) and stores in $t2      

        srl $s1, $s1, 1
        srl $s2, $s2, 1 #right shift pro-plier..how to save LSB of $s2?

        #add carry-out $t2 to LSB of product $s2
        addu    $s2, $s2, $t0   #Is this right?

        addu    $t0, $t0,-1 # counter = counter -1
        j   loopOut

    done:
        jr $ra

print:
    # print result string
    li  $v0,4           # code for print_string
    la  $a0,result      # point $a0 to string
    syscall             # print the result string

    # print out the result
    li  $v0,1           # code for print_int
    move    $a0,$s2         # put result in $a0
    syscall             # print out result

    li  $v0,4           # code for print_string
    la  $a0,space       # point $a0 to string
    syscall             # print the result string

    li  $v0,1           # code for print_int
    move    $a0,$s1         # put result in $a0
    syscall             # print out result


    # print the line feed
    li  $v0,4           # code for print_string
    la  $a0,endLine     # point $a0 to string
    syscall             # print the linefeed

doMult:
#Do same computation using Mult
    multu   $s4, $s5
    mfhi    $t0
    mflo    $t1

    li  $v0,4           # code for print_string
    la  $a0,mipMult     # point $a0 to string
    syscall 

    # print out the result
    li  $v0,1           # code for print_int
    move    $a0,$t0         # put high in $a0
    syscall             # print out result

    li  $v0,4           # code for print_string
    la  $a0,space       # point $a0 to string
    syscall             # print the result string

    # print out the result
    li  $v0,1           # code for print_int
    move    $a0,$t1         # put low in $a0
    syscall             # print out result

    # print the line feed
    li  $v0,4           # code for print_string
    la  $a0,endLine     # point $a0 to string
    syscall             # print the linefeed

    # All done, thank you!
    li  $v0,10          # code for exit
    syscall             # exit program

解决方案

As far as I can tell, even your algorithm is broken. You should be shifting the multiplicand to the left (for the addition), and the factor to the right (for bit testing). The product should not be shifted. Also, the multiplicand needs to be extended to 64 bits, and you need a 64 bit shift that correctly transfers bits across the word boundary.

.data

    promptStart:    .asciiz "This program does AxB without using mult or div"
           getA:    .asciiz "Please enter the first number(multiplicand): "
           getB:    .asciiz "Please enter the second number(multiplier): "

          space:    .asciiz " "

         result:    .asciiz "The product, using my program is: "
         mipMult:   .asciiz "The product, using MIPs multu is: "

       endLine: .asciiz "\n"

.text

main:
    #"welcome" screen
    li  $v0,4           # code for print_string
    la  $a0,promptStart # point $a0 to prompt string
    syscall             # print the prompt


    li  $v0,4           # code for print_string
    la  $a0,endLine     # point $a0 to prompt string
    syscall             # print the prompt

    #prompt for multiplicand
    li  $v0,4           # code for print_string
    la  $a0,getA        # point $a0 to prompt string
    syscall             # print the prompt

    #acquire multiplicand
    li  $v0,5           # code for read_int
    syscall             # get an int from user --> returned in $v0
    move    $s0,$v0     # move the resulting int to $s0
    move    $s5,$s0     # copy of multiplicand to use in multu

    #prompt for multiplier
    li  $v0,4           # code for print_string
    la  $a0,getB        # point $a0 to prompt string
    syscall             # print the prompt

    #acquire multiplier
    li  $v0,5           # code for read_int
    syscall             # get an int from user --> returned in $v0
    move    $s1,$v0     # move the resulting int to $s0

    move    $s6,$s1     # copy of multiplier to use in multu

    jal MyMult
    j   print

MyMult:
    move $s3, $0        # lw product
    move $s4, $0        # hw product

    beq $s1, $0, done
    beq $s0, $0, done

    move $s2, $0        # extend multiplicand to 64 bits

loop:
    andi $t0, $s0, 1    # LSB(multiplier)
    beq $t0, $0, next   # skip if zero
    addu $s3, $s3, $s1  # lw(product) += lw(multiplicand)
    sltu $t0, $s3, $s1  # catch carry-out(0 or 1)
    addu $s4, $s4, $t0  # hw(product) += carry
    addu $s4, $s4, $s2  # hw(product) += hw(multiplicand)
next:
    # shift multiplicand left
    srl $t0, $s1, 31    # copy bit from lw to hw
    sll $s1, $s1, 1
    sll $s2, $s2, 1
    addu $s2, $s2, $t0

    srl $s0, $s0, 1     # shift multiplier right
    bne $s0, $0, loop

done:
    jr $ra

print:
    # print result string
    li  $v0,4           # code for print_string
    la  $a0,result      # point $a0 to string
    syscall             # print the result string

    # print out the result
    li  $v0,1           # code for print_int
    move    $a0,$s4     # put result in $a0
    syscall             # print out result

    li  $v0,4           # code for print_string
    la  $a0,space       # point $a0 to string
    syscall             # print the result string

    li  $v0,1           # code for print_int
    move    $a0,$s3     # put result in $a0
    syscall             # print out result


    # print the line feed
    li  $v0,4           # code for print_string
    la  $a0,endLine     # point $a0 to string
    syscall             # print the linefeed

doMult:
#Do same computation using Mult
    multu   $s5, $s6
    mfhi    $t0
    mflo    $t1

    li  $v0,4           # code for print_string
    la  $a0,mipMult     # point $a0 to string
    syscall

    # print out the result
    li  $v0,1           # code for print_int
    move    $a0,$t0         # put high in $a0
    syscall             # print out result

    li  $v0,4           # code for print_string
    la  $a0,space       # point $a0 to string
    syscall             # print the result string

    # print out the result
    li  $v0,1           # code for print_int
    move    $a0,$t1         # put low in $a0
    syscall             # print out result

    # print the line feed
    li  $v0,4           # code for print_string
    la  $a0,endLine     # point $a0 to string
    syscall             # print the linefeed

    # All done, thank you!
    li  $v0,10          # code for exit
    syscall             # exit program

这篇关于不使用MULT或DIV MIPS的32位无符号乘法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆