assembly 我有问题,试图添加一个获取中位数功能在我的MIPS程序

eulz3vhy  于 2023-01-09  发布在  其他
关注(0)|答案(1)|浏览(94)

我编写了以下MIPS程序,从用户处获取10个整数,然后输出(最小值、最大值和平均值),然后添加指令以获取中值(从第72行开始,从注解# Calculate median开始),每次输入10个数字后运行程序时,我都会遇到以下异常(0x004000e0处的运行时异常:提取地址未在字边界0x10010005上对齐)。

.data 

array: .space 40 #10 X 4(byte)
prompt: .asciiz "Please enter 10 random numbers :\n"
sort: .asciiz "\nThe descending order of the numbers are :\n"
sum: .asciiz "\n\nThe Sum of all numbers are : "
average: .asciiz "\n\nThe average of all the number is : "
max: .asciiz "\n\nThe maximum number is : "
min: .asciiz "\n\nThe minimum number is : "
space: .asciiz " "
dot: .asciiz "."
median: .asciiz "\n\nThe median of the numbers is: "

.text

.globl main

main:
li $v0, 4
la $a0, prompt #print out prompt
syscall

la $s0, array #load array into register s0

LoopInput:
li $v0, 5 #input numbers
syscall
sw $v0, 0($s0) # $v0 = i
addi $s0, $s0,4 #move array position
addi $t0, $t0,1 #loop array where i++
bne $t0, 10,LoopInput #for(t1=0;t1!=10;t1++) g

la $s0, array
sub $t0, $t0,$t0

Sorting: #sorting number from big to small
beq $t1,9, ConSort #if t1=9, go to conSort
lw $s1, 0($s0) #load the number in the first location into $s1
lw $s2, 4($s0) #load the number in the second location into $s2
addi $s0, $s0, 4 #update array position
addi $t1, $t1, 1 #move array position #for(s1=0;s1!=9;s1++)
bge $s1, $s2, Sorting #if s1>s2, back to sorting
sw $s1, 0($s0) #exchange position
sw $s2, -4($s0)
bne $t1, 9, Sorting #if t1!=9, go back to sorting

ConSort:
la $s0, array #continue sort with the same way
addi $t0, $t0, 1 #keep sorting the other numbers
addi $t1, $t0, 0
bne $t0, 9, Sorting #if t0!=9, go back to sorting

li $v0, 4 #print out prompt
la $a0, sort
syscall
la $s0, array
sub $t0, $t0, $t0

PrintSort:
li $v0, 1 #print sorting
lw $a0, 0($s0)
syscall
li $v0, 4
la $a0, space #print out prompt
syscall
addi $s0, $s0, 4
addi $t0, $t0, 1
bne $t0, 10, PrintSort #if t0!=10, go to printsort

# Calculate median
li $t4, 5 # t4 = 5
la $s0, array # s0 points to the beginning of the array
add $s0, $s0, $t4 # s0 points to the middle element of the array
lw $t5, 0($s0) # t5 = array[5]
li $v0, 4 # print message
la $a0, median # message to print: "The median of the numbers is: "
syscall
move $a0, $t5 # print median value
li $v0, 1 # print integer
syscall

sub $t0, $t0, $t0
sub $t1, $t1, $t1
sub $t2, $t2, $t2
sub $t3, $t3, $t3
la $s0, array #load array number to $s0
li $v0, 4 #print out prompt
la $a0, sum
syscall

SumA:
lw $t2, 0($s0) #load first $t2 to $s0
addi $s0, $s0,4 #update the array[s0] position
add $t3, $t2, $t3 #t3=t2+t3
addi $t0, $t0, 1 #t0= i++
bne $t0, 10, SumA #if t0!=10, go back to SumAll

move $a0, $t3 #move $t3 to $a0
li $v0, 1 #print out the sum of all numbers
syscall

li $v0, 4

la $a0, average #print out prompt
syscall

addi $t6, $t6, 10 #t6=10
div $t3, $t6 #t3=t3/10
mflo $s5 #move quotient to s5
mfhi $s3 #move remainder to s3

move $a0, $s5 #move s5 to a0
li $v0, 1 #print out quotient
syscall

li $v0, 4
la $a0, dot #print out dot
syscall

move $a0, $s3 #move s3to a0
li $v0, 1 #print out remainder
syscall
la $s0, array #load array into s0
li $v0, 4 #print out prompt
la $a0, max
syscall

lw $t5, 0($s0) #load number in array into t5
move $a0, $t5 #move t5 to a0
li $v0, 1 #print out number
syscall

li $v0, 4 #print out prompt
la $a0, min
syscall

lw $t4 , 36($s0) #load number in array into t4
move $a0, $t4 #move t4 to a0
li $v0, 1 #print out number
syscall

li $v0, 10
syscall #end of program

从我对试图在一个没有在字边界上对齐的地址访问内存所引起的问题的理解。

n9vozmp4

n9vozmp41#

与C不同的是,汇编不会自动缩放指针算术/数组索引。看起来你明白这一点,因为你总是使用addi $s0,$s0,4来前进到数组中的下一个条目,因为int在32位MIPS硬件上占用4个字节。你唯一出错的地方是这里:

li $t4, 5 # t4 = 5
la $s0, array # s0 points to the beginning of the array
add $s0, $s0, $t4 # s0 points to the middle element of the array

假设你想要中间的值,这实际上需要你使用li $t4, 20,我将使用下面的图表来解释这个,我将假设你的数组位于内存地址0x00000000(不是这样,但这只是为了使演示更容易一些。)例如,如果用户输入数字2、3、4、5、6、7、8、9、10和11,这是数组排序后在内存中的样子(假设使用小端CPU)

0x00000000: 02 00 00 00
0x00000004: 03 00 00 00
0x00000008: 04 00 00 00
0x0000000C: 05 00 00 00
0x00000010: 06 00 00 00
0x00000014: 07 00 00 00 (this is what you will get when you load from offset 20)
0x00000018: 08 00 00 00
0x0000001C: 09 00 00 00
0x00000020: 0A 00 00 00 (ten)
0x00000024: 0B 00 00 00 (eleven)

现在,因为有奇数个值,所以你需要取中间两个值的平均值,所以你要从0($s0)-4($s0)加载,把它们相加,然后右移一次。

相关问题