Kamil Witkowski
Kamil Witkowski

Reputation: 2083

restoring Division in MIPS Assembly

I am trying to write a program in MIPS assembly language that implements the restoring division algorithm.

I found very good example of my task that I have to do, the thread is old and closed, and I don't fully understand it.

http://forums.extremeoverclocking.com/showthread.php?p=2693342

I have few questions:

  1. so in the end how should look like good code? Beacuse i understand that the code in 1st post is wrong ?

  2. What is good algorithm of restoring Division?

    " You are dividing two numbers: a/b = c, remainder = d

    Register A = a Register B = b Register P = a "connected" set of two registers (64 bit register)

    1. Shift the double regiaster (P,A) one bit left
      • use zero sign extension for unsigned values
      • force MSB(P) to fall off the upper end
    2. Subtract b from P
    3. If the result is < 0 LSB(A) = 0 else LSB(A) = 1
    4. If result is negative P = P + b

    Repeat n times (for n-bit values) Contents of register A = a/b Contents of register P = remainder(a/b)"

is this good algorithm? can someone write it in much simplier english? Cause i don;t understand it.

addition:

code from 1-st post:

.data
    GETA:           .asciiz "Enter A "
    GETB:           .asciiz "Enter B "
    QMSG:           .asciiz "Q = "
    RMSG:           .asciiz "R = "
    NL:             .asciiz "\n"
    ERR:            .asciiz "Divide by zero error\n"
    left:           .word 1
    right:          .word 1
.text
.globl main
main:
    # Prompt for an integer A: divisor
    li $v0, 4                            
    la $a0, GETA                           
    syscall                                     
    # Read A from user
    li $v0, 5                              
    syscall                              

    move $t0, $v0                         
    # Prompt for an integer B: dividend
    li $v0, 4                             
    la $a0, GETB                         
    syscall     

    # Read B from user
    li $v0, 5                               
    syscall                               
    move $a1, $v0                          

# Initialize quotient register to zero
# Initialize left half of Divisor regisiter with divisor
# Initialize remainder register with the dividend (right aligned)
# 1. Remainder = Remainder - Divisor
#    Remainder >= 0 goto Step 2a.
#    Remainder < 0 goto Step 2b.
# 2a. Shift quotient register to the left, setting rightmost bit to 1
# 2b. Restore the original value bu Remainder = Remainder + Divisor
#     Shift quotient register to the left setting new LSB to zero
# 3. Shift divisor register to the right 1 bit
# < 33 repitions, goto step 1
# >= 33 repititions, print result 
#
# Register usage:
# $a0 = divisor
# $a1 = dividend
# $a2 = quotient
# $a3 = remainder
# $t4 = counter of 33 repetitions
# $t0 = divisor (temp)
initialize:
    li $a2, 0                               # $a2 = quotient = 0
    swl $t0, left
    lwl $a0, left                           # $a0 = left half of divisor
    swr $a1, right
    lwr $a3, right                          # $a3 = remainder = $a2
    li $t4, 33                              # $t4 = counter = 33

step_one:
    sub $a3, $a3, $a0
    bge $a3, $zero, step_two_a
    blt $a3, $zero, step_two_b

step_two_a:
    #slt $a2, $zero, $a2
    sll $a2, $a2, 1
    ori $a2, $a2, 1
    j step_three

step_two_b:

    add $a3, $a3, $a0
    sll $a2, $a2, 1

step_three:

    sra $a0, $a0, 1

step_four:

    addi $t4, $t4, -1
    bge $t4, $zero, step_one
    beq $t4, $zero, print_result

print_result:

    li $v0, 4                  
    la $a0, QMSG                     
    syscall                   

    move $a0, $a2                      
    li $v0, 1                         
    syscall                            

    li $v0, 4                          
    la $a0, NL                         
    syscall                           

    li $v0, 4                    
    la $a0, RMSG                     
    syscall                     

    move $a0, $a3                      
    li $v0, 1                          
    syscall                            

    li $v0, 4                          
    la $a0, NL                         
    syscall

    j exit_program                    

