0

Good Evening! I am trying to write a program in MIPS 32 that will compute n Choose k. In the code below, I am initializing the variables to compute 8 Choose 3. I am running the code in QtSPIM and getting the following errors:

Exception occurred at PC=0x00400028
  Unaligned address in inst/data fetch: 0x00000008
Memory address out of bounds
Exception occurred at PC=0x00400034
  Unaligned address in inst/data fetch: 0x00000003
Memory address out of bounds
Attempt to execute non-instruction at 0x004000b4

Does anybody have any idea what I can do to fix these errors? Thanks for your help.

.globl main

main:
    .text
    li $t2, 8               # n = 8
    lw $a0, 0($t2)          # store n into $a0
    syscall

    li $t3, 3               # k = 3
    lw $a1, 0($t3)          # store k into $a1
    syscall

    # branch options
    beq $a0, 0,   case0     # n = 0, 0Ck is always 0
    beq $a1, 0,   case1     # k = 0, nC0 is always 1
    beq $a0, $a1, case1     # n = k, nCk is always 1
    slt $t1, $a0, $a1       # n < k, nCk is always 0
    beq $t1, 0,   case0

    # n > k, nCk = n! / (k! * (n - k)!)
    jal pfctrlN             # compute n!, store in $v0
    jal pfctrlK             # compute k!, store in $v1

    sub $a2, $a0, $a1       # compute (n - k), store in $a2
    jal pfctrlNmK           # compute (n - k)!, store in $s0

    mul $t3, $v1, $s0       # compute (k! * (n - k)!), store in $t3
    div $s1, $v0, $t3       # compute n! / (k!*(n-k)!), store in $s1
    syscall

    slt $t1, $a1, $a0       # k < n, go to else
    beq $t1, 0,   else
    jr $ra

# Given n, in register $a0;
# calculates n! and stores the result in register $v0
pfctrlN: 
    sw   $ra, 4($sp)        # save the return address
    sw   $a0, 0($sp)        # save the current value of n
    addi $sp, $sp,   -8     # move stack pointer
    slti $t0, $a0,   2      # save 1 iteration, n = 0 or n = 1; n != 1
    beq  $t0, $zero, LoopN  # not, calculate n(n - 1)!
    addi $v0, $zero, 1      # n = 1; n != 1
    jr   $ra                # now multiply

LoopN:     
    addi $a0, $a0, -1       # n := n-1

    jal pfctrlN             # now (n - 1)!

    addi $sp, $sp, 8        # reset the stack pointer
    lw   $a0, 0($sp)        # fetch saved (n - 1)
    lw   $ra, 4($sp)        # fetch return address
    mul  $v0, $a0, $v0      # multiply n * (n - 1)
    jr   $ra                # return value n!

    # Given k, in register $a1;
    # calculates k! and stores the result in register $v1
    pfctrlK: 
    sw   $ra, 4($sp)        # save the return address
    sw   $a1, 0($sp)        # save the current value of k
    addi $sp, $sp,  -8      # move stack pointer
    slti $t0, $a1,  2       # save 1 iteration, k=0 or k=1; k!=1
    beq  $t0, $zero, LoopK  # not, calculate k(k-1)!
    addi $v1, $zero, 1      # k=1; k!=1
    jr   $ra                # now multiply

LoopK:     
    addi $a1, $a1, -1       # k := k-1

    jal pfctrlK             # now (k - 1)!

    addi $sp, $sp, 8        # reset the stack pointer
    lw   $a1, 0($sp)        # fetch saved (k - 1)
    lw   $ra, 4($sp)        # fetch return address
    mul  $v1, $a1, $v1      # multiply k * (k - 1)
    jr   $ra                # return value k!

# Given (n - k), in register $a2;
# calculates (n - k)! and stores the result in register $s0
pfctrlK: 
    sw   $ra, 4($sp)        # save the return address
    sw   $a2, 0($sp)        # save the current value of k
    addi $sp, $sp, -8       # move stack pointer
    slti $t0, $a2, 2        # save 1 iteration, (n - k) = 0 or (n - k) = 1; (n - k) != 1
    beq  $t0, $zero, LoopNK # not, calculate (n - k) * (n - k - 1)!
    addi $s0, $zero, 1      # (n - k) = 1; (n - k) != 1
    jr $ra                  # now multiply

LoopNK:     
    addi $a2, $a2, -1       # (n-k) := (n-k-1)

    jal pfctrlK             # now (k-1)!

    addi $sp, $sp, 8        # reset the stack pointer
    lw   $a2, 0($sp)        # fetch saved (n - k - 1)
    lw   $ra, 4($sp)        # fetch return address
    mul  $s0, $a2, $s0      # multiply (n - k) * (n - k - 1)
    jr   $ra                # return value (n - k)!

case0:
    li $a0, 0               # load immediate 0
    li $v0, 1               # display integer
    syscall
    .data

case1:
    li $a0, 1               # load immediate 1
    li $v0, 1               # display integer
    syscall
    .data

else:
    lw $a0, 0($s1)          # load nCk to display in $a0
    li $v0, 1               # display integer
    syscall
    .data

str:
    .asciiz "The odds are 1 in " 
mellerlite
  • 13
  • 1
  • 6

1 Answers1

1

This is not how you move the contents of one register into another:

lw $a0, 0($t2)          # store n into $a0

That instruction attempts to load a word from memory at the address specified by $t2 + 0 (which at that time equals 8). And you obviously can't just read from some random address like 8.

What you're looking for is probably the move instruction:

move $a0, $t2

Or, if you prefer to do it without any pseudo-instructions:

or $a0, $t2, $zero

Another issue is that you start off your code with two syscalls without initializing $v0. As you should know, the system call number goes into $v0.

I didn't look at the rest of the code, so there may be additional issues.

Michael
  • 57,169
  • 9
  • 80
  • 125