Continuous Arithmetic Overflow

78 views Asked by At

I have tried changing so much of this code but I keep getting either neverending Arithmetic Overflow warnings or 'Bad address in data/stack' errors. I can't seem to get it properly right! Any insight is welcome! I am trying to implement a sudoku board and these are the instructions for this function: Given a pointer to a Sudoku board, this function should return an integer indicating how many of the cells in the board have been solved. The state of the board should be unmodified. Each Sudoku cell occupies ten bytes in all. And with each cell occupying 10 bytes, the whole board occupies 810 bytes of memory.

Any insight?

# a0: pointer to board
# v0: number of solved cells

count_solved_cells:
    li $v0, 0               # Initialize count to 0
    la $s0, board           # Load the address of the board to $s0
    li $t0, 81              # Initialize loop counter

count_cells_loop:
    jal is_cell_solved      # Check if the current cell is solved
    addi $v0, $v0, 1        # Increment count regardless of cell status

    addi $s0, $s0, 10        # Move to the next cell (each cell is 10 bytes)
    addi $t0, $t0, -1        # Decrement loop counter
    bnez $t0, count_cells_loop  # If not reached the end of the board, continue the loop

    jr $ra
2

There are 2 answers

4
Reda Bourial On

It seems like there's an issue in your loop where you're incrementing the count regardless of the cell status. You should only increment the count if the cell is solved. Also, you need to properly handle the return value from the is_cell_solved function.

Here's a modified version of your code:

# a0: pointer to board
# v0: number of solved cells

count_solved_cells:
    li $v0, 0               # Initialize count to 0
    la $s0, board           # Load the address of the board to $s0
    li $t0, 81              # Initialize loop counter

count_cells_loop:
    jal is_cell_solved      # Check if the current cell is solved
    beq $v0, $zero, not_solved  # If the cell is not solved, jump to not_solved

    addi $v0, $v0, 1        # Increment count only if the cell is solved

not_solved:
    addi $s0, $s0, 10        # Move to the next cell (each cell is 10 bytes)
    addi $t0, $t0, -1        # Decrement loop counter
    bnez $t0, count_cells_loop  # If not reached the end of the board, continue the loop

    jr $ra

This modification includes a branch (not_solved) to skip the increment of the count if the cell is not solved. Ensure that the is_cell_solved function properly returns a value indicating whether the cell is solved or not.

0
Erik Eidt On

@Reda Bourial already pointed out that perhaps you need your counting in this function to be conditional rather than unconditional.

The other 6 logic errors are of the calling convention, i.e. related to function calling that we don't see in C or other languages, since the compilers take care of these details for us.  (We presume that your intent is to follow the standard calling convention as would be the idea with most instructional assignments, since it doesn't make educational sense to attempt calling convention deviation/optimization without knowing first the standard approaches and why they are used.)

Function calling on a register machine is one of the most difficult things for beginners to get right, not because it is fundamentally deep or intertwined but there are several different rules, each simple but together a lot to remember and about when to use which rule.

A logic error does not necessarily cause an infinite loop or a program crash, because the surrounding code (callers and callees) do not test those logics to see if bad or not.  And since you aren't showing any code but the one function we cannot say about some of those errors.

The function calling logic errors are:

  1. $ra being used for a second purpose without its value being preserved for later use by this function's own epilogue.
  2. $s0 being used in violation of calling convention rules — without preservation and restoration, which is a violation in calling convention contract with this function's caller(s).
  3. $v0 is being using also in violation of the calling convention rules, by expecting the callee to have preserved these legitimately call-clobbered registers.
  4. $t0 same as for (3.)
  5. The function comments document that $a0 is an incoming parameter, but the function ignores this parameter (presumably in favor of the la instead, though we don't see it as probably due to missing computation of actual arguments for the callee).
  6. Just as function formal parameters are not being properly used in this function, the actual arguments are also surely not being set up properly for the callee is_cell_solved.

With the first error the $ra register is expected to hold two different and independent values at the same, which it cannot do.  A register can be repurposed, but only under program control and definitely not automatically — the program/function has to instruct the processor how to do this (by placing appropriate instructions into the machine code instruction stream).  If the program fails to manage the sharing of the $ra register, then some jr $ra will go not back to the actual caller, but to some other call site, and this is the cause of your infinite looping with attendant other overflow issues.