assemblymasmirvine32

Assembly Language program stuck in an infinite loop


My program seems to be stuck in a loop after the program prompts the user to input the paragraph.

TITLE CSC221A4  (CSC2214.asm)

INCLUDE Irvine32.inc

.data
mainMenu1   BYTE    " ", 0Ah, 0Ah, 0Ah
            BYTE    "       Main Menu           ", 0Ah
            BYTE    " 1. Count and Display number of characters (Press 1)   ", 0Ah, 0Ah
            BYTE    " 2. Count and display number of words (Press 2) ", 0Ah, 0Ah
            BYTE    " 3. Count and display number of sentences (Press 3) ", 0Ah, 0Ah
            BYTE    " 4. Count and display numbers of letters that are equal to 'N' or 'n'  (Press 4)", 0Ah, 0Ah
            BYTE    " 5. Count and display number of capital letters (Press 5) ", 0Ah, 0Ah
            BYTE    " 6. Count and display number of vowels (Press 6) ", 0Ah, 0Ah

prompt1     BYTE " ", 0Ah, 0Ah
            BYTE "Please enter your paragraph. Press $ to end.",0Ah, 0Ah, 0
prompt2     BYTE " ", 0Ah, 0Ah
            BYTE " '$' was entered. Paragraph will now calculate.", 0Ah, 0Ah, 0 

prompt3     BYTE "Calculating choice ", 0Ah, 0Ah, 0 
prompt4     BYTE "Number of characters: ",0 
prompt5     BYTE "Number of words: ",0
prompt6     BYTE "Number of sentences: ",0 
prompt7     BYTE "Number of letters equal to 'N' or 'n': ",0 
prompt8     BYTE "Number of capital letters: ",0 
prompt9     BYTE "Number of vowels: ",0 

Sentinel    BYTE '$'
thirdLetter BYTE 'N' , 'n'
space       BYTE ' '

num_char    DWORD ?
num_words   DWORD ?
num_sentences   DWORD ?
num_thirdLetter DWORD ?
num_capLetter   DWORD ?
num_vowels  DWORD ?

.code
main PROC
call mainMenu

exit
main ENDP

mainMenu PROC
mov edx, OFFSET mainMenu1
call WriteString
mov eax, 0;
call ReadChar
cmp al, '1'
jne JUMPLABEL1
call Option1

JUMPLABEL1:
cmp al, '2'
jne JUMPLABEL2
call Option2

JUMPLABEL2:
cmp al, '3'
jne JUMPLABEL3
call option3

JUMPLABEL3:
cmp al, '4'
jne JUMPLABEL4
call option4

JUMPLABEL4:
cmp al, '5'
jne JUMPLABEL5
call option5

JUMPLABEL5:
cmp al, '6'
call option6
exit 
mainMenu ENDP

Option1 PROC
mov edx, OFFSET prompt1
call WriteString
mov eax, 0
mov num_char, 1
mov num_words, 1
mov num_sentences, 1
mov num_thirdLetter, 1
mov num_capLetter, 1
mov num_vowels, 1

L1:
call ReadChar
call WriteTempOutput 
cmp al, Sentinel
jne Not_Sentinel_Flag
mov edx, OFFSET prompt2
call WriteString
jmp End_Flag
Not_Sentinel_Flag:
cmp al, space
jne Not_New_Char_Flag
inc num_char 
Not_New_Char_Flag:
cmp al, 0dh
jne Not_New_Line_Flag
inc num_char
Not_New_Line_Flag:
jmp L1;
End_Flag:
call Display_Char_Results
Option1 ENDP 

Option2 PROC
mov edx, OFFSET prompt1
call WriteString
mov num_words, 1
mov num_sentences, 1
mov num_thirdLetter, 1
mov num_capLetter, 1
mov num_vowels, 1

L1:
call ReadChar
Call WriteTempOutput
cmp al, sentinel
jne Not_Sentinel_Flag
mov edx, OFFSET prompt2
call writestring
jmp End_Flag
Not_Sentinel_Flag:
cmp al, space
jne NOT_NEW_WORD_FLAG
inc num_words
NOT_NEW_WORD_FLAG:
cmp al, 0dh
jne Not_New_Line_Flag
inc num_words
Not_New_Line_Flag:
jmp L1;
End_Flag:
call Display_Word_Results
Option2 ENDP

option3 PROC
mov edx, OFFSET prompt1
call WriteString
mov num_capLetter, 1
mov num_char, 1
mov num_sentences, 1
mov num_thirdLetter, 1
mov num_vowels, 1
mov num_words, 1

L1:
call ReadChar
call WriteTempOutput
cmp al, sentinel
jne Not_Sentinel_Flag
mov edx, OFFSET prompt2
call writestring
jmp End_Flag
Not_Sentinel_Flag:
cmp al, 0dh
jne Not_New_Line_Flag
inc num_sentences
Not_New_Line_Flag:
jmp L1;
End_Flag:
call Display_Sentences_Results
option3 ENDP

option4 PROC
mov edx, OFFSET prompt1
call WriteString
mov num_capLetter, 1
mov num_char, 1
mov num_sentences, 1
mov num_thirdLetter, 1
mov num_vowels, 1
mov num_words, 1

L1:
call readchar
call WriteTempOutput
cmp al, sentinel
jne Not_Sentinel_Flag
mov edx, OFFSET prompt2
call writestring
jmp End_Flag
Not_Sentinel_Flag:
cmp al, 'N'
jne Not_Uppercase_N
inc num_thirdLetter
Not_Uppercase_N:
cmp al, 'n'
jne Not_Letter_N_flag
inc num_thirdLetter
Not_Letter_N_flag:
jmp L1;
End_Flag:
call Display_thirdLetter_results
option4 ENDP

