#	Program to compute fact(n) 
#
#	Remember:
#		need to start with label main
#		$sp is the stack pointer
#		$ra save return address
#		$zero always equal to zero

#	Can you find the bugs here ?
main:
	subu	$sp, $sp, 8	# make space for parameters on stack
	sw	$ra, 0($sp)	# Store register $ra
	sw	$zero, 4($sp)	# Reset parameter n

	li	$v0, 4		# Ask for number
	la	$a0, ask
	syscall

	li	$v0, 5		# read int
	syscall			# $v0 holds the integer

	sw	$v0, 4($sp)	# Save n on stack

	move	$a0, $v0	# Prepare argument for fact
	jal	fact		# Call fact (Jump & Link)

    	#			# We're back !
	move	$t0, $v0	# Save result temporarily

        li      $v0, 4		# Print the result
        la      $a0, str1
        syscall

        li      $v0, 1
        lw   	$a0, 4($sp)
        syscall

        li      $v0, 4
        la      $a0, str2
        syscall

        li      $v0, 1
        move    $a0, $t0
        syscall

        li      $v0, 4
        la      $a0, newl
        syscall

	lw	$ra, 0($sp)	# Restore register 31
	addu	$sp, $sp, 8	# Pop stack
	jr	$ra		# return


fact:
	subu	$sp, $sp, 8	# make space for parameters on stack
	sw	$ra, 0($sp)	# Save register $ra
	sw	$a0, 4($sp)	# Save argument

	bne	$a0, 1, recurs	# Do we need to recurse ?
	move	$v0, $a0	# else return 1.
	lw	$ra, 0($sp)	# Restore register $ra
	addu	$sp, $sp, 8	# Pop stack back
	j	$ra		# return

recurs:
	addi	$a0, $a0, -1	# Prepare to call fact(n-1)
	jal	fact		# Call fact(n-1)
    	#			# We're back.
	lw	$t0, 4($sp)	# Recall n
	mulo	$v0, $t0, $v0	# fact(n) = n*fact(n-1)

	lw	$ra, 0($sp)	# Restore register $ra
	addu	$sp, $sp, 8	# Pop stack
	jr	$ra		# return

	.data
str1:
	.asciiz	"\nfact("
str2:
	.asciiz	") = "
ask:
	.asciiz "\nEnter number > "
newl:
	.asciiz "\n"

