MARS MIPS超出范围错误

编程入门 行业动态 更新时间:2024-10-08 02:19:59
本文介绍了MARS MIPS超出范围错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我是MIPS的新手,正在尝试一个程序在伪随机数组中查找最大数的值.但是,我在相当确定分配了适当内存等的行上收到超出范围的错误.给出了大多数框架代码,注释等,我只是试图编写find_max函数.我在给我留言的那条线上发表了评论.

I'm a newbie at MIPS and am attempting a program to find the value of the max number in a pseudo random array. However, I get an out of range error on a line I was fairly sure was allocated proper memory and such. Most of the skeleton code, comments, etc were given, I just am attempting to write the find_max function. I commented at the line giving me issues.

.data #data segment nl: .asciiz "\n" #ASCII for a new line separator: .asciiz ":" #string that seprates index from number msg1: .asciiz "The function returned " msg2: .asciiz "\nThe maximum value is " li $v0, $t5 #.asciiz msg3: .asciiz "\nThe address of the word is " #.asciiz li $v0, $t6 .align 2 # important for words buffer: .space 4096 # allocate space for 1K words .text # Code segment .globl main # declare main to be global main: addi $sp, $sp, -4 # allocate space on the stack for $s0 sw $s0, ($sp) # save $s0 li $s0, 16 # specify the size of the array, must be less than 1024 la $a0,name # load the address of "name" into $a0 li $v0,4 # system call, type 4, print an string, *$a0 syscall # call the "OS" # call la $a0, buffer move $a1, $s0 jal init_array # initialize the array with random values la $a0, buffer move $a1, $s0 jal print_array # call print. You can comment it out. # call your find_max function la $a0, buffer move $a1, $s0 lw $t0, 0($a0) la $t5, 0($a0) jal find_max # call find_max lw $v0, 0($t0) lw $v1, 0($t5) # add code to print the results # print the returned value la $a0, msg1 # print mssage 1 li $v0, 4 syscall # print the maximum value la $a0, msg2 # print mssage 2 li $v0, 4 syscall # print the address of the value (in hex). la $a0, msg3 # print mssage 3 li $v0, 4 syscall la $a0, nl # print end of line syscall # restore $s0. You can check $sp here to make sure the stack is maintained correctly. lw $s0, ($sp) # load $s0 addi $sp, $sp, 4 # restore $sp Exit: lw $v0, 0($t5) lw $v1, 0($t6) #li $v0,10 # System call, type 10, standard exit syscall # ...and call the OS find_max: # your implementation of find_max addi $sp, $sp, -16 # allocate space on the stack for four registers sw $s0, ($sp) # save $s0 sw $s1, 4($sp) # save $s1 sw $s2, 8($sp) # save $s2 sw $s3, 12($sp) # save $s3 # put your code below. # You can use temporary registers and $s0 to $s3 add $t1,$t1,1 # increment index i by 1 beq $t1,$s0,Exit # if all elements examined, quit sll $t2,$t2,2 # compute 4i in $t2 add $t2,$t2,$s1 # form address of A[i] in $t2 # THIS IS THE LINE GIVING PROBLEMS lw $t3,0($t2) # load value of A[i] into $t3 slt $t4,$t0,$t3 # maximum < A[i]? beq $t4,$zero,find_max # if not, repeat with no change addi $t0,$t3,0 # if so, A[i] is the new maximum addi $t5, $t2, 0 # restore saved registers. # make sure $sp is restored if you changed it. lw $s0, ($sp) lw $s1, 4($sp) lw $s2, 8($sp) lw $s3, 12($sp) addi $sp, $sp, 16 # restore $sp jr $ra # return to calling routine

推荐答案

好的,您必须编写的函数在计算数组索引时使用了错误的寄存器:

Okay, the function you had to write was using the wrong register when calculating the array index:

更改:

sll $t2,$t2,2 # compute 4i in $t2

进入:

sll $t2,$t1,2 # compute 4i in $t2

