Assembly MIPS组装中的河内塔
我想在MIPS汇编中实现Hanoi Towers算法 杆由Assembly MIPS组装中的河内塔,assembly,mips,towers-of-hanoi,Assembly,Mips,Towers Of Hanoi,我想在MIPS汇编中实现Hanoi Towers算法 杆由A、B和C表示 输入是磁盘的数量,输出是解决问题所需的移动顺序 例如: 如果输入为3,则输出应为: A>C A>B C>B A>C B>A B>C A>C 我已经设法用棒的编号得到结果,即1>3,而不是A>C,代码如下: .data NewLine: .asciiz "\n" To: .asciiz ">" .globl main .text main:
A
、B
和C
表示
输入是磁盘的数量,输出是解决问题所需的移动顺序
例如:
如果输入为3
,则输出应为:
A>C
A>B
C>B
A>C
B>A
B>C
A>C
我已经设法用棒的编号得到结果,即1>3
,而不是A>C
,代码如下:
.data
NewLine: .asciiz "\n"
To: .asciiz ">"
.globl main
.text
main:
li $v0, 5
syscall
add $a0, $v0, $zero
addi $a1, $zero, 1
addi $a2, $zero, 3
addi $a3, $zero, 2
jal hanoi1
li $v0, 10
syscall
hanoi1:
addi $t0, $a0, 0
addi $t1, $zero, 1
bne $a0, $t1, hanoi2
li $v0, 1
move $a0, $a1
syscall
li $v0, 4
la $a0, To
syscall
li $v0, 1
move $a0, $a2
syscall
li $v0, 4
la $a0, NewLine
syscall
addi $a0, $t0, 0
jr $ra
hanoi2:
addi $sp, $sp, -20
sw $ra, 16($sp)
sw $a3, 12($sp)
sw $a2, 8($sp)
sw $a1, 4($sp)
sw $a0, 0($sp)
addi $t3, $a3, 0
addi $a3, $a2, 0
addi $a2, $t3, 0
addi $a0, $a0, -1
jal hanoi1
lw $ra, 16($sp)
lw $a3, 12($sp)
lw $a2, 8($sp)
lw $a1, 4($sp)
lw $a0, 0($sp)
addi $t0, $a0, 0
addi $t1, $zero, 1
li $v0, 1
move $a0, $a1
syscall
li $v0, 4
la $a0, To
syscall
li $v0, 1
move $a0, $a2
syscall
li $v0, 4
la $a0, NewLine
syscall
addi $a0, $t0, 0
addi $t3, $a3, 0
addi $a3, $a1, 0
addi $a1, $t3, 0
addi $a0, $a0, -1
jal hanoi1
lw $ra, 16($sp)
addi $sp, $sp, 20
add $v0, $zero, $t5
jr $ra
我尝试添加标签,例如:
PrintA:
li $v0, 4
la $a0, A
syscall
jr $ra
并将beq
添加到右侧标签的分支:
beq $a1, $t7, PrintA # $t7=1
beq $a1, $t8, PrintB # $t8=2
beq $a1, $t9, PrintC # $t9=3
但是程序进入了无限循环,可能是因为我没有正确处理$ra
所以我的问题是我不知道如何把棒的数字转换成字母
任何帮助都将不胜感激。要使用
jr$ra
返回某处,您必须首先将register$ra
设置为要返回的地址,这就是jal
在分支之前所做的,将下一条指令的地址放入ra
也就是说,要使用这个:
beq $a1, $t7, PrintA # $t7=1
beq $a1, $t8, PrintB # $t8=2
beq $a1, $t9, PrintC # $t9=3
由于PrintA/B/C
变量以jr$ra
结尾,这意味着如果您不想在那里打印任何内容,那么下一条指令而不是beq
块也将是jr$ra
,从而结束该代码流
然后,您可以这样做:
move $a0, <number of rod (from)>
# make sure you have current `ra` stored in stack to not lose it
jal print_rod # will set ra to address of next line
... continue with printing "To" string
... and then you can reuse the same subroutine to display second rod
move $a0, <number of rod (to)>
jal print_rod # will set ra to address of next line
... do remaining things (? if any), restore ra, continue
只需稍加修改:
li $v0, 11 # print character service
addi $a0, $a1, 64 # number to ASCII letter (1->A, 2->B, 3->C)
syscall
就是这样,没有分支(分支通常比做简单的计算慢,比如addi
)
您当前的源代码的不同部分与其他部分相同,您希望再次花费一些时间来尝试了解代码的哪些部分不同,并仅保留这些部分,并使用单个代码实现相同的路径,或者将相同的代码提取到子例程中(通过jal subroutine+jr$ra
使用它),或者重新安排代码流,如下所示:
# something to be done in every iteration
# if (next_part_should_not_execute) branch to skip_part_2
# part 2 of code - being run just under certain condition
skip_part_2:
# if (next_part_should_not_execute) branch to skip_part_3
# part 3 of code - being run just under certain other condition
skip_part_3:
# part 4 of code, being run every iteration, unconditionally
这样,在源代码中仍然只需要“Part4”指令的一个副本,但只有在某些条件为真时,才会运行Part2和Part3
# something to be done in every iteration
# if (next_part_should_not_execute) branch to skip_part_2
# part 2 of code - being run just under certain condition
skip_part_2:
# if (next_part_should_not_execute) branch to skip_part_3
# part 3 of code - being run just under certain other condition
skip_part_3:
# part 4 of code, being run every iteration, unconditionally