鱼C论坛

 找回密码
 立即注册
查看: 5650|回复: 4

汇编语言递归求解斐波那契数列第N位

[复制链接]
发表于 2021-3-31 15:39:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1.题目:求Fibonacci数FIB
2.要求:
a)程序接收由用户键入的范围在0~100(不包括0和100)之间的n值
b)根据给定的n值,计算Fibonacci数,其定义如下
FIB(1) = 1
FIB(2) = 1
FIB(n) = FIB(n-2) +FIB(n-1)                (n>2)
c)程序输出FIB(n)的值
3.提示:程序可由三部分组成
a)输入部分:程序接收用户键入的十进制n值,转换为2进制后存入num单元中
b)用递归子程序fibp求出FIB(n)的值,结果存放在result单元中。
c)输出部分:把result的值转换为十进制后打印输出


自己不会写这个代码,在网上看到的一个,分析到一半到add65536就看不懂了,有木有大佬能给看一下这是啥意思不 ,或者有哪位哥哥能写出来自己的也可以


datas segment
    str1 db 'please input a number(1-100):n=','$'
    str2 db 13,10,'fib(n)=','$'
    wrongstr db 13,10,13,10,'a number between 1 and 100 please!',13,10,13,10,'$'
    inputbuffer db 3,?,3 dup(?)
    n dw ?
    result1h dw 0
    result1l dw 0
    result2h dw 0
    result2l dw 0
    c10 dw 10
    outputbuffer db 11 dup('0')
datas ends;--------------------定义好要输出的提示语以及出错提示,开辟好四个result单元

