0

I am trying to convert code that I have written in java into MIPS Assembly, however there seems to be an issue where I am losing the values calculated in a function when I return. Logically what I have written seems like it should work (to me at least).

For some context, a range will be entered by a user. In $s0 I store the smaller, $s1 the larger. I am checking for amicable numbers in the range.

Currently I am getting an infinite loop, I think it is because $s6 is getting reset to zero after a function call but I do not know how to resolve it. Any input would be greatly appreciated.

isAmicable:
li $s5, 0 #counter for number of amicable pairs
add $s6, $s0, $zero

amicableLoop:
bge $s6, $s1, final_output
jal isFactor
add $s3, $s4, $zero
move $s6, $s3 
jal isFactor
bne $s6, $s4, increment
bge $s6, $s3, increment
bge $s3, $s1, increment
j amicablePair

increment:
addi $s6, $s6, 1
j amicableLoop
    
isFactor:
li $s4, 0           # => The sum of all proper divisors of A
li $s2 , 1          # => start here with checks for devisors

sumLoop:
bge $s2, $s6, return_sum # while $s2 < $s1
rem $t0, $s6, $s2   # $t0 = $s1 % $s2
bne $t0, $0, while
addu $s4, $s4, $s2  # $s1 += $s2

while:
addi $s2, $s2, 1    # $s2++
j sumLoop                 

return_sum:
jr $ra          
  • Do you know where the infinite loop is occurring? – Ryan Millares Nov 22 '21 at 23:34
  • That is not a [mcve]. Also, use a debugger/simulator to single step the code and see where something gets corrupted. One possible problem is you don't save `$ra` before the `jal isFactor` so if your `isAmicable` is itself trying to return with `jr $ra` in code not shown that will indeed cause an endless loop. – Jester Nov 22 '21 at 23:35
  • @RyanMillares I believe the loop that is infinite is the ```amicableLoop```. From what I can see in the registers ```$s6``` is alternating between 0 and 1. I think this may be a result of it getting wiped or something when ```isFactor``` is called or returned, possibly both. – Greedy-Boogster Nov 23 '21 at 00:01
  • Note you also have a `move $s6, $s3`. Function calls don't change any registers except `$ra` unless the code you put into the function does. – Jester Nov 23 '21 at 00:05
  • You are using the s registers to share information between functions. While this can sometimes be efficient, it is non stadard register usage. Passing parameters in s registers is like passing parameters in global variables in C but even more error prone in assembly – Erik Eidt Nov 23 '21 at 00:09
  • @ErikEidt Ok that makes some sense to me. Could you possibly explain a standard method of parameter passing or direct me to a good resource on the subject? Thanks so much. – Greedy-Boogster Nov 23 '21 at 00:38
  • Optimized compiler output can be a useful example for simple functions that take args and return values. [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116). The standard MIPS calling convention passes args in $a0..a3, returns in `$v0` (and `$v1` for wider types). https://www.cs.umb.edu/cs641/MIPscallconvention came up when I googled for "mips calling convention", and from a quick skim looks sensible. (The danger with random guides / tutorials on the internet is that they can be wrong, course material like this is more often good.) – Peter Cordes Nov 23 '21 at 05:58
  • https://www.dyncall.org/docs/manual/manualse11.html – Erik Eidt Nov 23 '21 at 07:14

0 Answers0