Home > Blockchain >  Assembly language code is giving inaccurate results. (8086 emulator)
Assembly language code is giving inaccurate results. (8086 emulator)

Time:03-26

I need to write a code in 8086 emulator where a user gives an input from 0 to 9. If the value is below 3, 'Good morning!' is printed. If the value is greater or equal to 4 and less than 6 (just 4 and 5, basically), 'Good afternoon!' is printed. If the value is greater or equal to 8, 'Good night!' is printed. For the values 3, 6 and 7, the system does nothing. However, in my case, I am getting an output for these three values as well. What are the issues with my code?

.MODEL SMALL
.STACK 100H
.DATA  
    STRING1 DB "Enter number:$"
    STRING2 DB "Good morning!$"
    STRING3 DB "Good afternoon!$"  
    STRING4 DB "Good night!$"
.CODE
 MAIN PROC
    
    MOV AX , @DATA
    MOV DS , AX
    LEA DX , STRING1
    MOV AH , 9
    INT 21h
    
    MOV AH , 1
    INT 21h
    SUB AL , 30h
    
    CMP AL , 3
    JL good_morning
    
    CMP AL , 6
    JL next_check
    
    CMP AL , 8
    JGE good_night
    
    good_morning:
    LEA DX , STRING2
    MOV AH , 9
    INT 21h
    JMP exit_label
    
    next_check:
    CMP AL , 4
    JGE good_afternoon
    
    good_afternoon:
    LEA DX , STRING3
    MOV AH , 9
    INT 21h
    JMP exit_label
    
    good_night:
    LEA DX , STRING4
    MOV AH , 9
    INT 21h
    JMP exit_label    
    
    exit_label:
    MOV AX , 4C00H
    INT 21h
    
    
 MAIN ENDP
 
END MAIN

CodePudding user response:

The first issue with your code is that there are no comments! Assembly is hard enough to read with comments; don't make it harder on yourself (or whoever has to go back and maintain this code later). Discipline yourself to write the comments when you write the code. No one ever wants to go back later and just write the comments. As a bonus, writing the comments will (hopefully) force you to think through the logic as you write the code.

[I]n my case, I am getting an output for these three values [3, 6 and 7] as well.

Start by tracing the logic of the code, stepping through it and "executing" it in your head. Since most of the input-processing is working OK, we can assume that the code that reads the input is correct, so we'll start just after that:

CMP AL , 3
JL good_morning    ; if AL < 3, jump to "good_morning"; otherwise, fall through

CMP AL , 6
JL next_check      ; if AL < 6, jump to "next_check"; otherwise, fall through

CMP AL , 8
JGE good_night     ; if AL > 8, jump to "good_night"; otherwise, fall through

Ask yourself: What happens if the input value is 3 (since that's the first value for which you're seeing an incorrect output)? Well, it goes to next_check. So, go look at that code:

next_check:
CMP AL , 4
JGE good_afternoon   ; if AL >= 4, jump to "good_afternoon"; otherwise, fall through

good_afternoon:
LEA DX , STRING3
MOV AH , 9
INT 21h
JMP exit_label

Oops! You fall through to good_afternoon no matter what the input value is! If AL is greater than or equal to 4, you jump to it; otherwise, you fall through. But what you fall through to is exactly the same as what you jump to, so you're going to see the output for "good afternoon" for an input value of 3. This is wrong.

You could fix it by adding an unconditional jump after the conditional one:

next_check:
CMP AL , 4
JGE good_afternoon   ; if AL >= 4, jump to "good_afternoon"; otherwise, fall through
JMP exit_label

good_afternoon:
LEA DX , STRING3
MOV AH , 9
INT 21h
JMP exit_label

But this is less efficient (and less readable, in my opinion) than reversing the logic of the comparison and thus the direction of the branch:

next_check:
CMP AL , 4
JL  exit_label     ; if AL < 4, jump to "exit_label"; otherwise, fall through

good_afternoon:
LEA DX , STRING3
MOV AH , 9
INT 21h
JMP exit_label

Based on this technique, you should be able to trace through your code for the other inputs that produce invalid outputs and correct the problem in a similar way.

  • Related