summaryrefslogtreecommitdiff
path: root/PGU/CHAP4
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
parent869e68986aa8f69af6e7842260a68d1e5c6f796f (diff)
Add new code
Signed-off-by: Carlos Maiolino <[email protected]>
Diffstat (limited to 'PGU/CHAP4')
-rw-r--r--PGU/CHAP4/factorial.s67
-rw-r--r--PGU/CHAP4/power.s94
2 files changed, 161 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
diff --git a/PGU/CHAP4/power.s b/PGU/CHAP4/power.s
new file mode 100644
index 0000000..124586e
--- /dev/null
+++ b/PGU/CHAP4/power.s
@@ -0,0 +1,94 @@
+# Power Program
+#
+# Computes the value of a number raised to a power
+# using functions.
+#
+
+# Everything in the main program is stored in registers
+# no need for data section
+.section .data
+
+.section .text
+
+.globl _start
+
+_start:
+
+ pushq $3 # Second argument (power)
+ pushq $2 # First argument (base)
+ call power # Call the function power
+
+ # Cleanup stack removing the arguments from it
+ addq $16, %rsp
+
+ # Save the answer in the stack before calling power again
+ push %rax
+
+ pushq $2 # Second argument (Power)
+ pushq $5 # First argument (Base)
+ call power
+
+ addq $16, %rsp # Cleanup stack
+
+ # Second answer is already in %rax, get the first
+ # back from stack to %rdi
+ popq %rdi
+
+ # Just add them
+ addq %rax, %rdi
+
+ #Sum is already in %rdi, just call exit() with %rdi as argument
+ movq $60, %rax
+ syscall
+
+
+
+##################
+# Power Function #
+##################
+
+# - First Arg - Base power
+# - Second Arg - The power to raise it to
+#
+# NOTE: So far, power must be 1 or greater
+#
+# Variables
+#
+# - %rbx - holds the base number
+# - %rcx - holds the power (also acts as a counter)
+# - -8(%rbp) holds the current result
+
+.type power, @function
+
+power:
+ pushq %rbp # Save old Base Pointer
+ movq %rsp, %rbp # make stack pointer the base pointer
+ subq $8, %rsp # Add space in stack for local storage
+
+ movq 16(%rbp), %r8 # Retrieve Base number from stack to %rbx
+ movq 24(%rbp), %r9 # Retrieve second argument from stack to %rcx
+
+ movq %r8, -8(%rbp) # Store current result (the operand by itself)
+
+power_loop_start:
+ cmpq $1, %r9 # If power is 1, we are done
+ je end_power
+
+ movq -8(%rbp), %rax # Move current into %rax
+ imulq %r8, %rax # Multiply current result by base number
+
+ movq %rax, -8(%rbp) # Save current result
+
+ decq %r9 # Decrease the power (using as a counter)
+ jmp power_loop_start
+
+end_power:
+ movq -8(%rbp), %rax # Retrieve end result into %rax
+ # Return value goes into %rax
+ movq %rbp, %rsp # Restore stack pointer
+ popq %rbp # Restore base pointer
+ ret
+
+
+
+