summaryrefslogtreecommitdiff
path: root/PGU/CHAP4/factorial.s
diff options
context:
space:
mode:
Diffstat (limited to 'PGU/CHAP4/factorial.s')
-rw-r--r--PGU/CHAP4/factorial.s67
1 files changed, 67 insertions, 0 deletions
diff --git a/PGU/CHAP4/factorial.s b/PGU/CHAP4/factorial.s
new file mode 100644
index 0000000..d4907b7
--- /dev/null
+++ b/PGU/CHAP4/factorial.s
@@ -0,0 +1,67 @@
+# Recursion example - calculates the factorial of a number
+
+# Everything goes in the stack, no data section needed
+.section .data
+
+.section .text
+
+.globl _start
+
+# This is pointless unless we are exporting this function to other programs or
+# files. It's just here for completeness.
+.global factorial
+
+_start:
+ pushq $4 # Push argument
+ call factorial # call command pushes the next instruction's address on
+ # the stack, when we return to it, it will pop the
+ # address off of the stack and point the Instruction
+ # pointer to it
+
+ addq $8, %rsp # Cleanup stack - Remove the argument from it
+ # Remember by cleanup, we just move the stackpointer
+ # back a word (8 bytes in x86_64) times the number of
+ # arguments pushed in the stack.
+
+ movq %rax, %rdi # Move result into exit() argument register %rdi
+ # Return values are always stored in %rax...
+
+ movq $60, %rax # Setup %rax to exit() syscall number
+ syscall # Invoke kernel's syscall
+
+
+# Tell linker this is a function
+# Export factorial as a function
+.type factorial, @function
+
+factorial:
+ # Create the stack frame for this function...
+ pushq %rbp # Save %rbp in the stack
+ movq %rsp, %rbp # And current stack pointer in %rbp
+
+ movq 16(%rbp), %rax # Retrieve argument from stack, remember, we're
+ # dealing with quad words, %rbp is at the
+ # beginning of the function's stack frame,
+ # 8(%rbp) is the function's return address setup
+ # by call command and
+ # 16(%rbp) is our argument pushed in the stack
+ # by the function's caller
+
+ cmpq $1, %rax # If we are at 1, nothing to be done...
+ je end_factorial
+
+ decq %rax # Otherwise we decrease our current operand
+ pushq %rax # and send it again to factorial function
+ call factorial # here...
+
+ movq 16(%rbp), %r8 # Retrieve our current argument again
+ imulq %r8, %rax # and multiply it by the result of the factorial
+ # below (num factorial = num * factorial of
+ # previous num, ex. 4! == 4 * 3!)
+
+end_factorial:
+
+ ## Clean up function's stack frame ##
+ movq %rbp, %rsp # We are done with this factorial, restore
+ popq %rbp # %rsp and %rbp and
+ ret # return to the caller