option5 PROC
mov edx, OFFSET prompt1
call writestring
mov num_capLetter, 1
mov num_char, 1
mov num_sentences, 1
mov num_thirdLetter, 1
mov num_vowels, 1
mov num_words, 1

L1:
call readchar
call WriteTempOutput
cmp al, sentinel
jne Not_Sentinel_Flag
mov edx, OFFSET prompt2
call writestring
jmp End_Flag

Not_Sentinel_Flag:
cmp al, 'A' - 'Z'
jbe NOT_Capital_letter
inc num_capLetter
NOT_Capital_letter:
jmp L1;
End_Flag:
call Display_capital_results
option5 ENDP

option6 PROC
mov edx, OFFSET prompt1
call writestring
mov num_capLetter, 1
mov num_char, 1
mov num_sentences, 1
mov num_thirdLetter, 1
mov num_vowels, 1
mov num_words, 1

L1:
call readchar
call WriteTempOutput
cmp al, sentinel

mov edx, OFFSET prompt2
call writestring
OPTION6 endp









Display_char_results PROC
mov edx, OFFSET prompt3
call writestring
mov edx, OFFSET prompt4
call writestring
mov eax, 0
mov eax, num_char
call WriteDec
call crlf
call mainMenu
Display_char_results ENDP

DISPLAY_WORD_RESULTS PROC
mov edx,OFFSET prompt3
call WriteString
mov edx,OFFSET prompt5
call WriteString
mov eax,0
mov eax,num_words
call writeDec
call CRLF
call mainMenu
DISPLAY_WORD_RESULTS ENDP

DISPLAY_sentences_RESULTS PROC
mov edx,OFFSET prompt3
call WriteString
mov edx,OFFSET prompt6
call WriteString
mov eax,0
mov eax,num_sentences
call writeDec
call CRLF
call mainMenu
DISPLAY_sentences_RESULTS ENDP

DISPLAY_thirdLetter_results PROC
mov edx,OFFSET prompt3
call WriteString
mov edx,OFFSET prompt7          
call WriteString
mov eax,0
mov eax,num_thirdLetter
call writeDec
call CRLF
call mainMenu
DISPLAY_thirdLetter_rESULTS ENDP

Display_capital_results PROC
mov edx, OFFSET prompt3
call writestring
mov edx, OFFSET prompt8
call writestring
mov eax, 0
mov eax, num_capLetter
call writeDec
call crlf
call mainMenu
Display_capital_results ENDP

Display_vowels_results PROC
mov edx, OFFSET prompt3
call writestring
mov edx, OFFSET prompt9
call writestring
mov eax, 0 
mov eax, num_vowels
call writeDec
call crlf
call mainMenu
Display_vowels_results ENDP

WriteTempOutput PROC
cmp AL,0Dh          
jne NONEWLINE
mov BL,AL
mov AL,0Ah          
call WriteChar  
mov AL,BL
call WriteChar
ret
NONEWLINE:
call dumpregs
call WriteChar
ret
WriteTempOutput ENDP


exit
END main

Solution

  • Your program mostly has issues with its flow. When we use the call instruction we expect to return here. But your code just screams to jmp so that's the instruction you should use to correct the problems.

    cmp al, '1'
    jne JUMPLABEL1
    call Option1   <-- Change this to   jmp Option1
    
    JUMPLABEL1:
    

    Every time that you have a block of code like the previous you should not CALL but rather JUMP to the relevant Option_ procedure.

    ...
    L1:
    call ReadChar
    call WriteTempOutput 
    cmp al, Sentinel
    jne Not_Sentinel_Flag
    mov edx, OFFSET prompt2
    call WriteString
    jmp End_Flag
    Not_Sentinel_Flag:
    cmp al, space
    jne Not_New_Char_Flag
    inc num_char 
    Not_New_Char_Flag:
    cmp al, 0dh
    jne Not_New_Line_Flag      <-- Change this to   je New_Line_Flag
    inc num_char
    Not_New_Line_Flag:         <-- Change this to   New_Line_Flag:
    jmp L1;
    End_Flag:
    call Display_Char_Results  <-- Change this to   jmp Display_Char_Results
    Option1 ENDP 
    

    In the Option1 procedure you are not really counting the characters! Follow the flow with p.e. AL=65 and you'll see that the num_char variable doesn't get incremented. Also don't CALL the display routine because you programmed that particular display routine to NOT return here. So JMP to it.

    Display_char_results PROC
    mov edx, OFFSET prompt3
    call writestring
    mov edx, OFFSET prompt4
    call writestring
    mov eax, 0             <-- This can savely be deleted
    mov eax, num_char
    call WriteDec
    call crlf
    call mainMenu          <-- Change this to   jmp mainMenu
    Display_char_results ENDP
    

    Every Display_..._results procedure should not CALL but rather JUMP to the mainMenu label. That way you have got a loop that is not rapidly filling the stack and thus avoiding stack overflow.

    JUMPLABEL5:
    cmp al, '6'
    call option6
    exit 
    mainMenu ENDP
    

    In this code snippet you don't do anything with the outcome of the compare. You could do it like

    JUMPLABEL5:
     cmp al, '6'
     jne BadChoice
     call option6       <-- Remember to change this into a jump!
    BadChoice:
     exit 
    mainMenu ENDP