assembly 连续算术溢出

7lrncoxx  于 4个月前  发布在  其他
关注(0)|答案(2)|浏览(47)

我已经尝试改变了这么多的代码,但我一直得到neverending算术溢出警告或'坏地址在数据/堆栈'错误.我似乎不能得到它正确!任何见解是受欢迎的!我试图实现一个数独板,这些是这个函数的说明:给一个数独棋盘的指针,这个函数应该返回一个整数,表示棋盘中有多少个单元格已经被解出。棋盘的状态应该是未修改的。每个数独单元格总共占用10个字节。每个单元占用10个字节,整个板占用810个字节的内存。
有什么发现吗?

# 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

字符串

moiiocjp

moiiocjp1#

@Reda Bourial已经指出,也许你需要在这个函数中计数是有条件的,而不是无条件的。
其他6个逻辑错误是调用约定,即与我们在C或其他语言中看不到的函数调用有关,因为编译器为我们处理了这些细节。(我们假设你的意图是遵循标准的调用约定,这是大多数教学作业的想法,因为在不首先知道标准方法和为什么使用它们的情况下,尝试调用约定偏差/优化是没有教育意义的。
在寄存器机器上调用函数是初学者最难掌握的事情之一,这并不是因为它从根本上很深或相互交织,而是因为有几个不同的规则,每个规则都很简单,但在一起需要记住很多东西,以及何时使用哪个规则。
逻辑错误不一定会导致无限循环或程序崩溃,因为周围的代码(调用者和被调用者)不会测试这些逻辑是否错误。由于您没有显示任何代码,但只有一个函数,因此我们不能说其中的一些错误。
函数调用逻辑错误有:

  1. $ra用于第二个目的,而不保留其值以供此函数自己的后记使用。
  2. $s0违反了调用约定规则-没有保留和恢复,这违反了与此函数的调用者的调用约定。
  3. $v0的使用也违反了调用约定规则,因为它期望被调用者保留这些合法的调用删除寄存器。
  4. $t0与(3.)
    1.函数注解说明$a0是一个传入参数,但函数忽略了这个参数(可能是为了支持la,尽管我们不认为这可能是因为缺少对被调用方实际参数的计算)。
    1.就像函数形参在这个函数中没有被正确使用一样,实际的参数也肯定没有为被调用方is_cell_solved正确设置。
    对于第一个错误,$ra寄存器预期同时保存两个不同且独立的值,但它不能这样做。但是仅在程序控制下并且绝对不是自动的程序/功能必须指示处理器如何这样做(通过将适当的指令放入机器代码指令流)。如果程序未能管理$ra寄存器的共享,那么一些jr $ra将不会返回到实际的调用者,而是返回到其他一些调用站点,这就是导致无限循环以及随之而来的其他溢出问题的原因。
izkcnapc

izkcnapc2#

看起来你的循环中有一个问题,不管单元格的状态如何,你都要递增计数。你应该只在单元格被求解时才递增计数。另外,你需要正确处理is_cell_solved函数的返回值。
下面是代码的修改版本:

# 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

字符串
此修改包括一个分支(not_solved),用于在单元格未求解时跳过计数的增量。确保is_cell_solved函数正确返回一个值,指示单元格是否已求解。

相关问题