codes segment
    assume cs:codes,ds:datas
    start:
    mov ax,datas
    mov ds,ax
    call input;------------------------------------------跳转到输入函数
    call fib;--------------------------------------------跳转到求值函数
    call output;-----------------------------------------跳转到输出函数
    jmp quit;--------------------------------------------跳转到结束函数
    input proc
        jmp t1;------------------------------------------t1为将数据段预存数据输出
        wrong:
            lea dx,wrongstr
        mov ah,9
        int 21h
        t1:
            lea dx,str1
            mov ah,9
            int 21h
            lea dx,inputbuffer
            mov ah,10
            int 21h
            mov ax,0
            mov cl,inputbuffer+1
            mov ch,0
            lea bx,inputbuffer+2
        t2:
            mul c10;-------------------------------------将第一个读入的数乘以10
            mov dl,[bx]
            cmp dl,'0';----------------------------------将输入的数和0比较,如果小于零,错误
            jb wrong
            cmp dl,'9';----------------------------------将输入的数和9比较,如果目标数字只是一位数,前面的乘以10就会错误
            ja wrong
            and dl,0fh;----------------------------------取dl的后四位
            add al,dl
            adc ah,0
            inc bx
            loop t2
            cmp ax,0032h;--------------------------------这里以50为界限,超过50的数其实已经到了32位数的极限了
            ja wrong
            cmp ax,1
            jb wrong
            mov n,ax;------------------------------------将输入的数存到n中
            ret
    input endp
    fib proc
        cmp n,1;-----------------------------------------首先检查n是否等于1,等于1直接跳转到l1
        jz l1
        cmp n,2;-----------------------------------------其次检查n是否等于2,等于2直接跳转到l2
        jz l2
        dec n;-------------------------------------------n减一,准备开始启动递归调用
        call fib;----------------------------------------递归调用fib函数
        mov ax,result2l
        mov dx,result2h
        mov cx,result1l
        add result2l,cx
        mov cx,result1h
        adc result2h,cx
        mov result1l,ax
        mov result1h,dx;---------------------------------循环置换加数
        jmp exit
        l1:
            mov result1l,1
            mov result2l,1
            jmp exit
        l2:
            mov result2l,1
            dec n
            call fib;------------------------------------减一再回到该函数
            exit:ret
    fib endp
    output proc
        mov ax,result2l
        lea si,outputbuffer
        mov cx,5
        r1:
            mov dx,0
            div c10
            inc si
            add [si],dl
            loop r1;-------------------------------------循环5次,将输出缓冲区的数存到内存中
        mov ax,result2h
        lea si,outputbuffer
        mov cx,5
        r2:
            mov dx,0
            div c10
            inc si
            push cx
            cmp dx,0
            je noadd;------------------------------------如果余数为0,说明这个数能被10整除,不是个位数
            mov cx,dx;-----------------------------------将分离出来的个位数存入cx,进行call add65536函数的循环
            addn:
                call add65536
                loop addn
            noadd:
                pop cx
            loop r2
            lea dx,str2
            mov ah,9
            int 21h
            lea si,outputbuffer
            mov bx,10
        r3:
            cmp byte ptr [si+bx],'0'
            ja print;------------------------------------如果大于0就将该数输出
            dec bx
            jmp r3
        print:
            mov dl,[si+bx]
            mov ah,2
            int 21h
            dec bx
            cmp bx,1
            jae print;-----------------------------------bx大于等于1就将[si+di]后的位置的数字输出,否则返回
            ret
    output endp
    add65536 proc
        add byte ptr [si],6
        mov dl,0
        cmp byte ptr [si],3ah
        jb a1
        sub byte ptr [si],10
        mov dl,1
        a1:
            add byte ptr [si+1],3
            add byte ptr [si+1],dl
            mov dl,0
            cmp byte ptr [si+1],3ah
            jb a2
            sub byte ptr [si+1],10
            mov dl,1
        a2:
            add byte ptr [si+2],5
            add byte ptr [si+2],dl
            mov dl,0
            cmp byte ptr [si+2],3ah
            jb a3
            sub byte ptr [si+2],10
            mov dl,1
        a3:
            add byte ptr [si+3],5
            add byte ptr [si+3],dl
            mov dl,0
            cmp byte ptr [si+3],3ah
            jb a4
            sub byte ptr [si+3],10
            mov dl,1
        a4:
            add byte ptr [si+4],6
            add byte ptr [si+4],dl
            mov dl,0
            cmp byte ptr [si+4],3ah
            jb a0
            sub byte ptr [si+4],10
            mov dl,1
        a5:
            add byte ptr [si+5],dl
            mov dl,0
            cmp byte ptr [si+5],3ah
            jb a0
            sub byte ptr [si+5],10
            mov dl,1
        a6:
            add byte ptr [si+6],dl
            mov dl,0
            cmp byte ptr [si+6],3ah
            jb a0
            sub byte ptr [si+6],10
            mov dl,1
        a7:
            add byte ptr [si+7],dl
            mov dl,0
            cmp byte ptr [si+7],3ah
            jb a0
            sub byte ptr [si+7],10
            mov dl,1
        a8:
            add byte ptr [si+8],dl
            mov dl,0
            cmp byte ptr [si+8],3ah
            jb a0
            sub byte ptr [si+8],10
            mov dl,1
        a9:
            add byte ptr [si+9],dl
        a0:
            ret
    add65536 endp
    quit:
        mov ah,4ch
        int 21h
codes ends
end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-3-31 16:54:46 | 显示全部楼层
  1. data segment para public 'DATA'
  2.         db 400h dup(0)
  3. data ends
  4. stack segment para stack 'STACK'
  5.         db 800h dup(0)
  6. stack ends
  7. code segment para public 'CODE'
  8.         assume cs:code , ds:data
  9. fib proc near
  10.         push bx
  11.         cmp ax,2
  12.         ja f1
  13.         mov ax,1
  14.         jmp f2
  15. f1:     dec ax
  16.         push ax
  17.         call fib
  18.         push ax
  19.         pop bx
  20.         pop ax
  21.         dec ax
  22.         call fib
  23.         add ax,bx
  24. f2:     pop bx
  25.         retn
  26. fib endp
  27. main proc far
  28.         mov ax,data
  29.         mov ds,ax
  30.         mov ax,10         ; 计算第 10 项的数值
  31.         call fib          ; ax = 第 10 项的数值  
  32.         xor ax,ax
  33.         int 16h
  34.         mov ax,4c00h
  35.         int 21h
  36. main endp
  37. code ends
  38. end main
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-3-31 19:22:11 | 显示全部楼层

