This program takes user input as an array and then determines the number of even numbers and prints them. This program is written using 8086 assembly language using emu8086 software.
TITLE PUCHTAA
.MODEL SMALL
.STACK 100H
.DATA
MSG1 DB 0AH, 0DH, "THIS PROGRAM ACCEPTS SIZE OF ARRAY AND ELEMENTS THEN PRINTS EVEN NUMBERS$"
MSG DB 0AH, 0DH, "ENTER A LENGHT OF ARRAY: $"
ARRAY DB 0AH, 0DH, "ENTER ELEMENTS OF ARRAY$"
EVEN DB 0AH, 0DH, "TOTAL EVEN NUMBERS ARE $"
CONTINUE DB 0AH, 0DH, "CONTINUE? [Y/N] $"
NOEVEN DB 0AH, 0DH, "NO EVEN NUMBERS IN ARRAY!!$"
.CODE
MAIN:
MOV AX, @DATA
MOV DS, AX
LEA DX, MSG1
MOV AH, 09H
INT 21H
CONT:
LEA DX, MSG
MOV AH, 09H
INT 21H
MOV AH, 01H
INT 21H
SUB AL, 30H
MOV CL, AL
LEA DX, ARRAY
MOV AH, 09H
INT 21H
MOV CH, 00H
AGAIN:
MOV DL, ' '
MOV AH, 02H
INT 21H
MOV AH, 01H
INT 21H
SUB AL, 30H
MOV AH, 00H
MOV BL, 02H
AAD
DIV BL
CMP AH, 00H
JE INCREASE
RETURN:
DEC CL
CMP CL, 00H
JG AGAIN
CMP CH, 00H
JE NOEVENS
LEA DX, EVEN
MOV AH, 09H
INT 21H
JMP NUM
NOEVENS:
LEA DX, NOEVEN
MOV AH, 09H
INT 21H
JMP QUEST
NUM:
MOV DL, ' '
MOV AH, 02H
INT 21H
POP AX
MOV DL, AH
ADD DL, 30H
MOV AH, 02H
INT 21H
DEC CH
CMP CH, 00H
JNE NUM
QUEST:
LEA DX, CONTINUE
MOV AH, 09H
INT 21H
MOV AH, 01H
INT 21H
OR AL, 20H
CMP AL, 'y'
JE CONT
JMP EXIT
INCREASE:
MOV AH, AL
ADD AH, AL
PUSH AX
INC CH
JMP RETURN
EXIT:
MOV AH, 4CH
INT 21H
END MAIN

2 comments:
Nice idea for a short 8086 program. However, it has a few flaws:
1. It expects only one ASCII character, so technically user can input only numbers from '0' (ASCII `0x30`) to '9' (ASCII `0x39`). However, there is no check whether user pressed a number key, or any other key - only `0x30` is subtracted from `AL` after the `INT 0x21` call.
2. It always tries to read at least one number to the "array" (in this case it stores EVEN numbers on a stack, and ignores the rest), but what if user presses '0'?
3. A few optimizations can be made, for instance: you don't need any fancy dividing, when you can just check if the number given by the user has the last bit set or clear, by using a bitwise AND with a immediate value `0x01` (`0000 0001 b`).
Possible solutions:
• Line 28 (getting the array size):
```
mov ah,0x01
int 0x21
cmp al,'0'
jb NOT_A_NUMBER ; "JUMP BELOW": if ASCII is 0x00 to 0x2F
cmp al,'9'
ja NOT_A_NUMBER ; "JUMP ABOVE": if ASCII is 0x3A to 0xFF
sub al,0x30 ; now we can continue - we have a valid digit
test al,al ; bitwise operaions are widely used to optimize code
; especially here where we just test for a ZERO byte
; instructions `CMP AL,0` and `TEST AL,AL` both take two bytes,
; but `CMP reg,0` would take three bytes for other registers
jz QUEST ; skip if array size is ZERO
; place somewhere a "NOT_A_NUMBER" label, showing a warning message,
; then go to the "QUEST" label
```
• Line 48 (checking if the number is even)
```
mov ah,0x01
int 0x21
cmp al,'0'
jb NOT_A_NUMBER
cmp al,'9'
ja NOT_A_NUMBER
test al,0x01 ; performs bitwise AND without affecting AL
jz INCREASE ; result will be ZERO for EVEN numbers
RETURN:
dec cl
jnz AGAIN ; you can check the result immediately after INC or DEC,
; we are not dealing with negative numbers
; and we skipped the case when user pressed '0'
; (so we won't roll from 0x00 to 0xFF)
```
• Line 109 (optimizing the "INCREASE" code due to the change above)
```
push ax ; AL still holds the ASCII number, nothing else needs to be done
inc ch
jmp RETURN
```
• Line 77 (printing the EVEN numbers)
```
mov dl,' '
mov ah,0x02
int 0x21
pop dx ; DL now holds the number digit, AH still holds 0x02
int 0x21
dec ch
jnz NUM
```
Much appreciated you detailed analytical comment and suggestion. as long as array length 0 is concerned my mind thought array length cannot be zero so user wouldn't enter 0. I will update this program. and thank you again for detailed analysis.
Post a Comment