从C递归错误输出的Mips转换

时间:2014-12-06 22:00:26

标签: c recursion mips c99

这个问题被称为八皇后问题(在8 x 8棋盘上放置8个皇后,这样它们都不能互相攻击/威胁)。我在C中有以下解决方案,它使用递归来打印所有可能的解决方案。我想让它非递归,但我遇到了麻烦所以我只是直接将它翻译成MIPS ..

然而,我仍然宁愿让它非递归。

#include <string.h>
#include <stdio.h>
#include <stdlib.h>


int attack(int i, int j, int col, int* hist)
{
    return (hist[j] == i) || (abs(hist[j] - i) == (col - j));
}

int solve(int n, int col, int *hist)
{
    if (col == n)
    {
        putchar('\n');
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                if (hist[i] == j)
                {
                    putchar('Q');
                }
                else if((i + j) & 1)
                {
                    putchar(' ');
                }
                else
                {
                    putchar(178);
                }
            }
            putchar('\n');
        }
        return 0;
    }

    for (int i = 0, j = 0; i < n; ++i)
    {
        for (j = 0; j < col; ++j)
        {
            if (attack(i, j, col, hist) != 0)
                break;
        }

        if (j < col) continue;

        hist[col] = i;
        solve(n, col + 1, hist);
    }
    return 0;
}

int main()
{
    int hist[8];
    solve(8, 0, hist);
}

结果是(一种可能的解决方案):

enter image description here 现在我需要把它翻译成mips而且我有:

#include <mips.h>


.data
new_line:  .asciiz "\n"
new_lines: .asciiz "\n\n\n"
black_sq: .asciiz "B"
white_sq: .asciiz "W"
queen_sq: .asciiz "Q"
hist:     .word 0, 0, 0, 0, 0, 0, 0, 0

i_p:  .asciiz "I: "
j_p: .asciiz "   J: "
.text
.globl main

main:
    subiu $sp, $sp, 32
    sw $ra, 28($sp)
    sw $fp, 24($sp)
    sw $s0, 20($sp)
    sw $s1, 16($sp)
    #store stack-frame: end.

    li $a0, 8
    li $a1, 0
    la $a2, hist
    jal solve   


    #restore stack-frame: beg.
    sw $s1, 16($sp)
    sw $s0, 20($sp)
    lw $fp, 24($sp)
    lw $ra, 28($sp)
    addiu $sp, $sp, 32
    li $v0, 10
syscall


