繁体   English   中英

使用 MIPS 的“河内塔”递归解决方案

[英]'hanoi towers' recursive solution using MIPS

我刚开始问关于堆栈溢出的问题,甚至对 MIPS 也是新手。 我尝试使用 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

看看这个解决方案:

# 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 代码的直接翻译,应该足以了解如何通过堆栈保留例程参数。

Makukha 的 MIPS 程序也适用于 QtSPIM。

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

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM