斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从 1963 年起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。
C语言版本#include "stdio.h"
unsigned long Fibon1(int n)
{
if (n == 1 || n == 2)
{
return 1;
}
else
{
return Fibon1(n - 1) + Fibon1(n - 2);
}
}
int main()
{
int n = 0;
unsigned long ret = 0;
//scanf("%d", &n);
n=50;
ret = Fibon1(n);
printf("ret=%lu\n", ret);
return 0;
}
可以直接编译运行。
#gcc -o fibo-c fibo.c
# time ./fibo-c
ret=12586269025
real 1m9.897s
user 1m9.931s
sys 0m0.020s
Nasm版本extern printf ;//调用外部的printf函数
section .data
fmt db "result is: %lu ", 0xa
global _start
fibo:
push rbx
push rdx
cmp rax, 1
je _get_out
cmp rax, 2
je _get_out;//相当于if(n == 1 || n == 2) return 1;
mov rdx, rax;//相当于if(n!=1&&n!=2),先保存rax
sub rax, 1
call fibo;//相当于fibo(n-1)
mov rbx, rax;//保存fibo(n-1)结果到rbx
mov rax, rdx;//获取rax值。
sub rax, 2
call fibo;//相当于fibo(n-2)
mov rcx, rax;//保存fibo(n-2)到rbx
mov rax, rbx
add rax, rcx;//fibo(n-1)+fibo(n-2)
pop rdx
pop rbx
ret
_get_out:
pop rdx
pop rbx
mov rax, 1
ret;//直接返回fibo函数
_start:
mov rax, 50 ;//求数列中第七个数
call fibo
mov rdi,fmt
mov rsi,rax
call printf
mov rax,60
syscall
nasm -f elf64 -o fibo.o fibo.asm
ld -o fibo fibo.o -lc -I /lib64/ld-linux-x86-64.so.2
# time ./fibo
result is: 12586269025
real 0m41.641s
user 0m41.639s
sys 0m0.000s
Gas版本
.extern printf ;//调用外部的printf函数
.section .data
fmt: .ascii "result is: %lu \n"
.global _start
fibo:
push %rbx
push %rdx
cmp $1,%rax
je _get_out
cmp $2,%rax
je _get_out;//相当于if(n == 1 || n == 2) return 1;
mov %rax, %rdx;//相当于if(n!=1&&n!=2),先保存rax
sub $1,%rax
call fibo;//相当于fibo(n-1)
mov %rax, %rbx;//保存fibo(n-1)结果到rbx
mov %rdx, %rax;//获取rax值。
sub $2,%rax
call fibo;//相当于fibo(n-2)
mov %rax, %rcx;//保存fibo(n-2)到rbx
mov %rbx, %rax
add %rcx, %rax;//fibo(n-1)+fibo(n-2)
pop %rdx
pop %rbx
ret
_get_out:
pop %rdx
pop %rbx
mov $1,%rax
ret;//直接返回fibo函数
_start:
mov $50,%rax ;//求数列中第七个数
call fibo
mov $fmt,%rdi
mov %rax,%rsi
call printf
mov $60,%rax
syscall
编译连接:
as -g -o fibo_att.o fibo_att.s
ld -o fibo_att fibo_att.o -lc -I /lib64/ld-linux-x86-64.so.2
# time ./fibo_att
result is: 12586269025
real 0m41.625s
user 0m41.623s
sys 0m0.000s
性能差异
|
Nasm汇编 |
Gas汇编 |
C语言 |
C语言-O1 编译优化 |
C语言-O2 编译优化 |
执行时间 |
41.6s |
41.6s |
1m0.876s |
NA,异常 |
NA,异常 |
可以看到汇编程序编译后的明显性能优势。性能提升31.5%。
使用GCC的-O参数优化后会影响程序本身的功能。