以下のコードで何が問題なのかを正確に把握しようとしています。
簡単な背景: このプログラムのアイデアは、プレーヤーが実行したシングルス、ダブルス、トリプルス、ホームラン、およびアウトの量に基づいて打率と長打率を計算することです。私がコードに対して実行しているテスト ケースの 1 つは、これらの値が天文学的であることを示しており、それらに何らかの追加を試みるたびに、コードは失敗します。double-point float を使用する必要があることは認識していますが (特に Out と Hit を追加する場合、最終的には 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