У меня проблема с проектом MIPS. Задача состоит в том, чтобы умножить двоичное число (double) на целое число со знаком без использования блока с плавающей запятой. Он почти работает, но для некоторых чисел возникает ошибка (например, float-123456789123456, int - 1). По ошибке я имею в виду, что после 7-го числа мой результат кажется отличным от правильного. Я подозреваю, что может возникнуть проблема с переносом некоторого бита во время процедуры (возможно, при добавлении $ high of mantissa2 и $ low of mantissa2). Я попытался исправить это, но до сих пор я понятия не имею, как это сделать. Пожалуйста, проверьте мой код и исправьте его, если это возможно.MIPS - IEEE binary64 (double) и целочисленное умножение со знаком
.data
text1: .asciiz "Enter double: "
text2: .asciiz "Enter integer: "
text3: .asciiz "Result: "
quest: .asciiz "\nIf you want to multiply enter 1, otherwise enter 0: "
num1a: .word 0 #multiplicand and result(sign exponent and first part of mantissa)
num1b: .word 0 #second part of the multiplicand and result(remaining part of mantissa)
num2: .word 0 #integer
.text
.globl input
input:
#print "Enter double: "
la $a0, text1
li $v0, 4
syscall
# saving input double into num1
li $v0, 7
syscall
swc1 $f0, num1b
swc1 $f1, num1a
#print "Enter integer: "
la $a0, text2
li $v0, 4
syscall
# saving input int into num2
li $v0, 5
syscall
sw $v0, num2
# loading data to registers
lw $t0, num1a
lw $t1, num1b
lw $t2, num2
#########################################################sign
sign:
move $t3, $t0
andi $t3, $t3, 0x80000000 #preserve sign, zero the rest
bgez $t2, extract #if less than zero we change the final sign and negate the value of integer
xori $t3, $t3, 0x80000000 #multiply signs (if integer is negative, then the sign is equal to $s0)
neg $t2, $t2 #absolute value of int
extract:
################################################checking for zero
or $t5, $t0, $t1 #if both part of double are equal to zero we skip all the calculation
beqz $t5, result_zero
beqz $t2, result_zero
###############################sign, exponent and mantissa
move $t7, $t0
andi $t7, $t7, 0x7FF00000 #extracting exponent to $t7
move $t8, $t0
andi $t8, $t8, 0x000FFFFF #extracting first part of mantissa
ori $t8, $t8, 0x00100000 #adding prefix one to mantissa
#remaining mantissa stays in register $t1
#########################################################
multiply:
########################multiplying mantissa part 1
multu $t8, $t2 #multiply mantissa1 by integer
mflo $t8 #low part of multiplication to $t8
mfhi $s1 #high part of multiplication to $s1
########################multiplying mantissa part 2
multu $t1, $t2 #mantissa part 2 multiplication
mflo $t1 #low part to $t1
mfhi $t0 #with overflow going to $t0
########################partial accumulation
addu $t8, $t8, $t0 #adding the high part of mantissa2 to result of low part of mantissa1
bgeu $t8, $t0, skip_add #if the result is less than any element we add 1 to mantissa1 high
addiu $s1, $s1, 1
######
skip_add:
bnez $s1, shift
bltu $t8, 0x00200000, result
shift: #else we shift 3 parts of mantissa and increment the the exponent
###extracting least significant bit of high mantissa1
sll $s2, $s1, 31 #copying least significant beat of $s1 to most significant bit in $s2
sll $t9, $t8, 31 #copying least significant beat of $s8 to most significant bit in $t9
######
srl $s1, $s1, 1 #shifting right mantisa part1 high
srl $t8, $t8, 1 #shifting right mantisa part1 low
or $t8, $t8, $s2 #copying least significant bit from mantissa1- high to most significant bit of mantissa1 low
srl $t1, $t1, 1 #shifting right mantisa part2
or $t1, $t1, $t9 #copying least significant bit from mantissa1 to most significant bit of mantissa2
######
addiu $t7, $t7, 0x00100000 #increment exponent by one
######
bnez $s1, shift #if mantissa1 high is greater than zero we continue
bgeu $t8, 0x00200000, shift #if mantissa1 low exceeds final mantissa space
result:
andi $t8, $t8, 0x000FFFFF #preserve mantissa, zero the rest(cut the prefix - one)
move $t0, $t3 #copy propoer sign
or $t0, $t0, $t7 #add exponent
or $t0, $t0, $t8 #add mantissa part1
b output
result_zero:
li $t0, 0
li $t1, 0
output:
sw $t0, num1a
sw $t1, num1b
#print "Result: "
la $a0, text3
li $v0, 4
syscall
lwc1 $f12, num1b
lwc1 $f13, num1a
#print double - the result
li $v0, 3
syscall
question:
la $a0, quest #Do you want to enter new numbers or finish?
li $v0, 4
syscall
li $v0, 5 #reads the answer (integer)
syscall
beq $v0, 1, input #if input =1, continue, if 0 finish, otherwise ask again
beqz $v0, fin
b question
fin:
li $v0, 10 #exit
syscall
Я думаю, что проблема может быть в этом разделе (умножить):
addu $t8, $t8, $t0 #adding the high part of mantissa2 to result of low part of mantissa1
bgeu $t8, $t0, skip_add #if the result is less than any element we add 1 to mantissa1 high
#addiu $s1, $s1, 1
######
skip_add:
bnez $s1, shift
bltu $t8, 0x00200000, result
Процесс добавления может вызвать выполнять. Я попытался обработать его с инструкцией, хранящейся в комментарии (addiu). Это означает, что если результат добавления двух беззнаковых чисел меньше одного из них, мы получим cary out и должны добавить 1 для регистрации $ s1, который содержит наиболее значимые часть мантиссы. Это не помогло.
Этот процесс будет легче, если вы можете предоставить информацию о том, какие ошибки вы испытываете и, если возможно, вы можете детализировать вопрос в какой-то части вашего кода , Учитывая, что, вероятно, очень мало людей, которые знают MIPS-ассемблер и IEEE с плавающей запятой и находятся на SO, чем больше информации вы предоставляете в своем вопросе, тем лучше. – dho
Я отредактировал сообщение. Надеюсь, мои мысли теперь легче понять. – Kornel
К счастью, проблема решена. В размножении действительно была ошибка. Однако проблема заключалась в использовании функции mult. Теперь это правильно и работает. Надеюсь, это поможет кому-то в будущем. – Kornel