I was posed with a lab assignment to code Tower of Hanoi in Assembly. As I have graduated from the course, I have no qualms in sharing out the thought process of working out the code.
I believe the objective in this lab assignment is for students to understand the underlying mechanism to handle recursion. The following is the code snippet of my solution in assembly:
.text
.globl main
main:
addi $sp, $sp, -8 # Make space on stack.
sw $ra, 0($sp) # Save return address.
la $a0, prompt
li $v0, 4
syscall # display prompt
li $v0, 5
syscall # get integer response from user
li $t0, 1
slt $t1, $v0, $t0 # user supplied a number less than 1, how can this be valid
bne $t1, $zero, exit # just exit the program
sw $v0, 4($sp)# save initial value of numDiscs
move $a0, $v0 # $numdisc = user specified value
move $v1, $zero # steps = 0
li $a1, 1 # start = 1
li $a2, 3 # goal = 3
jal towers
printf:
lw $a0, 4($sp) # Get initial value of numDiscs back
li $v0, 1
syscall
la $a0, midOfEndResult
li $v0, 4
syscall # print middle part of sentence
move $a0, $v1
li $v0, 1
syscall # print results
la $a0, steps
li $v0, 4
syscall # print end of string
lw $ra, 0($sp) # Restore return address.
exit:
addi $sp, $sp, 8 # Restore stack pointer.
jr $ra # return to main
towers:
addi $sp, $sp -16
sw $ra, 0($sp) # save return address
sw $s0, 4($sp) # save numDiscs
move $s0, $a0
sw $s1, 8($sp) # save start
move $s1, $a1
sw $s2, 12($sp) # save goal
move $s2, $a2
li $t0, 2
slt $t1, $a0, $t0
beq $t1, $zero, moreThanEqualsTwo # numDiscs >= 2
lessThanTwo:
# print (start, goal)
la $a0, lbracket
li $v0, 4
syscall
move $a0, $a1
li $v0, 1
syscall
la $a0, comma
li $v0, 4
syscall
move $a0, $a2
li $v0, 1
syscall
la $a0, rbracket
li $v0, 4
syscall
la $a0, endl
li $v0, 4
syscall
# end print
addi $v1, $v1, 1 # steps++
j returnCall
moreThanEqualsTwo:
li $t0, 6
sub $t0, $t0, $s1
sub $t0, $t0, $s2 # peg = 6 - start - goal
addi $a0, $s0, -1 # numDiscs - 1
move $a1, $s1 # start = start
move $a2, $t0 # goal = peg
jal towers # towers(numDiscs-1, start, peg)
li $a0, 1
move $a1, $s1 # start = start
move $a2, $s2 # end = end
jal towers # towers(1, start, goal)
li $t0, 6
sub $t0, $t0, $s1
sub $t0, $t0, $s2 # peg = 6 - start - goal
addi $a0, $s0, -1 # numDiscs - 1
move $a1, $t0 # start = peg
move $a2, $s2 # goal = goal
jal towers #towers(numDiscs-1, peg, goal)
returnCall:
lw $ra, 0($sp) # restore return address
lw $s0, 4($sp) # restore numDiscs
lw $s1, 8($sp) # restore start
lw $s2, 12($sp) # restore goal
addi $sp, $sp, 16 #restore stack pointer
jr $ra # return to previous call
.data
prompt: .asciiz "Enter the number of disks to be moved: "
lbracket: .asciiz "("
comma: .asciiz ", "
rbracket: .asciiz ")"
endl: .asciiz "\n"
midOfEndResult: .asciiz " disc(s) moved from peg 1 to peg 3 in "
steps: .asciiz " steps.\n"
After being able to code everything on my own, I felt so blessed that higher level languages like C++ and Java had built-in mechanisms to handle recursion for the programmer. Imagine how much time and effort you would have saved if a similar solution in C++ (with comments) is only around 20 lines of C++ coding?
Saturday, January 5, 2008
Subscribe to:
Posts (Atom)