1

我试图弄清楚在进行浮点加法时如何规范化 MIPS 中的有效数字。

假设你有 0.001*2^-1。在这种情况下,要规范化,您必须将有效位左移 3 并将指数减 3。

我将如何确定最高有效位回到标准化位置(在我之前的情况下,我怎么知道我在第三次移位后停止移位)?


更新:这是我目前正在使用的代码。给定两个输入(浮点数),程序应该进行半精度浮点加法,这就是我将单精度转换为半精度的原因。输出应该只是两个浮点数的总和

我认为问题在于正常化。

.data
ask_user_a:     .asciiz "Enter a decimal number (a): "
ask_user_b:     .asciiz "Enter a decimal number (b): "
sum:            .asciiz "a+b = "
error_out_of_range: .asciiz "Error: A number you entered is out of range! "
new_line:       .asciiz "\n"


.text
main:
#Ask user for the input a
la $a0, ask_user_a      # load the addr of ask_user_a into $a0.
li $v0, 4           # 4 is the print_string syscall.
syscall             # do the syscall.

#put input a into $s0
li $v0, 6           #6 for getting floating point numbers
syscall             # do the syscall
mfc1  $s0, $f0          #move floating point number to $s0

## ask user for the input b
la $a0, ask_user_b      # load the addr of ask_user_b into $a0.
li $v0, 4           # 4 is the print_string syscall.
syscall             # do the syscall.

#put input b into $s1
li $v0, 6           #6 for getting floating point numbers
syscall             # do the syscall
mfc1  $s1, $f0          #move floating point number to $s1

#extract parts for A
srl $t0, $s0, 31        #$t0 = Sign Bit A
sll $t1, $s0, 1
srl $t1, $t1, 24        
sub $t1, $t1, 127       #t1 = Exponent Bit A    
sll $t2, $s0, 9
srl $t2, $t2, 9         #t2 = Mantissa A
srl $t2, $t2, 13        #Truncate Mantissa
ori $t2, $t2, 0x800000
srl $t2, $t2, 12

#extract parts for B
srl $t5, $s1, 31        #$t5 = Sign Bit B
sll $t6, $s1, 1
srl $t6, $t6, 24        
sub $t6, $t6, 127       #t6 = Exponent Bit B
sll $t7, $s1, 9
srl $t7, $t7, 9         #t7 = Mantissa B
srl $t7, $t7, 13        #Truncate Mantissa
ori $t7, $t7, 0x800000
srl $t7, $t7, 12

##Check that exponent A is >16 and <-16, jump to error otherwise
blt $t1, -16, oor_error
bgt $t1, 16, oor_error

##Check that exponent B is >16 and <-16, jump to error otherwise
blt $t6, -16, oor_error
bgt $t6, 16, oor_error

j no_oor_error

#Throw error
oor_error:  
la $a0, error_out_of_range  # load the addr of ask_user_a into $a0.
li $v0, 4           # 4 is the print_string syscall.
syscall             # do the syscall.
j exit      

#There was no out of range error
no_oor_error:

#compare exponents
beq $t6, $t1, exponents_match
bgt $t6, $t1 expBgtexpA
sub $t8, $t6, $t1
srlv $t7, $t7, $t8
move $t6, $t1
j exponents_match
expBgtexpA:
sub $t8, $t1, $t6
srlv $t2, $t2, $t8
move $t1, $t6

exponents_match:
#If the signs are the same, add mants
#If the signs are diff, subtract mants
bne $t0, $t5, different_signs
add $t9, $t2, $t7
j significands_added
different_signs:
sub $t9, $t2, $t7


significands_added:
#normalize

#determine size
bne $t0, $t5, normalize_different_sign

normalize_same_sign:
andi $t8, $t9, 0x1000
beq $t8, $zero, done_normalize
srl $t9, $t9, 1
addi $t1, $t1, 1
j normalize_same_sign

normalize_different_sign:
andi $t8, $t9, 0x1000
beq $t8, $zero, done_normalize
sll $t9, $t9, 1
subi $t1, $t1, 1
j normalize_different_sign

done_normalize: 
#Check for overflow

##Convert back to float
sll $t0, $t0, 31        ##move sign to 32nd bit
addi $t1, $t1, 127      ##Add bias
sll $t1, $t1, 23        #move exponent to bits 24-31
sll $t9, $t9, 11        #move over mant
andi $t9, $t9, 0x3FFFFF
sll $t9, $t9, 1 

or $s2, $t0, $t1
or $s2, $s2, $t9

#Print the float
mtc1 $s2, $f12
li  $v0,    2   
syscall

exit:
#Exit Program
li $v0, 10          # syscall code 10 is for exit.
syscall             # make the syscall.
4

1 回答 1

1

此代码使用浮点输入数字的两个符号来选择用于规范化有效数的代码。如果符号相同(t0 等于 t5),它会尝试通过右移来进行归一化,直到结果有效数的第 12 位(0x1000)被设置。如果符号不同,它会尝试通过左移来进行归一化,直到第 12 位被设置。

这没有任何意义。

为了规范化有效数字,如果它太大而无法容纳所需的位数,则将其右移(并且它也应该根据需要进行四舍五入)。如果它太小以至于无法达到所需的位,则将其向左移动。(此时可能需要使用正有效位。如果对有效位执行的算术结果是负数,则确定有效位是否具有所需的位集会变得复杂。)

您可能会考虑用 C 或您熟悉和舒适的工作和调试语言来实现操作,然后转换为汇编。

于 2013-04-26T16:32:04.320 回答