2

Write a complete assembly program to read 8 digits, each digit separated by a single space from the keyboard (use single key input function). Convert them from character to numbers and calculate the average, lowest and highest score and display them on the screen.

Hint: Subtract 30h from each character to get actual digit. Before display, add 30h to each digit. For division operation, use appropriate shift instruction.

Average is showing the wrong answer! Where did I do wrong? Plz help me understand division by SRH instruction.

Include emu8086.inc
.model small
.stack 100h  
.data

 
.code
 mov bh,0
 mov bl,9  
 mov ah,1
 mov dh,0
 mov cx,0    
 
 input:    
 int 21H   
 putc 20h
 sub al,30h
 inc cx
 add dh,al
 cmp al,bh
 JA _max
 cmp al,bl
 JB _min  
 cmp cx,8
 JB input
 
 
 print:
 mov ah,2 
 printn
 mov dl,bh 
 add dl,30h
 printn "Max: "
 int 21h
   
 printn
 mov dl,bl
 add dl,30h
 printn "Min: "
 int 21h 
 
 AND dh, 0FH
 
 mov Cl,3
 shr dh,cl
 
 or dh,30H
 
 printn
 mov dl,dh
 printn "Avg: "
 int 21h 
 
 exit:
 mov ah,4ch
 int 21h
 
 _max:
 mov bh,al 
 cmp al,bl
 JB _min  
 cmp cx,8
 jae print
 jb input
 
 _min:
 mov bl,al
 cmp cx,10
 jae print
 jb input
Kaiser
  • 39
  • 4
  • 3
    It's `SHR` not `SRH`, but that is fine in the code. Yes, you can divide by 8 like that. The problem is you should be dividing the sum. Also, the sum should not be masked to 4 bits. – Jester Dec 29 '20 at 20:42

1 Answers1

4

Dividing by 8 of an unsigned number is the same as shifting the number 3 times to the right. In 8086 programming we need to put the shift count in the CL register before executing the shr instruction. Because you have placed the sum (that you want to divide) in the DH register and you want to display the average (result from the division) from the DL register (requested by the DOS.PrintChar function), you can do this in just 2 instructions:

mov cl, 11   ; 11 = 3 (is divide DH by 8) + 8 (is move DH to DL)
shr dx, cl

_min:
mov bl,al
cmp cx,10

Just like the _max, this _min should be using cmp cx, 8.

Better still, you should probably not duplicate that much code! Below code uses the opposite conditions and keeps everything nicely together:

.code
  mov bx, 9    ; BH=0 is Max, BL=9 is Min
  xor dx, dx   ; DH=0 is Sum, DL=0 is Count
input:
  mov ah, 01h  ; DOS.GetCharacter
  int 21h  
  putc 20h
  sub al, 30h
  add dh, al   ; Add to Sum DH
  cmp al, bh
  jbe NotMax
  mov bh, al   ; Set new max BH
NotMax:
  cmp al, bl
  jae NotMin
  mov bl, al   ; Set new Min BL
NotMin:
  inc dx       ; Increment Count DL
  cmp dl, 8
  jb input

Don't forget to add some meaningful comments in your programs so people can quickly understand what you have written.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • @zx485: That's what I thought at first, but then realized it was intentionally shifting 8 + 3 = 11 to emulate `mov dl,dh` / `shr dl,3`. (Which would be faster on CPUs without a barrel shifter, so every count takes a clock. But for code-size this is good. And yes I know shr dl,3 without using CL needs 186 or later.) – Peter Cordes Dec 30 '20 at 00:49
  • @PeterCordes: Thank you for this explanation. I underestimated the cleverness of the optimized code. Pardon me. – zx485 Dec 30 '20 at 00:53