Home > front end >  Code stuck at an infinite loop when finding the nth fibonacci number
Code stuck at an infinite loop when finding the nth fibonacci number

Time:12-20

I was trying to find the nth Fibonacci number e.x n=3, output = 1

so my logic was this

a = 0
b = 1
input n
si 0

n>2
loop
temp = b
b = a b
a = b
loop if si/=cx

print b

This is my pseudo code logic. When I tried to implement this I am stuck in an infinite loop


.MODEL SMALL
.STACK 100h
.DATA
 STRING0 DB 'Enter INDEX $'           
.CODE
    MAIN PROC
        MOV AX,@DATA
        MOV DS,AX  
        
        LEA DX, STRING0  
        MOV AH,9
        INT 21H  
        
        
        MOV AH, 2  
        MOV DL,0AH    ;NEW LINE
        INT 21H
        MOV DL,0DH 
        INT 21H   
        
  
        MOV AH,1
        INT 21H 
        SUB CX,CX
        MOV CL,AL
        MOV SI,0
        MOV AX,0
        MOV BX,1
        

        LOOP1:
        
        PUSH BX
        ADD BX,AX
        POP AX
        INC SI
        
        LOOP LOOP1
             
        MOV DX,BX
        MOV AH,9
        INT 21H
         

     MAIN ENDP
END MAIN

I use EMU 4.08. The code us stuck at an infinite loop. I have no idea why

I did SUB cx,cx to move the AL value to CL and use CL as counter otherwise it gives me error that the code failed to send 8bit data to 16bit

CodePudding user response:

I think this should be good:

.MODEL SMALL
.STACK 100h
.DATA
 STRING0 DB 'Enter INDEX $'
 STRING1 DB 'OUTPUT: $'           
.CODE
    MAIN PROC
        MOV AX,@DATA
        MOV DS,AX  
        
        LEA DX, STRING0  
        MOV AH,9
        INT 21H  
        
        
        MOV AH, 2  
        MOV DL,0AH    ;NEW LINE
        INT 21H
        MOV DL,0DH 
        INT 21H   
        
  
        MOV AH,1
        INT 21H 
        SUB CX,CX 
        SUB AL,30H  ;To convert char into digit value
        MOV CL,AL 
        MOV SI,0
        MOV AX,0
        MOV BX,1
        

        LOOP1:
        
        PUSH BX
        ADD BX,AX
        POP AX
        INC SI
        
        LOOP LOOP1
                
        MOV AH, 2  
        MOV DL,0AH    ;NEW LINE
        INT 21H
        MOV DL,0DH 
        INT 21H 
            
        LEA DX, STRING1  
        MOV AH,9
        INT 21H   
        
        ;Print the result
        MOV AX,BX
        MOV SI,0 
        ;Push digits from right to left into stack
        LOOP2:
        MOV DL,10
        DIV DL
        PUSH AX 
        MOV AH,0 
        INC SI
        CMP AL,0
        JNE LOOP2 
        ;Pop digits from stack and print them      
        LOOP3:
        POP DX
        MOV DL,DH
        MOV DH,0
        ADD DL,30H ;To convert digit to char
        MOV AH,2
        INT 21H 
        
        DEC SI
        CMP SI,0
        JNE LOOP3
                            
                
        HLT

     MAIN ENDP
END MAIN

CodePudding user response:

I was trying to find the nth Fibonacci number e.x n=3, output = 1

From your example I understand that you consider the Fibonacci sequence to begin with 0, 1, 1, 2, 3, 5, 8, 13, 21, ...
Fibonacci himself started his sequence from 1, 2, 3, 5, 8, ...
See the Wikipedia article https://en.wikipedia.org/wiki/Fibonacci_number

I didn't follow your pseudo code too much as it has flaws of its own!

Why your assembly program fails

  • You say your "code is stuck at an infinite loop", but that's not really the case. It is just that your loop executes an extra 50 iterations. The reason is that the DOS.GetCharacter function 01h gives you an ASCII code, that you have to convert into the digit that the pressed key represents. eg. If you press 3, DOS gives you AL=51, and you need to subtract 48 to obtain the inputted digit which is 3.
    But wait, don't use this number 3 as your loop counter already! Since the 1st and 2nd Fibonacci numbers are known from the start, calculating the 3rd Fibonacci number requires just 1 iteration of the loop. Account for this and subtract 2 beforehand.

  • Once your program has found the answer you simply move the result from BX to DX, and expect the DOS.PrintString function 09h to output the number. It can't do that. It's a function that outputs a series of characters and your result is still a number in a register. You have to convert it into its textual representation. Displaying numbers with DOS has all the fine details about this conversion!

Next code allows the user to input a single-digit from 1 to 9

  ...
  mov  ah, 01h   ; DOS.GetCharacter
  int  21h       ; -> AL is ["1","9"]
  sub  al, 48    ; -> AL is [1,9]
  cbw
  mov  cx, ax    ; -> CX is [1,9]
  xor  ax, ax
  dec  cx
  jz   PrintIt   ; 1st Fib is 0
  inc  ax
  dec  cx
  jz   PrintIt   ; 2nd Fib is 1
  cwd
CalcIt:          ; 3rd Fib and others
  xchg ax, dx
  add  ax, dx
  loop CalcIt
PrintIt:         ; AX is at most 21 (because of the limited input)
  aam
  add  ax, 3030h ; Conversion into text
  xchg al, ah
  cmp  al, '0'
  mov  dh, 02h   ; DOS.PrintCharacter
  xchg ax, dx
  je   Ones
  int  21h
Ones:
  mov  dl, dh
  int  21h

Because in your program the output is very limited, I used a special code to display at most 2 digits. For the general case of outputting numbers see this Q/A.

  • Related