#this is the factorial program
#main(){printf("the factorial of 10 is %d\n",fact(10));}
#int fact (int n)
# {if (n<1) return (1)
# else return (n*fact(n-1));
	.text
	.globl main
main:
	subu $sp,$sp,32		#stack frame is 32 bytes long
	sw $ra,20($sp)		#save return address in $ra
	sw $fp,16($sp)		#save old frame pointer
	addu $fp,$sp,28		#setup frame pointer
#main calls fact
	li $a0,4		#put arg in $a0
	move $s1,$a0		#save chosen n value for output in $s1
	jal fact		#call factorial function
	move $s0,$v0		#save return value in $s0
#using syscalls for output
	li $v0,4		#syscall to print a string
	la $a0,str		#put address of string str in $a0
	syscall			#prints the string str
	li $v0,1		#syscall to print an integer
	move $a0,$s1		#print out chosen n value
	syscall			#prints n value
	li $v0,4		#syscall to print a string
	la $a0,str2		#put address of string str2 in $a0 syscall
	syscall			#prints the string "equals"
	li $v0,1		#syscall to print an integer
	move $a0,$s0		#move return value into $a0
	syscall			#prints the integer return value
	li $v0,4		#syscall to print a string
	la $a0,new		#put address of string new in $a0
	syscall			#prints the string new
	lw $ra,20($sp)		#epilogue to exit
	lw $fp,16($sp)		#restore frame pointer
	addu $sp,$sp,32		#reset stack pointer
	jr $ra	#return to caller
	.rdata
str2:	.asciiz " equals "
str:	.asciiz "The factorial for argument "
new:	.asciiz "\n"
	.text
fact: subu $sp,$sp,32		#stack frame is 32 bytes
	sw $ra,20($sp)		#save return address
	sw $fp,16($sp)		#save old frame pointer
	addu $fp,$sp,28		#setup frame pointer
	sw $a0,0($fp)		#save argument - n
	lw $v0,0($fp)		#load n
	bgtz $v0,$L2		#branch if n>0
	li $v0,1		#return 1
	j $L1			#jump to code to return(base case)
$L2: lw $v1,0($fp)		#load n
	subu $v0,$v1,1		#compute n-1
	move $a0,$v0		#move value to $a0
	jal fact		#call recursively
	lw $v1,0($fp)		#load n
	mul $v0,$v0,$v1		#compute n*fact(n-1) in $v0
	move $s0,$v0		#save return value
#syscall used here for debugging
	li $v0,1		#syscall to print an integer
	move $a0,$s0		#move return value into $a0
	syscall			#prints the integer return value
	li $v0,4
	la $a0,new		#prints newline
	syscall
	move $v0,$s0		#restore return value into $v0
# end debugging code
$L1:	lw $ra,20($sp)		#restore $ra
	lw $fp,16($sp)		#return $fp
	addu $sp,$sp,32		#pop stack
	j $ra			#return to caller