我们的任务是在MIPS中实现精细的按位除法算法。
基本上在精炼程序中,我们将被除数加载到64位寄存器的LO位中,其余部分将累积在HI位中,这些位最初都设置为0。
然后我们只测试HI(我们的余数)> =除数。 如果我们的累积余数目前不是> =除数,我们只需移动整个寄存器并用0填充。这是我们商的开始。当红利位移入HI时,我们最终会遇到HI> 1的情况。 = 除数。然后我们将从HI中减去除数,将整个寄存器向左移,然后用1填充。
简而言之,我们可以简单地继续向左移动所有64位,当HI <1时填充0。除数,从HI中减去除数,当HI> 1时用1填充。 =除数。
在我们的作业中,我们要编写一个程序,从控制台接受两个正数(16位有符号数字),将前者除以后者。
我将除数设为$ t0,其余为$ t3,红利为$ t2。 $ t3和$ t2都是16位,它们一起配对成32位寄存器。不知何故,我的程序返回一个非常有趣的商:最不重要的几个位是正确的,但最重要的是总是1;不知怎的,我无法摆脱1,无论我向左移多少位。例如,如果红利是1000,通过向左移动,而不是获得0001 0000,我实际得到10000 - MSB总是1.有人可以看看我的程序并给我一些建议吗?非常感谢!
.data
GETA: .asciiz "Enter Dividend: "
GETB: .asciiz "Enter Divisor: "
QT: .asciiz "Quotient = "
RM: .asciiz "Remainder = "
NL: .asciiz "\n"
.text
main:
li $v0, 4 #Prompt for a dividend
la $a0, GETA
syscall
li $v0, 5 #Read dividend from user
syscall
move $t2, $v0 #dividend in $t2
li $v0, 4 #Prompt for a divisor
la $a0, GETB
syscall
li $v0, 5 #Read divisor from user
syscall
move $t0, $v0 #divisor in $t0
addi $t4, $zero, 17 #counter
j Loop
Loop:
slt $t1, $t3, $t0 #if remainder < divisor, $t1=1
beq $t1, $zero, subroutine #remainder >= divisor, $t1=0
#if remainder < divisor
sll $t3, $t3, 1 #shift remainder by to left by 1
andi $t5, $t2, 32768 #get MSB of $t2
bne $zero, $t5, updateRemainder1 #MSB of $t2 is 1
#MSB of $t2 is 0
sll $t2, $t2, 1 #shift dividend to left by 1
addi $t4, $t4, -1 #decrease counter by 1
bne $zero, $t4, Loop
j Exit
subroutine:
sub $t3, $t3, $t0 #subtract divisor from remainder
sll $t3, $t3, 1 #shift remainder by to left by 1
andi $t5, $t2, 32768 #get MSB of $t2
bne $zero, $t5, updateRemainder2 #MSB of $t2 is 1
#MSB of $t2 is 0
sll $t2, $t2, 1 #shift dividend to left by 1
ori $t2, $t2, 1 #fill in LSB of $t2 with a 1
addi $t4, $t4, -1 #decrease counter by 1
bne $zero, $t4, Loop
j Exit
updateRemainder1:
ori $t3, $t3, 1 #set LSB of remainder to 1
sll $t2, $t2, 1 #shift dividend to left by 1
addi $t4, $t4, -1 #decrease counter by 1
bne $zero, $t4, Loop
j Exit
updateRemainder2:
ori $t3, $t3, 1 #set LSB of remainder to 1
sll $t2, $t2, 1 #shift dividend to left by 1
ori $t2, $t2, 1 #fill in LSB of $t2 with a 1
addi $t4, $t4, -1 #decrease counter by 1
bne $zero, $t4, Loop
j Exit
Exit:
sub $t2, $t2, 524288
li $v0, 4 #print out output line
la $a0, QT
syscall
li $v0, 1 #print out quotient
move $a0, $t2
syscall
li $v0, 4 #print out new line
la $a0, NL
syscall
li $v0, 4 #print out output line
la $a0, RM
syscall
li $v0, 1 #print out remainder
move $a0, $t3
syscall
li $v0, 10
syscall