DualBall
DualBall

Reputation: 119

Address does not always increment by 4 in my MIPS program

The MIPS code below is supposed to write a function swapbigsmall that uses nested function findloc to find the location of the biggest and smallest numbers in this array, and swap them. But when I run the program, findloc increments the address incorrectly, causing v0 to potentially equal a number that isn't a multiple of 4, creating a bad address exception. How can I make sure that the address goes up by 4 at all times?

A: .word 90, 2, 93, 66, 8, 120, 121, 11, 33, 9

   .text
   .globl main

main: la $a0, A
      li $a1, 10

      jal swapbigsmall

done: li $v0, 10
      syscall

swapbigsmall:

      #Creates 3 spaces in stack,
      #then stores registers
      addi $sp, $sp, -12
      sw $ra, 8($sp)
      sw $ra, 4($sp)
      sw $ra, 0($sp)

      jal findloc  #Find smallest
      #Stores first result in s1
      #This is where exception occurs

      lw $s1, 0($v0)

      #Finds and stores largest
      li $a2, 1
      jal findloc
      lw $s2, 0($v0)
      
      #Swap code
      lw $t3, 0($s1)
      lw $t4, 0($s2)
      sw $t3, 0($s2)
      sw $t4, 0($s1)

      #Function conclusion
      lw $ra, 8($sp)
      lw $s2, 4($sp)
      lw $s1, 0($sp)
      add $sp, $sp, 12
      jr $ra

findloc:
      li $t0, 0

      #t9 = A[0]
      lw $t9, 0($a0)

      blt $a2, 1, LOOPSM

      #t1 = A[i]
      LOOPL: sll $t1, $t0, 2
      add $t1, $t1, $a0
      lw $t1, 0($t1)
      sgt $t2, $t9, $t1
      bne $t2, $0, LOOP_NEXTL

      addi $t9, $t1, 0
      sll $v0, $t0, 2
      LOOP_NEXTL: addi $t0, $t0, 1
      bne $t0, $a1, LOOPL

      j Exit

      LOOPSM: sll $t1, $t0, 2
      add $t1, $t1, $a0
      lw $t1, 0($t1)
      slt $t2, $t9, $t1
      bne $t2, $0, LOOP_NEXTSM

      addi $t9, $t1, 0
      sll $v0, $t0, 2
      LOOP_NEXTSM: addi $t0, $t0, 1
      bne $t0, $a1, LOOPL

      EXIT:

      jr $ra

Upvotes: 0

Views: 430

Answers (1)

Erik Eidt
Erik Eidt

Reputation: 26646

When you have bugs in assembly language, you should not assume you know where to focus or what's going wrong, as any little typo can have a dramatic or unexpected effect on the execution.

So, this is your opportunity to learn debugging.

The simulators have a single step feature, and you are supposed to use it to verify that each and every instruction does what it is supposed to do: what you expect it to do.

If any one instruction is wrong, the program won't work, it won't hang together.

  • Most instructions have an affect on the registers, so verify the proper effect you're expecting.
  • Other instructions affect the flow of control (sequencing of the instruction stream) so verify those for that.
  • And still, other instructions store to memory, so verify every store is storing the right thing at the right place.

You need to be especially careful of syscalls and jal calls.  If the called function, the callee, messes up the expectations of the caller, then the caller just won't work when the callee returns to the caller.

When you're making a call, verify every parameter.  When the call comes back, verify that the stack pointer has returned to its original position, and that all the registers have the expected values.  The registers are shared between caller and callee, so in the abstract sense, there's more to verify when stepping over a function call.  (Bugs in the callee that stomp on the caller's expectations can be found in the callee, though, to be clear; but sometimes just stepping over the call may give you quick insight as to what's being clobbered.)

Just like with C or other language debugging, we can debug "forwards" with single step or debug "backwards" using divide & conquer to find the point in the code where something went wrong.

I prefer forwards for new code, since the effect of mistakes won't compound.  All new code should be run forwards at least once.

However, working backwards with divide & conquer can sometimes work well to quickly find the cause of a fault — the idea being to go back in the code from a fault/exception and determine what when wrong.  Usually that is an iterative processes because working backwards the issues you find are not necessarily the bugs, and you have to keep working backwards to find the real bugs.

Upvotes: 1

Related Questions