第46部分-Linux x86 64位汇编 斐波那契和汇编性能增益

第46部分-Linux x86 64位汇编 斐波那契

斐波那契数列

斐波那契数列(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参数优化后会影响程序本身的功能。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
斐波那契数列是一个经典的数学问题,它的定义是:第一个和第二个数都是1,从第三个数开始,每个数都是前两个数的和。在x86汇编中,可以通过循环和寄存器操作来实现斐波那契数列的计算。 下面是一个简单的x86汇编代码示例,用于计算斐波那契数列的前n个数: ``` section .data fib_msg db "Fibonacci sequence:", 0 fib_num db "%d", 0 newline db 10, 0 section .text global _start _start: ; 获取用户输入的n mov eax, 1 mov ebx, 0 int 0x80 ; 将n保存到ecx寄存器中 mov ecx, eax ; 初始化斐波那契数列的前两个数 mov eax, 1 mov ebx, 1 ; 输出斐波那契数列的提示信息 mov eax, 4 mov ebx, 1 mov edx, 18 mov ecx, fib_msg int 0x80 ; 输出斐波那契数列的前n个数 mov eax, 4 mov ebx, 1 fib_loop: ; 输出当前斐波那契数列的数值 push ebx push fib_num call printf add esp, 8 ; 计算下一个斐波那契数列的数值 add ebx, eax sub ecx, 1 ; 判断是否还需要继续计算 cmp ecx, 0 jg fib_loop ; 输出换行符 mov eax, 4 mov ebx, 1 mov edx, 1 mov ecx, newline int 0x80 ; 退出程序 mov eax, 1 xor ebx, ebx int 0x80 section .data printf db "%d", 10, 0 section .text extern printf _start: ; 获取用户输入的n mov eax, 1 mov ebx, 0 int 0x80 ; 将n保存到ecx寄存器中 mov ecx, eax ; 初始化斐波那契数列的前两个数 mov eax, 1 mov ebx, 1 ; 输出斐波那契数列的提示信息 mov eax, 4 mov ebx, 1 mov edx, 18 mov ecx, fib_msg int 0x80 ; 输出斐波那契数列的前n个数 mov eax, 4 mov ebx, 1 fib_loop: ; 输出当前斐波那契数列的数值 push ebx push fib_num call printf add esp, 8 ; 计算下一个斐波那契数列的数值 add ebx, eax sub ecx, 1 ; 判断是否还需要继续计算 cmp ecx, 0 jg fib_loop ; 输出换行符 mov eax, 4 mov ebx, 1 mov edx, 1 mov ecx, newline int 0x80 ; 退出程序 mov eax, 1 xor ebx, ebx int 0x80 ``` 这段代码使用了系统调用来获取用户输入的n,并通过循环计算并输出斐波那契数列的前n个数。在每次循环中,使用eax和ebx寄存器来保存当前和前一个斐波那契数列的数值,使用ecx寄存器来保存剩余需要计算的数值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值