summaryrefslogtreecommitdiff
path: root/PGU/OLD/chapter4/factorial.s
blob: 749f57ebff94513bdbf56fba9bfb68c50b3dbf42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
##################################################################
# Calculate the factorial of a number, using recursive functions #
##################################################################


#
# %rbx holds the number to factor
#
.section .data

.section .text

.globl _start
_start:
	pushq $5
	call factorial2
	addq $8, %rsp	# Turn back the stack pointer
			# Not really needed here, but good practice
	movq %rax, %rbx
	movq $1, %rax
	int $0x80

.type factorial, @function

# This function is garbage, can be much more clean than this shit.

factorial:
	pushq %rbp		# Regular initial function stuff
	movq %rsp, %rbp		# Save %rbp and reset it to %rsp

	movq 16(%rbp), %rbx	# Get the argument passed into %rbx
	movq %rbx, %rcx		# Copy it to %rcx and decrement it
	decq %rcx		# here. %rcx will be the next element in the
				# factorial.
				#
	cmpq $1, %rcx		# Compare it to 1 and exit if true, we are at
	je exit_factorial	# the end of the factorial

	pushq %rbx		# If not one, save the original argument in the
	pushq %rcx		# stack and push the next value as argument to
	call factorial		# the recursive call
	popq %rcx		# pop value to restore stack pointer
	popq %rbx		# restore %rbx and multiply it
	imul %rax, %rbx		# by the result

exit_factorial:
	movq %rbx, %rax		# Move the result to %rax
	movq %rbp, %rsp		# And do standard clean up before
	popq %rbp		# returning.
	ret

# This is a clean version after extra thought on this

.type factorial2, @function
factorial2:
	pushq %rbp		# Basic function setup, save %rbp and
	movq %rsp, %rbp		# setup it to current %rsp

	movq 16(%rbp), %rax	# Get the argument passed into
	cmpq $1, %rax		#
	je factorial2_end	# We are at the last element in the factorial
				# Just return it
	decq %rax
	pushq %rax
	call factorial2
	movq 16(%rbp), %rbx
	imulq %rbx, %rax

factorial2_end:
	movq %rbp, %rsp
	popq %rbp
	ret