题目

从键盘输入n,计算其对应的斐波那契函数的fib(n),并输出结果。

流程图

思路

  1. 第二步定义的子程序的功能是这样子的。假如 a = 0,b = 1;此时定义c = b,b = b + c,a = c。这个功
    能就意义递归推荐斐波那契数列,最后b值就是fib(n),这里递归的此时可能是输入的n值要减去1,因为
    fib(1) = 1;
  2. 在字符串转化为数的时候,可以采取str = ‘123’ 从字符串表头取值,清空S = 0, S = S * 10 + str[i] -
    30H;然后i从0到2;字符串的输入不宜过长,不然寄存器无法保存fib(n)。
  3. 输入功能调用和输出功能调用

MOV DL,48 ; 十进制的48对应的ASCII值为0
MOV AH,0200H
int 21H ;会将字母0打印到屏幕上 MOV AH
0100H int 21H ;系统产生中断,直至从键盘录入一个字符至AL寄存器中

效果图

fib(2) = 1,fib(3) = 2,fib(123) = 41026

实现代码

; 0 1 2 3 4 5 6 7  8  9  10 11 12  13  14  15  16  17   18   19   20   21    22    23    24
; 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368
.model small
.data
str db 2 dup(10)  ; 保存输入
fib dw 0,1,23 dup(-1)  ; 保存斐波那契数
.stack
dw 128 dup(?)
.code
start:

mov ax, @data
mov ds, ax

mov si, 0  ; 下标
mov cx, 2

s1:
mov ah, 01h ; 输入
int 21h
cmp al, 13  ; 判断是否回车
je break1
sub al, 48  ; ASCII(0) = 48
mov str[si], al
inc si
loop s1

break1:
cmp cx, 0  ; 如果输入了 2 个数则换行
jne exit
mov dl, 10
mov ah, 02h
int 21h
exit:

cmp cx, 0
je next
; 1 位数
mov cl, str[0]
mov ch, 0
jmp short break2
next:  ; 2 位数
mov al, str[0]
mov ah, 10
mul ah
mov bl, str[1]
mov bh, 0
add ax, bx
mov cx, ax
break2:

call function

mov ax, bx
mov bx, 0  ; 栈的高度
mov cx, 5  ; 0 - 65535 最大位数为 5

s2:
mov dl, 10
div dl
mov dh, 0
mov dl, ah
push dx
inc bx
mov ah, 0
cmp ax, 0
je break3
loop s2

break3:
mov cx, bx

s3:
pop dx
add dl, 48
mov ah, 02h
int 21h
loop s3

mov ax, 4c00h
int 21h

function:
push ax  ; 保存 ax,因为乘法需要用到 ax
mov al, cl
mov ah, 0
mov dl, 2
mul dl
mov si, ax  ; 2 * cx 对应斐波那契数组的坐标
cmp fib[si], -1  ; 检查是否已经计算过
je calculate
mov bx, fib[si]  ; 直接使用计算好的值
jmp short return
calculate:

dec cx
call function
mov ax, bx
dec cx
call function
add ax, bx
mov bx, ax

add cx, 2  ; 恢复 cx
mov al, cl
mov ah, 0
mul dl
mov si, ax  ; 将计算好的数值放入斐波那契数组中
mov fib[si], bx

return:
pop ax
ret

end start

实现效果