;Fibonacci
ORG 100h
SECTION .TEXT

   CALL GetInt
   MOV   DL,AL

   CALL  Fibo

   CALL  OutNum

   ;exit to DOS
   MOV  AH,4Ch
   INT  21h


;read digit chars, convert to int, until any non-digit char entered
;only working up to couple of thousand, then "Divide Overflow"
GetInt:
    PUSH BX
    PUSH CX
    PUSH DX
    PUSH DI
    MOV  BX,0      ;accumulating total number
;get first digit:
    MOV  AH,01     ;read char from stdin, with echo.  into AL
    INT  21h
    CMP  AL,30h    ;char-'0'
    JL   doneNum
    CMP  AL,39h    ;char-'9'
    JG   doneNum
    SUB  AL,30h    ;convert from ascii digit to number
    MOV  BL,AL     ;keep total in BX

;get subsequent digits
    MOV  CH,0      ;clear hi byte of CX
nextD:
    MOV  AH,01     ;read char from stdin, with echo.  into AL
    INT  21h
    CMP  AL,30h    ;char-'0'
    JL   doneNum
    CMP  AL,39h    ;char-'9'
    JG   doneNum
    SUB  AL,30h    ;convert from ascii digit to number
    MOV  CL,AL     ;save to CL.
    MOV  AX,BX     ;current total
    MOV  DI,10     ;multiplier
    MUL  DI        ;multiply by 10. DX,AX=AX*DI
    ADD  AX,CX     ;add digit to total
    MOV  BX,AX     ;back to BX
    JMP  nextD
doneNum:
    MOV  AX,BX
    POP  DI
    POP  DX
    POP  CX
    POP  BX
    RET


;Fibonacci number
; returns AX = F(DL)

; BX holds F(i-1)
; CX holds previous F(i)
; DL holds n counter--
;Loop n times C=A, A=A+B, B=C

Fibo:
    PUSH BX
    PUSH CX
    PUSH DX
    
    MOV  AX,1 ;AX is F(i), here F(1)
    MOV  BX,1 ;BX is F(i-1), here F(0)

NextI:
    MOV  CX,AX   ;save F(i)
    ADD  AX,BX   ;F(i+1)=F(i)+F(i-1)
    MOV  BX,CX   ;previous F(i) is now F(i-1)
    DEC  DL      ;n counter--
    JNZ  NextI   ;until count down to zero

    POP DX
    POP CX
    POP BX
    RET


;convert AX to decimal and output the digits
OutNum:
    PUSH  AX
    PUSH  BX
    PUSH  DX
    PUSH  SI
    
    MOV   DX,10    ;div and mod by 10 each iteration
    MOV   BX,digitBuf  ;address of buffer
    MOV   SI,4     ;buffer index.  five iterations for the 5 digits
NextDig:
    DIV   DL          ;AL=AX/10  AH=AX%10
    MOV   [BX+SI],AH  ;remainder (last digit) to buffer
    MOV   AH,0        ;clear high byte.  AL has quotient
    DEC   SI
    JNS   NextDig     ;until negative

    MOV   SI,0        ;index into buffer
NextOut:
    MOV   DL,[BX+SI]  ;char param to display
    ADD   DL,30h      ;offset to ASCII digit char.
    MOV   AH,02       ;write char to screen INT
    INT   21h
    INC   SI
    CMP   SI,5
    JNZ   NextOut

    POP   SI
    POP   DX
    POP   BX
    POP   AX
    RET


SECTION .DATA
digitBuf: DB  "     "   ;five bytes
