8086 Assmlby中的简单斐波那契打印机

时间:2018-07-21 16:23:58

标签: assembly dos x86-16

几天前,我开始学习汇编语言,我正在尝试制作一个程序,以打印最多5个字符的 fibonacci系列,但是我的代码可以打印出奇怪的字符< / p>

我以为是因为ASCII转换系统,但是即使我将数值48加到数字上,它仍然是不正确的。

.model small 
.data
  lastFib DB 0
.code
  main PROC
    mov cx,5
    mov dl,48
  loopy: 
    add dl,lastFib 
    mov ah,2h          
    int 21h
    mov lastFib,dl   
    loop loopy 
  ENDP
end main

2 个答案:

答案 0 :(得分:1)

  

但是我的代码打印出了奇怪的字符

仅需添加48即可将(小)数字输出为字符。您一定不能允许这个增加的48篡改斐波那契数的计算。在下面的代码中,我在调用DOS之前以及刚将其取回之后立即添加48。

当前,您的代码根本不计算任何斐波那契数。基本方案是:

xchg dl, lastFib   ; Exchange current with previous
add  dl, lastFib   ; Add previous to current

有6个位数的斐波那契数字:1、1、2、3、5、8。
通过输出之前计算下一个斐波那契数字,下面的代码设法在一个循环中打印所有6个数字。已计算出第七个数字(13),但从未显示。

.model small 
.data
  lastFib DB 0       ;previous
.code
  main PROC
    mov  cx, 6
    mov  dl, 1       ;current
  loopy:
    add  dl, 48      ;make character
    mov  ah, 02h
    int  21h
    sub  dl, 48      ;take back
    xchg dl, lastFib
    add  dl, lastFib
    loop loopy
  ENDP
end main

作为替代方案,它表明可以避免使用慢速loop指令:

.model small 
.data
  lastFib DB 0       ;previous
.code
  main PROC
    mov  dl, 1       ;current
  loopy:
    add  dl, 48      ;make character
    mov  ah, 02h
    int  21h
    sub  dl, 48      ;take back
    xchg dl, lastFib
    add  dl, lastFib
    cmp  dl, 10
    jb   loopy
  ENDP
end main

这次,循环仅持续DL中的数字保持一位数字。

答案 1 :(得分:0)

我没有您的汇编程序(MASM?),但是代码相当简单,应该可以使用。

C和其他语言打印数字的一种简单方法是使用递归函数。但是组装起来很困难。在这里,我先计算位数,然后一一打印出来。由于AX最多可保留5位数字,因此无循环操作非常简单,而且实际上更好。

.model small 
.data

.code
main PROC
            mov     di, 0       ; Fibonacci(n-1); n = 1
            mov     si, 1       ; Fibonacci(n);   n = 1

loopA:      mov     ax, si      ; prepare for counting digits
            xor     cx, cx      ; cx will be number of digits
            mov     bx, 10      ; print as decimal
loopDigit:  xor     dx, dx      ; dx:ax is the dividend
            div     bx
            inc     cx
            or      ax, ax      ; test if the quotient is 0
            jnz     loopDigit
            ; cx should be the number of digit

            mov     bp, si      ; the number to be printed
            cmp     cx, 5       ; test if there are 5 digits
            jb      digit4
            mov     ax, bp      ; get the number
            mov     bx, 10000
            div     bx
            mov     bp, dx      ; the next number to be printed
            mov     dl, al      ; the quotient, current digit
            add     dl, 48      ; convert to ASCII
            mov     ah, 2h
            int     21h
digit4:     cmp     cx, 4       ; test if there are 4 or more digits
            jb      digit3
            mov     ax, bp      ; get the number
            mov     bx, 1000
            div     bx
            mov     bp, dx      ; the next number to be printed
            mov     dl, al      ; the quotient, current digit
            add     dl, 48      ; convert to ASCII
            mov     ah, 2h
            int     21h
digit3:     cmp     cx, 3       ; test if there are 4 or more digits
            jb      digit2
            mov     ax, bp      ; get the number
            mov     bx, 100
            div     bx
            mov     bp, dx      ; the next number to be printed
            mov     dl, al      ; the quotient, current digit
            add     dl, 48      ; convert to ASCII
            mov     ah, 2h
            int     21h
digit2:     cmp     cx, 2       ; test if there are 4 or more digits
            jb      digit1
            mov     ax, bp      ; get the number
            mov     bx, 10
            div     bx
            mov     bp, dx      ; the next number to be printed
            mov     dl, al      ; the quotient, current digit
            add     dl, 48      ; convert to ASCII
            mov     ah, 2h
            int     21h
digit1:     mov     dx, bp      ; always need to print the last digit
            add     dl, 48      ; convert to ASCII
            mov     ah, 2h
            int     21h

            add     di, si      ; Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2)
            jc      done        ; overflow, done!
            xchg    di, si      ; to keep them in order; si = F(n); di = F(n-1)
            jmp     loopA
done:
ENDP
end main

使用循环打印会更加复杂,因为我们需要在使用除数(并在每个循环中进行调整)之前计算除数(下面的cx

.model small 
.data
.code
main PROC
            mov     di, 0       ; Fibonacci(n-1); n = 1
            mov     si, 1       ; Fibonacci(n);   n = 1

            mov     cx, 1       ; 10^n_digits
loopA:      mov     ax, si      ; prepare for counting digits
            mov     bx, 10      ; print as decimal
loopDigit:  xchg    ax, cx      ; calculate 10^n_digits
            mul     bx
            xchg    cx, ax
            xor     dx, dx      ; can be omitted, dx should be 0
            div     bx
            or      ax, ax      ; test if the quotient is 0
            jnz     loopDigit

            mov     bx, si
            mov     bp, 10
loopPrint:  mov     ax, cx      ; need to divide cx by 10 first
            xor     dx, dx
            div     bp
            mov     cx, ax
            mov     ax, bx      ; get the number
            xor     dx, dx
            div     cx
            mov     bx, dx      ; the next number to be printed
            mov     dl, al      ; the quotient, current digit
            add     dl, 48      ; convert to ASCII
            mov     ah, 2h
            int     21h
            cmp     cx, 1       ; should end?
            jnz     loopPrint

            add     di, si      ; Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2)
            jc      done        ; overflow, done!
            xchg    di, si      ; to keep them in order; si = F(n); di = F(n-1)
            jmp     loopA
done:
ENDP
end main