看着你的代码好短小精悍啊,但是这个好像只能算16位的,再往后变数变大就会溢出了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-4-2 00:04:06 | 显示全部楼层
老司机。。 发表于 2021-3-31 19:22
看着你的代码好短小精悍啊,但是这个好像只能算16位的,再往后变数变大就会溢出了

       是啊,16 位、32 位、64 位都有溢出的时候,你能从根本上解决问题吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-4-22 16:03:25 | 显示全部楼层
求任意位的 fibonacii 数,如果位数不够,把 NUM_LEN 改大就可以了。
程序中的用的 40H(64个word)结果可以算到 64*4 = 256 位
  1. assume cs:code,ds:data

  2. data segment
  3.         NUM_LEN                =        40H
  4.         _BASE                =        10000

  5.         _Number1        DW        NUM_LEN        DUP(0)
  6.         _Number2        DW  NUM_LEN        DUP(0)
  7. data ends

  8. code segment
  9. _start:
  10.         MOV                AX,data
  11.         PUSH        AX
  12.         POP                DS
  13.         PUSH        AX
  14.         POP                ES
  15.         MOV                AX,1000
  16.         PUSH        AX
  17.         CALL        _Fibonacii
  18.         PUSH        AX
  19.         CALL        _OutputNumber
  20.         MOV                AX,4C00H
  21.         INT                21H

  22. ;[BP+4]----第几个 fibonacii  数
  23. ;[BP+2]----return address
  24. ;[BP+0]----old bp
  25. _Fibonacii        PROC
  26.         PUSH        BP
  27.         MOV                BP,SP
  28.         PUSH        CX
  29.         PUSH        SI
  30.         PUSH        DI
  31.         PUSHF

  32.         PUSH        WORD PTR [BP+4]
  33.         POP                CX

  34.         LEA                SI,_Number1
  35.         LEA                DI,_Number2
  36.        
  37.         XOR                AX,AX
  38.         ;第一个 Fibonacii 数置0
  39.         MOV                WORD PTR DS:[SI],AX
  40.         INC                AX
  41.         ;第二个 Fibonacii 数置1
  42.         MOV                WORD PTR ES:[DI],AX
  43.        
  44.         DEC                CX
  45.         MOV                AX,SI
  46.         TEST        CX,CX
  47.         JE                @FB_1

  48.         DEC                CX
  49.         MOV                AX,DI
  50.         TEST        CX,CX
  51.         JE                @FB_1
  52.                
  53. @FB_2:
  54.         ;前数 + 后数 =>前数
  55.         PUSH        DI
  56.         PUSH        SI
  57.         CALL        _AddNumber
  58.        
  59.         ;交换前数后数的地址
  60.         XCHG        DI,SI
  61.         LOOP        @FB_2

  62.         MOV                AX,DI

  63. @FB_1:
  64.         POPF
  65.         POP                DI
  66.         POP                SI
  67.         POP                CX
  68.         MOV                SP,BP
  69.         POP                BP
  70.         RET                2
  71. _Fibonacii        ENDP

  72. ;[BP+6]----dst number
  73. ;[BP+4]----src number
  74. ;[BP+2]----return address
  75. ;[BP+0]----old bp
  76. _AddNumber PROC
  77.         PUSH        BP
  78.         MOV                BP,SP
  79.         PUSH        BX
  80.         PUSH        CX
  81.         PUSH        DX
  82.         PUSH        SI
  83.         PUSH        DI
  84.         PUSHF
  85.        
  86.         ;取得加数地址 => DI
  87.         PUSH        WORD PTR [BP+4]
  88.         POP                DI
  89.        
  90.         ;取得被加数地址 => SI
  91.         PUSH        WORD PTR [BP+6]
  92.         POP                SI

  93.         MOV                CX,NUM_LEN
  94.        
  95.         MOV                BX,_BASE
  96.         XOR                DX,DX

  97. @AN_1:
  98.         ;取加数
  99.         LODSW
  100.         ;加数 + 被加数
  101.         ADD                AX,WORD PTR ES:[DI]
  102.         ;加进位
  103.         ADD                AX,DX
  104.         ;计算是否进位
  105.         XOR                DX,DX
  106.         DIV                BX
  107.         XCHG        AX,DX
  108.         ;保存和
  109.         STOSW
  110.         ;和为0了则结束循环
  111.         ADD                AX,DX
  112.         TEST        AX,AX
  113.         JZ                @AN_3
  114.         LOOP        @AN_1
  115.         ;循环结束后加进位
  116.         ADD                WORD PTR [DI],DX
  117. @AN_3:

  118.         POPF
  119.         POP                DI
  120.         POP                SI
  121.         POP                DX
  122.         POP                CX
  123.         POP                BX
  124.         MOV                SP,BP
  125.         POP                BP
  126.         RET                4
  127. _AddNumber ENDP


  128. _OutputNumber PROC
  129.         PUSH        BP
  130.         MOV                BP,SP
  131.         PUSH        BX
  132.         PUSH        CX
  133.         PUSH        DX
  134.         PUSH        SI
  135.         PUSH        DI
  136.         PUSHF
  137.        
  138.         PUSH        WORD PTR [BP+4]
  139.         POP                DI
  140.         MOV                CX,NUM_LEN
  141.         SHL                CX,1
  142.         ADD                DI,CX
  143.         SHR                CX,1
  144.         SUB                DI,2
  145.         STD
  146.         XOR                AX,AX
  147.         REPZ        SCASW
  148.         MOV                SI,DI
  149.         INC                CX
  150.         ADD                SI,2
  151. @ON_1:
  152.         LODSW
  153.         PUSH        AX
  154.         CALL        _OutputWord
  155.         LOOP        @ON_1
  156.        
  157.         CLD
  158.         POPF
  159.         POP                DI
  160.         POP                SI
  161.         POP                DX
  162.         POP                CX
  163.         POP                BX
  164.         MOV                SP,BP
  165.         POP                BP
  166.         RET                2
  167. _OutputNumber ENDP

  168. _OutputWord        PROC
  169.         PUSH        BP
  170.         MOV                BP,SP
  171.         SUB                SP,8
  172.         PUSH        BX
  173.         PUSH        CX
  174.         PUSH        DX
  175.         PUSH        SI
  176.         PUSH        DS
  177.         PUSHF
  178.        
  179.         PUSH        SS
  180.         POP                DS

  181.         MOV                SI,BP
  182.         SUB                SI,8
  183.         MOV                CX,4
  184.         PUSH        WORD PTR [BP+4]
  185.         POP                AX
  186.         MOV                BX,10

  187. @OW_1:       
  188.         XOR                DX,DX
  189.         DIV                BX
  190.         ADD                DL,030H
  191.         MOV                DS:[SI],DL
  192.         INC                SI
  193.         LOOP        @OW_1
  194.        
  195.         MOV                CX,4

  196. @OW_2:
  197.         DEC                SI
  198.         MOV                AH,02H
  199.         MOV                DL,DS:[SI]
  200.         INT                21H
  201.         LOOP        @OW_2

  202.         POPF
  203.         POP                DS
  204.         POP                SI
  205.         POP                DX
  206.         POP                CX
  207.         POP                BX
  208.         ADD                SP,8
  209.         MOV                SP,BP
  210.         POP                BP       
  211.         RET                2
  212. _OutputWord ENDP
  213. code ends
  214. end _start
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-28 12:32

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表