但是,您的函数还有一个严重错误.您将循环回到函数的开头,并在此过程中创建多个堆栈帧.我认为您可能已经在某种程度上意识到了这一点,这就是为什么您尝试通过跳转到Exit: [它是main的一部分]来补偿并退出该功能的原因.

But, your function also had a much more severe bug. You were looping back to the function beginning and creating multiple stack frames in the process. I think you may have realized this on some level which is why you tried to compensate and exit the function with a jump to Exit: [which is part of main].

找到第一个最大值后,您的计算功能也会过早终止. 不会继续遍历数组的其余部分以找到更好(即更大)的值.

Your calculation function would also terminate prematurely after finding the first maximum. It would not continue to loop through the remainder of the array to find better (i.e. larger) values.

还有许多其他错误.

我已经创建了您的程序的两个版本.一种带有有关错误的注释.并且,第二个版本已清理并可以正常工作.

I've created two versions of your program. One with annotations regarding the bugs. And, a second version, cleaned up, and working.

这里是带注释的版本[请原谅免费的样式清理]:

Here is the annotated version [please pardon the gratuitous style cleanup]:

.data # data segment nl: .asciiz "\n" # ASCII for a new line separator: .asciiz ":" # string that seprates index from number msg1: .asciiz "The function returned " # NOTE/BUG: these "li" are misplaced and have no meaning msg2: .asciiz "\nThe maximum value is " ###li $v0,$t5 msg3: .asciiz "\nThe address of the word is " # .asciiz # .asciiz ###li $v0,$t6 .align 2 # important for words ###buffer: .space 4096 # allocate space for 1K words buffer: .space 128 # allocate space for 1K words bufe: .text # Code segment .globl main # declare main to be global main: addi $sp,$sp,-4 # allocate space on the stack for $s0 sw $s0,($sp) # save $s0 # specify the size of the array, must be less than 1024 la $s1,bufe # get address of array end la $a0,buffer # get address of array subu $s1,$s1,$a0 # get byte length of array srl $s0,$s1,2 # get word count of array # NOTE/BUG: "name" is undefined ###la $a0,name # load the address of "name" into $a0 ###li $v0,4 # system call, type 4, print an string, *$a0 ###syscall # call the "OS" # call la $a0,buffer move $a1,$s0 jal init_array # initialize the array with random values la $a0,buffer move $a1,$s0 jal print_array # call print. You can comment it out. # call your find_max function la $a0,buffer move $a1,$s0 # NOTE/BUG: these serve no purpose lw $t0,0($a0) la $t5,0($a0) jal find_max # call find_max # NOTE/BUG: these serve no purpose lw $v0,0($t0) lw $v1,0($t5) # NOTE/BUG: the messages are printed below, but not the actual values # add code to print the results # print the returned value la $a0,msg1 # print mssage 1 li $v0,4 syscall # print the maximum value la $a0,msg2 # print mssage 2 li $v0,4 syscall # print the address of the value (in hex). la $a0,msg3 # print mssage 3 li $v0,4 syscall la $a0,nl # print end of line syscall # restore $s0. You can check $sp here to make sure the stack is maintained correctly. lw $s0,($sp) # load $s0 addi $sp,$sp,4 # restore $sp Exit: # NOTE/BUG: these serve no purpose lw $v0,0($t5) lw $v1,0($t6) # NOTE/BUG: the "li" should _not_ be commented out # li $v0,10 # System call, type 10, standard exit syscall # ...and call the OS # your implementation of find_max # # arguments: # a0 -- buffer address # a1 -- buffer count # # registers: # find_max: addi $sp,$sp,-16 # allocate stack space for four registers sw $s0,($sp) # save $s0 sw $s1,4($sp) # save $s1 sw $s2,8($sp) # save $s2 sw $s3,12($sp) # save $s3 # NOTE/BUG: the "max" value is never initialized to anything # put your code below. # You can use temporary registers and $s0 to $s3 # NOTE/BUG: $t1 has _not_ been initialized add $t1,$t1,1 # increment index i by 1 # NOTE/BUG: we just want to exit the function and _not_ the program -- this # bug is linked to the one below beq $t1,$s0,Exit # if all elements examined, quit # NOTE/BUG: this should be: # sll $t2,$t1,2 ###sll $t2,$t2,2 # compute 4i in $t2 sll $t2,$t1,2 # compute 4i in $t2 add $t2,$t2,$s1 # form address of A[i] in $t2 # THIS IS THE LINE GIVING PROBLEMS # NOTE/FIX: with the bugfix it won't lw $t3,0($t2) # load value of A[i] into $t3 slt $t4,$t0,$t3 # maximum < A[i]? # NOTE/BUG: this should _not_ loop back to find_max as that will create # _multiple_ stack frames -- it is because of _this_ bug that you # tried to compensate and leave this function by jumping to Exit beq $t4,$zero,find_max # if not, repeat with no change # NOTE/BUG: if you set a new maximum, you still have to loop back and _not_ # just exit this function. you may have found the _first_ maximum but there # could be others (i.e. larger values) addi $t0,$t3,0 # if so, A[i] is the new maximum addi $t5,$t2,0 # restore saved registers. # make sure $sp is restored if you changed it. lw $s0,($sp) lw $s1,4($sp) lw $s2,8($sp) lw $s3,12($sp) addi $sp,$sp,16 # restore $sp jr $ra # return to calling routine # init_array -- initialize array with random values # # arguments: # a0 -- array address # a1 -- array count # # registers: # t0 -- array address # t1 -- array count init_array: move $t0,$a0 # prevent value from being clobbered move $t1,$a1 # prevent value from being clobbered init_loop: li $v0,41 # syscall for random int li $a0,0 # specify which generator to use syscall sw $a0,0($t0) # store into array addiu $t0,$t0,4 # advance to next array element subi $t1,$t1,1 # decrement count bgtz $t1,init_loop # more to do? if yes, loop jr $ra # return # print_array -- initialize array with random values # # arguments: # a0 -- array address # a1 -- array count # # registers: # t0 -- array address # t1 -- array index print_array: move $t0,$a0 # prevent value from being clobbered li $t1,0 # array index print_array_loop: move $a0,$t1 # index value li $v0,1 # syscall for print int syscall la $a0,separator li $v0,4 syscall lw $a0,0($t0) # get array value li $v0,1 # syscall for print int syscall # output a newline la $a0,nl li $v0,4 syscall addiu $t0,$t0,4 # advance to next array element addi $t1,$t1,1 # increment index blt $t1,$a1,print_array_loop # more to do? if yes, loop jr $ra # return

