From d98f46ce647846b0aa30b2e16a30fd4e152a1bf5 Mon Sep 17 00:00:00 2001 From: Carlos Maiolino Date: Thu, 10 Jul 2025 22:55:07 +0200 Subject: Add new code Signed-off-by: Carlos Maiolino --- PGU/CHAP4/factorial.s | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 PGU/CHAP4/factorial.s (limited to 'PGU/CHAP4/factorial.s') 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 -- cgit v1.2.3