2014-11-09 5 views
1

MIPS mult (multu) 또는 div (divu) 명령을 사용하지 않고 두 개의 32 비트 부호없는 정수를 곱하는 프로그램을 작성했습니다. 64-bit high word/low word 콤보처럼 multu 함수가 어떻게 생겼는지를 출력으로 보여주고 싶습니다. 나는 승수 그래서 제품의 오른쪽 인 모델을 사용하고있다 : 내 코드에서 현재멀티 또는 div를 사용하지 않고 MIPS 32 비트 부호없는 곱셈

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

내가 32에서 가능한 캐리 아웃 비트 돌보는하고 있다면 확실하지 오전 비트 추가.

어떤 정수 값을 선택하더라도 현재 "0 0"의 출력을 얻고 있습니다.

내 코드에서 가장 오른쪽 비트를 LSB (낮은 워드)라고하고, 대부분 MSB (상위 워드)를 남겼습니다.

내 코드 :

지금까지 내가 말할 수있는
.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 
+1

문제를 분리하기 위해 디버거/시뮬레이터를 사용 해본 적이 있습니까? – Jester

+0

PcSpim을 사용하여 프로그램을 시뮬레이트하는 중 ... 단일 스테핑을 사용해 보았지만 실제로 사용하는 방법을 알지 못했습니다. 그 외의 프로그램 자체에는 오류가 표시되지 않습니다. –

답변

3

, 심지어 알고리즘이 끊어집니다. 피승수를 왼쪽 (덧셈)으로, 오른쪽으로 계수 (비트 테스트 용)로 이동해야합니다. 제품을 옮겨서는 안됩니다. 또한 피승수는 64 비트로 확장해야하며 단어 경계에서 비트를 올바르게 전송하는 64 비트 시프트가 필요합니다.

.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 
+0

코드가 작동합니다. 나는 그것이 작동하는 이유를 이해하려고 노력하고 있습니다. 실수로 $ s2를 lw 제품, $ s1을 hw 곱셈기라고 부르는 실수를 범했습니다. 실제로 $ s2를 HW 제품, $ s1을 lw 배율이라고 부를 때 말이죠. 내가 준 알고리즘이 여기에 예시되어 있습니다. (http://imgur.com/jDIxH2d) 그 예에 따르면, 그것은 올바르게 작동해야합니다. 이것은 단지 구현이 틀렸음을 의미합니다. –

+0

그 알고리즘은 다르지만 물론 앞에서 말한 것이 아닙니다. P 어쨌든, 오른쪽 시프트는 높은 단어의 LSB를 낮은 단어의 MSB로 이동해야합니다. 마찬가지로 왼쪽 시프트가 반대말. 또한 캐리는 LSB가 아니라 MSB에 삽입해야합니다. – Jester