1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
|