Reputation: 2083
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:
so in the end how should look like good code? Beacuse i understand that the code in 1st post is wrong ?
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)
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
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