.macro lstr %rd, %str
	.data
	lstr_message: .asciiz %str
	.text
	la %rd, lstr_message
.end_macro

.macro print_str %str
	push a0
	push v0
	lstr a0, %str
	li v0, 4
	syscall
	pop v0
	pop a0
.end_macro

# --------------------------------------------------
.global main
main:
	print_str "8! = "

	# print_int(fact(8))
	li a0, 8
	jal fact
	move a0, v0
	li v0, 1
	syscall

	print_str "\n"

	# exit
	li v0, 10
	syscall

# --------------------------------------------------
# int fact(int x)
#
# returns factorial of x, calculated recursively.

fact:
	push ra
	push s0

	# save argument into s0. from now on,
	# s0 = x.
	move s0, a0

	# if(x <= 1) {
	bgt s0, 1, _else
		# return 1
		li v0, 1
		# just jump to the pops to force a return.
		j _return
	j _endif
	_else:
		# return fact(x - 1) * x

		# this is fact(x - 1)
		sub a0, s0, 1
		jal fact

		# and this multiplies the return value from the
		# recursive call by x (s0). since we put the
		# result back into v0, *this* recursion will return
		# the product.
		mul v0, v0, s0
	_endif:

_return:
	# pops are in reverse order of pushes.
	pop s0
	pop ra
	jr ra