Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly ';河内大厦';基于MIPS的递归求解_Assembly_Mips - Fatal编程技术网

Assembly ';河内大厦';基于MIPS的递归求解

Assembly ';河内大厦';基于MIPS的递归求解,assembly,mips,Assembly,Mips,我对询问堆栈溢出问题还不熟悉,甚至对MIPS也不熟悉。 我尝试使用MIPS实现以下针对“hanoi towers”问题(取自)的递归解决方案。 我认为我这样做的失败是因为我不知道什么时候应该恢复/保存寄存器,比如$ra,$sp-所以我假设我需要在任何地方都这样做-非常感谢您的帮助: void towerOfHanoi(int n, char from_rod, char to_rod, char aux_rod) { if (n == 1) { printf("\

我对询问堆栈溢出问题还不熟悉,甚至对MIPS也不熟悉。 我尝试使用MIPS实现以下针对“hanoi towers”问题(取自)的递归解决方案。 我认为我这样做的失败是因为我不知道什么时候应该恢复/保存寄存器,比如
$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

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


运行此操作时是否发生了不好的情况?在调试器下运行时,您学到了什么?在您的C版本中,请注意第二次调用(
towerOfHanoi(n-1,aux_rod,to_rod,from_rod);
)如何使用与第一次函数调用相同的变量。i、 在第一次递归调用之后,仍然需要函数参数,因此您也必须保存/恢复它们。如果您想知道一种方法,请查看C版本()的编译器输出。@DavidWohlferd它确实运行,只是产生了错误的输出。@PeterCordes我想我理解您的意思-第二次调用基本上是在第一次调用中完成所有操作后使用参数。我查看了你放在这里的链接,不幸的是,我无法理解其中的大部分内容——尽管如此,还是要谢谢你。@MarkoKlei:是的,但是输出有什么错误:显示它以使其成为一个新的链接。