' hanoi tower'使用MIPS的递归解决方案

时间:2018-05-17 02:17:53

标签: assembly mips

我是新问题,有关堆栈溢出的问题,甚至更新的MIPS问题。 我试着对“河内塔楼”实施以下递归解决方案。问题(取自here)使用MIPS。 我认为我这样做的失败背后的事实是我不知道什么时候应该恢复/保存$ra, $sp这样的寄存器 - 所以我只是假设我需要在任何地方这样做 - 任何帮助都会很大赞赏:

void towerOfHanoi(int n, char from_rod, char to_rod, char aux_rod)
{
    if (n == 1)
    {
        printf("\n Move disk 1 from rod %c to rod %c", from_rod, to_rod);
        return;
    }
    towerOfHanoi(n-1, from_rod, aux_rod, to_rod);
    printf("\n Move disk %d from rod %c to rod %c", n, from_rod, to_rod);
    towerOfHanoi(n-1, aux_rod, to_rod, from_rod);
}

int main()
{
    int n = 4; // Number of disks
    towerOfHanoi(n, 'A', 'C', 'B');  // A, B and C are names of rods
    return 0;
}

这是我试图翻译的原因。它进入MIPS:

.globl main
main:
    addi $sp, $sp, -4
    sw $ra, 0($sp)

    li $v0, 5 # system call code for read_int
    syscall

    move $a0, $v0 # a0 holds the number of disks
    li $a1, 'A' # a1 holds from_rod
    li $a2, 'C' # a2 holds to_rod
    li $a3, 'B' # a3 holds aux_rod

    jal hanoi

    lw $ra, 0($sp)
    addi $sp, $sp, 4
    li $v0, 10
    syscall

hanoi:
    addi $sp, $sp, -4
    sw $ra, 0($sp)

    beq $a0, 1, base_case
    addi $a0, $a0, -1 # number_of_disks -= 1
    # swap between to_rod and aux_rod :
    move $t0, $a2 # temp = to_rod
    move $a2, $a3 # to_rod = aux_rod
    move $a3, $t0 # aux_rod = temp
    jal hanoi

    jal print

    # swap between from_rod and aux_rod :
    move $t0, $a1 # temp = from_rod
    move $a1, $a3 # from_rod = aux_rod
    move $a3, $t0 # aux_rod = temp
    jal hanoi

    lw $ra, 0($sp)
    addi $sp, $sp, 4
    jr $ra
base_case:
    addi $sp, $sp, -4
    sw $ra, 0($sp)

    jal print

    lw $ra, 0($sp)
    addi $sp, $sp, 4
    jr $ra
print:
    addi $sp, $sp, -4
    sw $ra, 0($sp)
    move $t0, $a0

    li $v0, 11
    move $a0, $a1
    syscall # print from_rod
    li $a0, '>'
    syscall # print the char '>'
    move $a0, $a2
    syscall # print  to_rod
    li $a0, '\n'
    syscall # pirnt new line
    move $a0, $t0

    lw $ra, 0($sp)
    addi $sp, $sp, 4
    jr $ra

2 个答案:

答案 0 :(得分:2)

看看这个解决方案:

# Towers of Hanoi
# MIPS assembly implementation (tested with MARS)

.data
prompt: .asciiz "Enter a number: "
part1: .asciiz "\nMove disk "
part2: .asciiz " from rod "
part3: .asciiz " to rod "

.text
.globl main
main:
    li $v0,  4          # print string
    la $a0,  prompt
    syscall
    li $v0,  5          # read integer
    syscall

    # parameters for the routine
    add $a0, $v0, $zero # move to $a0
    li $a1, 'A'
    li $a2, 'B'
    li $a3, 'C'

    jal hanoi           # call hanoi routine

    li $v0, 10          # exit
    syscall

hanoi:

    #save in stack
    addi $sp, $sp, -20 
    sw   $ra, 0($sp)
    sw   $s0, 4($sp)
    sw   $s1, 8($sp)
    sw   $s2, 12($sp)
    sw   $s3, 16($sp)

    add $s0, $a0, $zero
    add $s1, $a1, $zero
    add $s2, $a2, $zero
    add $s3, $a3, $zero

    addi $t1, $zero, 1
    beq $s0, $t1, output

    recur1:

        addi $a0, $s0, -1
        add $a1, $s1, $zero
        add $a2, $s3, $zero
        add $a3, $s2, $zero
        jal hanoi

        j output

    recur2:

        addi $a0, $s0, -1
        add $a1, $s3, $zero
        add $a2, $s2, $zero
        add $a3, $s1, $zero
        jal hanoi

    exithanoi:

        lw   $ra, 0($sp)        # restore registers from stack
        lw   $s0, 4($sp)
        lw   $s1, 8($sp)
        lw   $s2, 12($sp)
        lw   $s3, 16($sp)

        addi $sp, $sp, 20       # restore stack pointer

        jr $ra

    output:

        li $v0,  4              # print string
        la $a0,  part1
        syscall
        li $v0,  1              # print integer
        add $a0, $s0, $zero
        syscall
        li $v0,  4              # print string
        la $a0,  part2
        syscall
        li $v0,  11             # print character
        add $a0, $s1, $zero
        syscall
        li $v0,  4              # print string
        la $a0,  part3
        syscall
        li $v0,  11             # print character
        add $a0, $s2, $zero
        syscall

        beq $s0, $t1, exithanoi
        j recur2

这几乎是你的C代码的直接翻译,应该足以理解如何通过堆栈保存例程参数。

答案 1 :(得分:0)

Makukha 的 MIPS 程序也适用于 QtSPIM。

这是另一个更直观的递归河内塔程序,用 CodeAPeel-C 汇编语言编写,内置像素屏幕。

enter image description here