#solve(n, col, hist)
solve:
    subiu $sp, $sp, 32
    sw $ra, 28($sp)
    sw $a0, 24($sp)
    sw $a1, 20($sp)
    sw $a2, 16($sp)

    bne $a1, $a0, solve_atk

    li $v0, 4
    la $a0, new_lines
    syscall
    lw $a0, 24($sp)


    li $t0, 0   #i = 0
    solve_for_1:
        beq $t0, $a0, solve_for_1_end

        li $t1, 0  #j = 0
        solve_for_2:
            beq $t1, $a0, solve_for_2_end


            sll $t2, $t0, 2     #ri = i * sizeof(int)
            add $t2, $t2, $a2
            lw $t2, 0($t2)      #hist[i]
            bne $t2, $t1, solve_for_2_else_if
            la $a0, queen_sq    #putchar('Q')
            j solve_for_2_if_end

            solve_for_2_else_if:
            add $t2, $t1, $t0
            andi $t3, $t2, 1
            beqz $t3, solve_for_2_else
            la $a0, white_sq    #putchar(' ')
            j solve_for_2_if_end

            solve_for_2_else:
            la $a0, black_sq    #putchar(¦)

            solve_for_2_if_end:
            li $v0, 4
            syscall
            lw $a0, 24($sp)

            addiu $t1, $t1, 1  #++j
            j solve_for_2
        solve_for_2_end:

        li $v0, 4
        la $a0, new_line  #putchar('\n')
        syscall
        lw $a0, 24($sp)
        addiu $t0, $t0, 1  #++i
        j solve_for_1
    solve_for_1_end:
    addiu $sp, $sp, 32
    jr $ra  #return;

    solve_atk:
        li $t3, 0 #i = 0   
        solve_atk_for_1:
            beq $t3, $a0, solve_atk_for_1_end
            li $t4, 0  #j = 0

            solve_atk_for_2:
            beq $t4, $a1, solve_atk_for_2_end

            move $a3, $a2  #hist
            move $a2, $a1  #col
            move $a1, $t4  #j
            move $a0, $t3  #i
            jal attack     #v0 = attack(i, j, col, hist);
            lw $a2, 16($sp)
            lw $a1, 20($sp)
            lw $a0, 24($sp)
            lw $ra, 28($sp)

            beqz $v0, solve_atk_for_2_end  #if (attack(i, j, col, hist) != 0) break;

            addiu $t4, $t4, 1
            j solve_atk_for_2
            solve_atk_for_2_end:

            blt $t4, $a1, solve_atk_for_1_continue  #if (j < col) continue;



            sll $t0, $a1, 2     #ri = col * sizeof(int)
            add $t0, $t0, $a2
            sw $t3, 0($t0)      #hist[col] = i

            lw $a2, 16($sp)
            lw $a1, 20($sp)
            lw $a0, 24($sp)
            lw $ra, 28($sp)
            addiu $a1, $a1, 1  #solve(i, col + 1, hist)
            jal solve

            solve_atk_for_1_continue:

        addiu $t3, $t3, 1  #++i
        j solve_atk_for_1
        solve_atk_for_1_end:


    lw $a2, 16($sp)
    lw $a1, 20($sp)
    lw $a0, 24($sp)
    lw $ra, 28($sp)
    addiu $sp, $sp, 32
jr $ra


#attack(i, j, col, hist)
attack:
    sll $t0, $a1, 2     #ri = j * sizeof(int)
    add $t0, $t0, $a3
    lw $t0, 0($t0)      #hist[j]    
    sub $a3, $t0, $a0

    li $v0, 0
    beqz $a3, attack_or  #if hist[j] != i
    li $v0, 1            #return true.
    j attack_done

    attack_or:
        abs $a3, $a3
        sub $t0, $a2, $a0
        bne $t0, $a3, attack_done
        li $v0, 1

    attack_done:
jr $ra


abs:
    sra $t1, $t0, 31   
    xor $t0, $t0, $t1   
    sub $v0, $t0, $t1 
jr $ra

但它打印出错误的结果。我怀疑这是由于递归,因为我之前测试了所有代码:

solve_atk

solve_atk之后的所有代码分开,它与C代码完全相同。根据我的判断,问题就在于递归。

任何想法我做错了什么?对于那些无法读取MIPs汇编的人来说,没有递归的“C”解决方案(与我的相同)也没问题(我可以自己翻译)。

任何想法或解决方案?

1 个答案:

答案 0 :(得分:1)

  

就我所知,问题就在于递归。

确实这是主要问题。你忽略了这一点,当递归调用solve时,寄存器$a1$t3被修改(前者由你的调用代码修改,后者由被调用的solve实例修改),而通话结束后仍需要原始值。您可以通过更改

来纠正此问题
            addiu $a1, $a1, 1  #solve(i, col + 1, hist)
            jal solve

            addiu $a1, $a1, 1   #solve(i, col + 1, hist)
            sw $t3, 12($sp)     # save $t3
            jal solve
            lw $t3, 12($sp)     # restore $t3
            addiu $a1, $a1, -1  # restore $a1

除此之外,还有一些小错误:

  • beqz $v0, solve_atk_for_2_end #if (attack(i, j, col, hist) != 0) break;必须为
    bnez $v0, solve_atk_for_2_end #if (attack(i, j, col, hist) != 0) break;
  • beqz $a3, attack_or #if hist[j] != i必须为
    bnez $a3, attack_or #if hist[j] != i
  • sub $t0, $a2, $a0(在attack_or:之后)必须为 sub $t0, $a2, $a1 $a0i,而$a1中我们需要j(col - j)