97 lines
4.4 KiB
ArmAsm
97 lines
4.4 KiB
ArmAsm
|
.global main
|
||
|
|
||
|
.section .data
|
||
|
result: .asciz "fib(%llu) = %llu\n"
|
||
|
a: .quad 0
|
||
|
|
||
|
.section .text
|
||
|
main: push %rbp # Save the old base pointer to the
|
||
|
# stack.
|
||
|
# This also makes sure that rsp is
|
||
|
# 16-byte aligned.
|
||
|
movq %rsp, %rbp # Write the new base pointer.
|
||
|
subq $16, %rsp # The stack frame is extended to fit
|
||
|
# the three local variables and the
|
||
|
# old value of the base pointer.
|
||
|
# ABI requires 16-byte alignment!
|
||
|
# This is not a problem here but it
|
||
|
# is very noteworthy!
|
||
|
|
||
|
movq 8(%rsi), %rdi # Retrieve the first argument from
|
||
|
# the array of arguments.
|
||
|
# The retrieved value is n in fib(n)
|
||
|
call atoll # Convert the argument to long long
|
||
|
movq %rax, %rdi # Save the long long as the argument
|
||
|
# for the fib(n) function.
|
||
|
movq %rax, a # Save the long long in a to use it
|
||
|
# later in the printed output.
|
||
|
|
||
|
call fib # Call the Fibonacci-function
|
||
|
|
||
|
movq a, %rsi # Move the number a to rsi to use it
|
||
|
# as the second argument for print.
|
||
|
movq %rax, %rdx # Move to result of the fib(n)-call
|
||
|
# to rdx, to use it as the third
|
||
|
# argument for printf.
|
||
|
movq $result, %rdi # Move the string to rdi, for use as
|
||
|
# as the first argument for print.
|
||
|
xor %al,%al # Specify that no vector arguments
|
||
|
# are to be used.
|
||
|
|
||
|
call printf # Print the string with values
|
||
|
|
||
|
xor %rax, %rax # Make sure to return 0 to indicate
|
||
|
# a successful run of the program.
|
||
|
jmp end # Jump to end to return from the
|
||
|
# program with the return value 0.
|
||
|
|
||
|
|
||
|
fib: push %rbp # Save old rbp to stack and align
|
||
|
# the stack pointer to 16-bytes,
|
||
|
# since the return address already
|
||
|
# has been pushed. Thus, the size
|
||
|
# of the two values totals to
|
||
|
# a size of 16-bytes.
|
||
|
movq %rsp, %rbp # Write new base pointer.
|
||
|
|
||
|
cmpq $1, %rdi # Compare the argument to 1.
|
||
|
je one # If equal to one, return 1.
|
||
|
cmpq $0, %rdi # Compare the argument to 0.
|
||
|
jle zero # If equal to zero or negative go
|
||
|
# to 'zero' and return zero.
|
||
|
|
||
|
decq %rdi # Decrement n by 1.
|
||
|
push %rdi # Save the value n - 1 in stack to
|
||
|
# be able to recover it later.
|
||
|
|
||
|
call fib # Call the function. The value of
|
||
|
# rax is now equal to the return
|
||
|
# value of fib(n-1).
|
||
|
|
||
|
pop %rdi # Restore rdi = n-1
|
||
|
decq %rdi # Decrement rdi by 1.
|
||
|
push %rax # Save the result of fib(n-1)
|
||
|
|
||
|
call fib # Call the function. The value of
|
||
|
# rax is now equal to the return
|
||
|
# value of fib(n-2).
|
||
|
addq (%rsp),%rax # Add fib(n-1) to rax which contains
|
||
|
# the reuslt of fib(n-2). fib(n-1)
|
||
|
# is retrieved from the stack.
|
||
|
jmp end # Jump to 'end' to leave and return
|
||
|
# from this call.
|
||
|
|
||
|
zero: movq $0, %rax # Set return value to 0.
|
||
|
jmp end
|
||
|
one: movq $1, %rax # Set return value to 1.
|
||
|
end: leave # Return the state of the base and
|
||
|
# stack pointers to their
|
||
|
# original state. By moving the
|
||
|
# base pointers value into the
|
||
|
# stack pointer and moving the old
|
||
|
# base pointer value into the stack
|
||
|
# pointer.
|
||
|
ret # Return from the current function
|
||
|
# with the contents of rax as the
|
||
|
# return value.
|