summaryrefslogtreecommitdiff
path: root/PGU/CHAP4/factorial.s
diff options
context:
space:
mode:
authorCarlos Maiolino <[email protected]>2025-07-10 22:55:07 +0200
committerCarlos Maiolino <[email protected]>2025-07-10 22:56:55 +0200
commitd98f46ce647846b0aa30b2e16a30fd4e152a1bf5 (patch)
tree267474fcc77cf20b428f6f4c7f768ca09f4cfe0e /PGU/CHAP4/factorial.s
parent869e68986aa8f69af6e7842260a68d1e5c6f796f (diff)
Add new code
Signed-off-by: Carlos Maiolino <[email protected]>
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