diff options
| author | Carlos Maiolino <[email protected]> | 2025-07-10 22:55:07 +0200 |
|---|---|---|
| committer | Carlos Maiolino <[email protected]> | 2025-07-10 22:56:55 +0200 |
| commit | d98f46ce647846b0aa30b2e16a30fd4e152a1bf5 (patch) | |
| tree | 267474fcc77cf20b428f6f4c7f768ca09f4cfe0e /PGU/CHAP4 | |
| parent | 869e68986aa8f69af6e7842260a68d1e5c6f796f (diff) | |
Add new code
Signed-off-by: Carlos Maiolino <[email protected]>
Diffstat (limited to 'PGU/CHAP4')
| -rw-r--r-- | PGU/CHAP4/factorial.s | 67 | ||||
| -rw-r--r-- | PGU/CHAP4/power.s | 94 |
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 + + + + |