这是固定的并且正在运行的版本.我添加了缺少的init_array和print_array函数以及结果打印.您得到的样板代码也有一些[小]错误,我已修复.我试图忠实于您的find_max代码,但不幸的是,我需要对其进行重构.

Here is the fixed and running version. I added the missing init_array and print_array functions as well as the results printing. The boilerplate code you were given also had some [minor] bugs that I fixed. I tried to remain faithful to your find_max code, but, unfortunately, I needed to refactor it.

还要注意以下事实:在mips ABI下,被调用函数可以将$v*,$a*和$t*用于 any 目的.因此,对于find_max而言,修改$s*寄存器从来都不是内部问​​题.

Also, make note of the fact that under the mips ABI, the $v*, $a*, and $t* can be used by the called function for any purpose. So, modifying the $s* registers was never an issue internally for find_max.

.data # data segment .align 2 # important for words ###buffer: .space 4096 # allocate space for 1K words buffer: .space 128 # allocate space for 1K words bufe: nl: .asciiz "\n" # ASCII for a new line separator: .asciiz ":" # string that seprates index from number msg1: .asciiz "The function returned " msg2: .asciiz "\nThe maximum value is " msg3: .asciiz "\nThe address of the word is " .text # Code segment .globl main # declare main to be global main: addiu $sp,$sp,-4 # allocate space on the stack for $s0 sw $s0,($sp) # save $s0 # specify the size of the array, must be less than 1024 la $s0,bufe # get address of array end la $a0,buffer # get address of array subu $s0,$s0,$a0 # get byte length of array srl $s0,$s0,2 # get word count of array la $a0,buffer move $a1,$s0 jal init_array # initialize the array with random values la $a0,buffer move $a1,$s0 jal print_array # call print. You can comment it out. # call your find_max function la $a0,buffer move $a1,$s0 jal find_max # call find_max move $t0,$v0 # save address move $t1,$v1 # save value # add code to print the results # print the maximum value la $a0,msg2 # print mssage 2 li $v0,4 syscall move $a0,$t1 # get max value li $v0,1 syscall la $a0,nl li $v0,4 syscall # print the address of the value (in hex). la $a0,msg3 # print mssage 3 li $v0,4 syscall move $a0,$t0 # get address of max value li $v0,34 syscall la $a0,nl li $v0,4 syscall # restore $s0. You can check $sp here to make sure the stack is maintained correctly. lw $s0,($sp) # load $s0 addiu $sp,$sp,4 # restore $sp li $v0,10 # exit program syscall # ...and call the OS # your implementation of find_max # # RETURNS: # v0 -- address of maximum value # v1 -- maximum value # # arguments: # a0 -- buffer address # a1 -- buffer count # # registers: # t0 -- current value # t1 -- test/temporary find_max: addiu $sp,$sp,-16 # allocate stack space for four registers sw $s0,($sp) # save $s0 sw $s1,4($sp) # save $s1 sw $s2,8($sp) # save $s2 sw $s3,12($sp) # save $s3 # put your code below. # You can use temporary registers and $s0 to $s3 # initialize the maximum value from the first element move $v0,$a0 # get the address lw $v1,0($a0) # get the value find_max_loop: addiu $a0,$a0,4 # advance buffer pointer subi $a1,$a1,1 # decrement remaining count blez $a1,find_max_done # more to do? if no, return lw $t0,0($a0) # get current value slt $t1,$v1,$t0 # got new maximum? beqz $t1,find_max_loop # no, loop move $v0,$a0 # set new maximum pointer move $v1,$t0 # set new maximum value j find_max_loop # try next value # restore saved registers. # make sure $sp is restored if you changed it. find_max_done: lw $s0,($sp) lw $s1,4($sp) lw $s2,8($sp) lw $s3,12($sp) addiu $sp,$sp,16 # restore $sp jr $ra # return to calling routine # init_array -- initialize array with random values # # arguments: # a0 -- array address # a1 -- array count # # registers: # t0 -- array address # t1 -- array count init_array: move $t0,$a0 # prevent value from being clobbered move $t1,$a1 # prevent value from being clobbered # seed the generator li $v0,40 li $a0,0 li $a1,0x12345678 syscall init_loop: li $v0,41 # syscall for random int li $a0,0 # specify which generator to use syscall sw $a0,0($t0) # store into array addiu $t0,$t0,4 # advance to next array element subi $t1,$t1,1 # decrement count bgtz $t1,init_loop # more to do? if yes, loop jr $ra # return # print_array -- initialize array with random values # # arguments: # a0 -- array address # a1 -- array count # # registers: # t0 -- array address # t1 -- array index print_array: move $t0,$a0 # prevent value from being clobbered li $t1,0 # array index print_array_loop: move $a0,$t1 # index value li $v0,1 # syscall for print int syscall la $a0,separator li $v0,4 syscall lw $a0,0($t0) # get array value li $v0,1 # syscall for print int syscall # output a newline la $a0,nl li $v0,4 syscall addiu $t0,$t0,4 # advance to next array element addi $t1,$t1,1 # increment index blt $t1,$a1,print_array_loop # more to do? if yes, loop jr $ra # return

更多推荐

MARS MIPS超出范围错误

本文发布于:2023-10-23 02:25:28,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1519468.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:错误   MARS   MIPS

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!