exit_program:
    li $v0, 10                       
    syscall

probably missing something like

Code:

 # shift the double register (P,A) one bit left
    slt $t2, $v0, $zero                  # store MSB of hi
    sll $v0, $v0, 1                      # shift hi left 1 bit
    slt $t3, $v1, $zero                  # store MSB of lo
    or $v0, $v0, $t2                     # move MSB of lo into LSB of hi
    sll $v1, $v1, 1                      # shift lo left 1 bit

how should like fine code??

Upvotes: 2

Views: 2235

Answers (1)

Amith G
Amith G

Reputation: 1

Here's the corrected code for restoring division with dvide by zero error handling:

.data
    GETA:           .asciiz "Enter Dividend: "
    GETB:           .asciiz "Enter Divisor: "
    QMSG:           .asciiz "Quotient = "
    RMSG:           .asciiz "Reminder = "
    NL:             .asciiz "\n"
    ERR:            .asciiz "Divide by zero error\n"
    left:           .word 1
    right:          .word 1
.text
.globl main

# Register usage:
# $a1 = Divisor
# $a2 = Quotient(Q)
# $a3 = Reminder
# $t4 = No. of bits = 31
# $s0 = A

main:

# Prompt for an integer A: dividend
    li $v0, 4                            
    la $a0, GETA                          
    syscall
                                       
# Read A from user
    li $v0, 5                              
    syscall                              

    move $a2, $v0                  
                   
# Prompt for an integer B: divisor
    li $v0, 4                            
    la $a0, GETB                        
    syscall    

# Read B from user
    li $v0, 5                              
    syscall                              
    move $a1, $v0                                        

#initialize:
    li $t4, 30                  # $t4 = counter = 30 = no of loops
    addi $s0, $s0, 0            # A=0

# Exception handling:
    beq $a1,$zero,zeroerror     #Raises an exception when a/0 is encountered
   
#step1: To shift Q and A
loop:
    andi $t5, $a2, 1073741824   # extracting the msb-1 of divident(quotient)
    srl $t5, $t5, 30            # move msb-1 to right
    sll $a2, $a2, 1             # shift Q by 1 position
    andi $a2, $a2, 2147483647   # to neglect 32nd po
    sll $s0, $s0, 1             # shift A by 1 position
    or $s0, $s0, $t5            # add the msb of Q to A
   
#step2: A = A - M
    addi $s5, $s0, 0            # storing A
    sub $s0, $s0, $a1           # A=A-M
   
#step3: Compare the msb of A to obtain lsb of Q
    andi $t5, $s0, 2147483648   # get the msb of A
    beq $t5, $zero, cond1       # if A[msb] = 0, jump to cond1
    j cond2                     # if A[msb] = 1, jump to cond2

#cond1
cond1:  ori $a2, $a2, 1         # if a[msb] = 0, q[lsb]=1
    j condover

#cond2
cond2: andi $a2, $a2, 4294967294# if A[msb] = 1, q[lsb]=0
    addi $s0, $s5, 0            # restoring A
    j condover

condover:
    addi $t4, $t4, -1           # n =n-1
    bge $t4, $zero, loop        # loop for n times
   

print_result:

    li $v0, 4                  
    la $a0, QMSG                    
    syscall                  

    move $a0, $a2                      
    li $v0, 1                        
    syscall                            

    li $v0, 4                          
    la $a0, NL                        
    syscall                          

    li $v0, 4                    
    la $a0, RMSG                    
    syscall                    

    move $a0, $s0                      
    li $v0, 1                          
    syscall                            

    li $v0, 4                          
    la $a0, NL                        
    syscall

    j exit_program                    

exit_program:
    li $v0, 10                      
    syscall
zeroerror:
# Show the Error on console
    li $v0, 4                            
    la $a0, ERR                          
    syscall
    j exit_program  

Check out this video for more info on debugging: Debug MIPS code Efficiently

Check out this video for detailed explanation of the algorithm : Restoring division algorithm explained

Upvotes: 0

Related Questions