尝试使用不存在的内存MIPS

时间:2016-09-22 01:19:43

标签: assembly mips

所以我遇到了一些代码问题。我正在练习,对于我的生活,我似乎无法弄清楚我的代码有什么问题。我一直在 "尝试使用不存在的内存"在调用is_prime之后返回到第88行的函数/标签时似乎发生了错误。

任何帮助都会很感激,我花了好几个小时才能解决这个问题。

这是代码

#
# CONSTANT DECLARATIONS
#
PRINT_INT   = 1     # code for syscall to print integer
PRINT_STRING    = 4     # code for syscall to print a string
MIN     = 3     # minimum value to check
MAX     = 102       # max value to check

#
# DATA DECLARATIONS
#
    .data
newline:
    .asciiz "\n"
#
# MAIN PROGRAM
#
    .text
    .align  2
    .globl  main
main:
        addi    $sp,$sp,-8      # space for return address/doubleword aligned
        sw      $ra, 0($sp)     # store the ra on the stack

    jal find_primes

        #
        # Now exit the program.
    #
        lw      $ra, 0($sp) # clean up stack
        addi    $sp,$sp,8
        jr      $ra

#
# Name:     find_primes 
#
# Description:  find the prime numbers between 3 and 101 inclusive
# Arguments:    none
# Returns:  nothing
#

find_primes:
        addi    $sp,$sp,-40     # allocate stack frame (on doubleword boundary)
        sw      $ra, 32($sp)    # store the ra & s reg's on the stack
        sw      $s7, 28($sp)
        sw      $s6, 24($sp)
        sw      $s5, 20($sp)
        sw      $s4, 16($sp)
        sw      $s3, 12($sp)
        sw      $s2, 8($sp)
        sw      $s1, 4($sp)
        sw      $s0, 0($sp)


    li  $a0, MIN        # load imm 3 into $a0
loo:
    slti    $t0, $a0, MAX       # if $a0 < 102 set $t0 = 1, else 0
    beq $t0, $zero, fin     # exit when done
    j   is_prime        # goto func to determine if prime

    addi    $a0, $a0, 1     # **ERROR HAPPENS HERE**
    j   loo         # go back to loop
fin:


        lw      $ra, 32($sp)    # restore the ra & s reg's from the stack
        lw      $s7, 28($sp)
        lw      $s6, 24($sp)
        lw      $s5, 20($sp)
        lw      $s4, 16($sp)
        lw      $s3, 12($sp)
        lw      $s2, 8($sp)
        lw      $s1, 4($sp)
        lw      $s0, 0($sp)
        addi    $sp,$sp,40      # clean up stack
    jr  $ra

#
# Name:     is_prime 
#
# Description:  checks to see if the num passed in is prime
# Arguments:    a0  The number to test to see if prime
# Returns:  v0  a value of 1 if the number in a0 is prime
#           a value of 0 otherwise
#

is_prime:
        addi    $sp,$sp,-40     # allocate stackframe (doubleword aligned)
        sw      $ra, 32($sp)    # store the ra & s reg's on the stack
        sw      $s7, 28($sp)
        sw      $s6, 24($sp)
        sw      $s5, 20($sp)
        sw      $s4, 16($sp)
        sw      $s3, 12($sp)
        sw      $s2, 8($sp)
        sw      $s1, 4($sp)
        sw      $s0, 0($sp)

    li  $t2, 2          # load 2 into $t2
    div $a0, $t2        # divide $a0/$t2 -> hi = $a0%$t2
    mfhi    $t1         # load hi reg into $t1
    beq $t1, $zero, notPri  # if $t1 == 0, jump to notPrime
    li  $s0, MIN        # load 3 into $s0
loopPr: 
    slt $t0, $s0, $a0       # set $t0 to 1 if $s0 < $a0 else 0
    bne $t0, $zero, notPri  # jump to notPri if done looping
    div $a0, $s0        # divide to get mod $a0%$s0
    mfhi    $t1         # load hi reg value into $t1
    bne $t1, $zero, prime   # if $t1 != 0 it's prime
    addi    $s0, $s0, 1     # increment by 1 since not prime
    j   loopPr          # jump back to loop
notPri:
    li  $v0, 0          # $v0 = 0 if not prime
    j   dne         # jumpe to done if not prime
prime:
    li  $v0, 1          # $vi = 1 if prime
    j   print_number
dne:


        lw      $ra, 32($sp)    # restore the ra & s reg's from the stack
        lw      $s7, 28($sp)
        lw      $s6, 24($sp)
        lw      $s5, 20($sp)
        lw      $s4, 16($sp)
        lw      $s3, 12($sp)
        lw      $s2, 8($sp)
        lw      $s1, 4($sp)
        lw      $s0, 0($sp)
        addi    $sp,$sp,40      # clean up the stack
    jr  $ra

#
# Name;     print_number 
#
# Description:  This routine reads a number then a newline to stdout
# Arguments:    a0,the number to print
# Returns:  nothing
#
print_number:

        li  $v0,PRINT_INT
        syscall         #print a0

        la  $a0, newline
        li      $v0,PRINT_STRING
        syscall         #print a newline

        jr      $ra

1 个答案:

答案 0 :(得分:1)

您的代码存在一些问题。

  • 在您应该使用J时,您会在几个地方使用JAL。 (j is_primej print_number)。

  • print_number需要保存并恢复$a0,但不是。

  • 您的优质检查不足。如果X是奇数并且至少有一个Y 否 Y&lt; = X / 2,其中X%Y == 0(实际上您只需要检查Y <= sqrt(X),但除非你想写一个平方根函数X / 2应该足够好了。

PS:SPIM / MARS具有调试功能,可让您逐步执行指令。我建议你学会使用它。