我正试图弄清楚下面的代码到底出了什么问题。
快速背景:此计划的想法是根据玩家执行的单打,双打,三重,本垒打和外出的数量来计算击球平均值和扣球百分比。我针对代码运行的一个测试用例的值是天文数字,每当我尝试添加它们时,代码都会失败。我意识到我需要使用双点浮点数(特别是在添加Outs和Hits时,最终应该使用数字31,500,032而不是存储26,207,920),但我不确定如何使用我的代码来处理这样做。有什么建议吗?
# test with three batters, both average and slugging percentage
# First batter has no hits, but does have outs
# Second batter has hits and outs, with realistic values
# Third hitter has large values for some of the hits and for the
# outs. This means the hits and outs *have* to be converted from int's
# to float's in order to get the right answer.
.data
mainNumBatters:
.word 3
mainBatter1:
.word 0, 0, 0, 15, 0 # player with no atBats
mainBatter2:
.word 101 # singles
.word 22 # doubles
.word 4 # triples
.word 423 # outs
.word 10 # home runs
mainBatter3:
.word 8000000 # singles
.word 22 # doubles
.word 500000 # triples
.word 23000000 # outs
.word 10 # home runs
mainNewline:
.asciiz "\n"
mainBatterNumber:
.asciiz "Batter number: "
mainBattingAverage:
.asciiz "Batting average: "
mainSluggingPercentage:
.asciiz "Slugging percentage: "
.text
main:
# Function prologue -- even main has one
subu $sp, $sp, 24 # allocate stack space -- default of 24 here
sw $fp, 0($sp) # save frame pointer of caller
sw $ra, 4($sp) # save return address
addiu $fp, $sp, 20 # setup frame pointer of main
# for (i = 0; i < mainNumBatters; i++)
# compute batting average
# compute slugging average
la $s0, mainNumBatters
lw $s7, 0($s0) # $s7 = number of batters
addi $s6, $zero, 0 # $s6 = i = 0
la $s0, mainBatter1 # $s0 = addr of current batter's stats
mainLoopBegin:
slt $t0, $s6, $s7 # $t0 = i < number of batters
beq $t0, $zero, mainDone
la $a0, mainBatterNumber
addi $v0, $zero, 4
syscall
addi $a0, $s6, 1
addi $v0, $zero, 1
syscall
la $a0, mainNewline
addi $v0, $zero, 4
syscall
lw $a1, 0($s0) # $a1 = singles
lw $a2, 4($s0) # $a2 = doubles
lw $a3, 8($s0) # $a3 = triples
lw $s5, 16($s0) # $s5 = home runs
lw $s4, 12($s0) # $s4 = outs
sw $s4, -4($sp) # put outs at top of average's stack
sw $s5, -8($sp) # put homeruns 2nd fm top of average's stack
addi $a0, $zero, 1 # $a0 = 1 = compute batting average
jal average
# Print the average
mtc1 $v0, $f12 # get result fm $v0 before we print string
la $a0, mainBattingAverage
addi $v0, $zero, 4
syscall
addi $v0, $zero, 2 # print the average
syscall
la $a0, mainNewline
addi $v0, $zero, 4
syscall
syscall
# do it again for the slugging percentage
lw $a1, 0($s0) # $a1 = singles
lw $a2, 4($s0) # $a2 = doubles
lw $a3, 8($s0) # $a3 = triples
lw $s5, 16($s0) # $s5 = home runs
lw $s4, 12($s0) # $s4 = outs
sw $s4, -4($sp) # put outs at top of average's stack
sw $s5, -8($sp) # put homeruns 2nd fm top of average's stack
addi $a0, $zero, 2 # $a0 = 1 = compute batting average
jal average
# Print the slugging percentage
mtc1 $v0, $f12 # get result fm $v0 before we print string
la $a0, mainSluggingPercentage
addi $v0, $zero, 4
syscall
addi $v0, $zero, 2 # print the average
syscall
la $a0, mainNewline
addi $v0, $zero, 4
syscall
syscall
addi $s6, $s6, 1 # i++
addi $s0, $s0, 20 # $s0 = addr of next batter's stats
j mainLoopBegin
mainDone:
# Epilogue for main -- restore stack & frame pointers and return
lw $ra, 4($sp) # get return address from stack
lw $fp, 0($sp) # restore frame pointer for caller
addiu $sp, $sp, 24 # restore frame pointer for caller
jr $ra # return to caller
.data
printHitsOuts:
.asciiz "Outs: "
printHitsSingles:
.asciiz "Singles: "
printHitsDoubles:
.asciiz "Doubles: "
printHitsTriples:
.asciiz "Triples: "
printHitsHomeruns:
.asciiz "Homeruns: "
printHitsNewline:
.asciiz "\n"
.text
printHits:
# Function prologue
addiu $sp, $sp, -28 # allocate stack space
sw $fp, 0($sp) # save frame pointer of caller
sw $ra, 4($sp) # save return address
sw $a0, 8($sp) # save $a0 thru $a3
sw $a1, 12($sp)
sw $a2, 16($sp)
sw $a3, 20($sp)
addiu $fp, $sp, 24 # setup frame pointer of average
# print the outs
la $a0, printHitsOuts
addi $v0, $zero, 4
syscall
lw $a0, 24($sp) # the outs are at the top of our stack
addi $v0, $zero, 1
syscall
la $a0, printHitsNewline
addi $v0, $zero, 4
syscall
# print the singles
la $a0, printHitsSingles
addi $v0, $zero, 4
syscall
lw $a0, 8($sp)
addi $v0, $zero, 1
syscall
la $a0, printHitsNewline
addi $v0, $zero, 4
syscall
# print the doubles
la $a0, printHitsDoubles
addi $v0, $zero, 4
syscall
addi $a0, $a1, 0
addi $v0, $zero, 1
syscall
la $a0, printHitsNewline
addi $v0, $zero, 4
syscall
# print the triples
la $a0, printHitsTriples
addi $v0, $zero, 4
syscall
addi $a0, $a2, 0
addi $v0, $zero, 1
syscall
la $a0, printHitsNewline
addi $v0, $zero, 4
syscall
# print the homeruns
la $a0, printHitsHomeruns
addi $v0, $zero, 4
syscall
addi $a0, $a3, 0
addi $v0, $zero, 1
syscall
la $a0, printHitsNewline
addi $v0, $zero, 4
syscall
printHitsDone:
# Epilogue for average -- restore stack & frame pointers and return
lw $ra, 4($sp) # get return address from stack
lw $fp, 0($sp) # restore frame pointer for caller
addiu $sp, $sp, 28 # restore frame pointer for caller
jr $ra # return to caller
# Your code goes below this line
# $s1 = Homeruns = $f6
# Outs = $f8
# atBats = $f10
# $a1 = Singles = $f12
# $a2 = Doubles = $f14
# $a3 = Triples = $f16
# $f20 = Slugging Percentage (Not Divided)
# $f18 = Hits
# $f2 = Batting Average
average:
# Function prologue
addiu $sp, $sp, -56 # allocate stack space
sw $fp, 0($sp) # save frame pointer of caller
sw $ra, 4($sp) # save return address
sw $a0, 8($sp) # 1 or 2 ; 1, batting average ; 2, slugging percentage
sw $a1, 12($sp) # Number of Singles
sw $a2, 16($sp) # Number of Doubles
sw $a3, 20($sp) # Number of Triples
addiu $fp, $sp, 24 # setup frame pointer of average
sw $s0, 28($sp)
sw $s1, 32($sp)
sw $s2, 36($sp)
sw $s3, 40($sp)
sw $s4, 44($sp)
# Grab Outs and Homeruns from Top of Main stack
lw $s0, 52($sp) # Number of Outs
lw $s1, 48($sp) # Number of Homeruns
# Convert Everything to Floating
mtc1 $s1, $f6 # $f6 = Homeruns
mtc1 $s0, $f8 # $f8 = Outs
mtc1 $a1, $f12 # $f12 = Singles
mtc1 $a2, $f14 # $f14 = Doubles
mtc1 $a3, $f16 # $f16 = Triples
# Calculate Hits ($f18)
add.s $f18, $f12, $f14 # Add Singles and Doubles
add.s $f18, $f18, $f16 # Add Triples
add.s $f18, $f18, $f6 # Add Homeruns
#Calculate atBats ($f10)
add.s $f10, $f8, $f18 # Add Outs and Hits
#Check if Batting or Slugging is to be computed
add $s4, $zero, $zero
addi $s4, $s4, 2
beq $s4, $a0, averageSlugging
averageBatting:
#Skip when atBats = 0
mfc1 $s3, $f10
beqz $s3, averageFinish
#Calculate Batting Average ($f4)
div.s $f4, $f18, $f10 # Divide Hits by atBats
j averageFinish
averageSlugging:
#Skip when atBats = 0
mfc1 $s3, $f10
beqz $s3, averageFinish
#Calculate Slugging Average ($f0)
add.s $f20, $f12, $f14 # $f20 = Singles + Doubles
add.s $f20, $f20, $f14 # $f20 = Singles + Doubles*2
add.s $f20, $f20, $f16 # $f20 = Singles + Doubles*2 + Triples
add.s $f20, $f20, $f16 # $f20 = Singles + Doubles*2 + Triples*2
add.s $f20, $f20, $f16 # $f20 = Singles + Doubles*2 + Triples*3
add.s $f20, $f20, $f6 # $f20 = Singles + Doubles*2 + Triples*3 + Homeruns
add.s $f20, $f20, $f6 # $f20 = Singles + Doubles*2 + Triples*3 + Homeruns*2
add.s $f20, $f20, $f6 # $f20 = Singles + Doubles*2 + Triples*3 + Homeruns*3
add.s $f20, $f20, $f6 # $f20 = Singles + Doubles*2 + Triples*3 + Homeruns*4
div.s $f4, $f20, $f10 # Divide Hits by atBats
averageFinish:
#Call printHits
add $a0, $a1, $zero # $a0 = Singles
add $a1, $a2, $zero # $a1 = Doubles
add $a2, $a3, $zero # $a2 = Triples
add $a3, $s1, $zero # $a3 = Homeruns
sw $s0, -4($sp) # Outs at the top of printHits Stack
jal printHits
#Prepare for Return
mfc1 $v0, $f4
mtc1 $zero, $f4 # $f4 = 0
# Epilogue for average -- restore stack & frame pointers and return
lw $ra, 4($sp) # get return address from stack
lw $fp, 0($sp) # restore frame pointer for caller
lw $a0, 8($sp) # 1 or 2 ; 1, batting average ; 2, slugging percentage
lw $a1, 12($sp) # Number of Singles
lw $a2, 16($sp) # Number of Doubles
lw $a3, 20($sp) # Number of Triples
lw $s0, 28($sp)
lw $s1, 32($sp)
lw $s2, 36($sp)
lw $s3, 40($sp)
lw $s4, 44($sp)
addiu $sp, $sp, 56 # restore frame pointer for caller
jr $ra # return to caller
答案 0 :(得分:2)
你的问题是你正在混合整数和浮点算术。 您的输入数字表示为整数。 然后将它们放入浮点寄存器并与它们一起操作。但是,您没有将它们转换为浮点表示。
对于小数字,加法和除法工作正常(你只添加或划分尾数)。但是,当任何算术运算中涉及的数字的指数不同时,操作将产生错误的结果。
在执行浮点运算之前,您应该做的是将数字的整数表示转换为浮点表示。
在MIPS中,这是通过cvt.s.w
指令完成的。
所以基本上,您必须在每个mtc1
发布之后添加其中一个转换:
# Convert Everything to Floating
mtc1 $s1, $f6 # $f6 = Homeruns
cvt.s.w $f6, $f6 # (convert to floating point)
mtc1 $s0, $f8 # $f8 = Outs
cvt.s.w $f8, $f8
mtc1 $a1, $f12 # $f12 = Singles
cvt.s.w $f12, $f12
mtc1 $a2, $f14 # $f14 = Doubles
cvt.s.w $f14, $f14
mtc1 $a3, $f16 # $f16 = Triples
cvt.s.w $f16, $f16