Search code examples
assemblyx86-16emu8086

Allocate and initialize a vector of 20 elements in the range [20-200]. Calculate and print the average of elements divisible by 3


I don't know what I'm doing wrong. I'm a beginner. Please help me.
This is my code:

DOSSEG
.MODEL SMALL
.STACK 32

.DATA
        VECTOR           DB 5 DUP(20H,20H,20H)           ;20 DE NR PE MAXIM 3 CIFRE
        KBD              DB 4,0,0,0,0,0
        TEN_POWER        DW 100,10,1
        NUMERE           DB 0Dh,0Ah,'Nr=$'
        MEDIE_ELEM_DIV3  DB 0
        NR_ELEMENTE_DIV3 DB 0
        SUMA             DW 0
        MSJ_SUMA         DB 'SUMA=$'
        FLAG             DB 0
        MSJ_CONTOR       DB 'NR_DIV3=$'
        NUMAR            DW 0
        NUMASC           DB 0Dh,0Ah,'Suma=     $'

.CODE
        START:         
                       MOV  AX, @DATA
                       MOV  DS, AX

                       CALL CITESTE
                       CALL CRLF
                       CALL AFISARE
                       CALL CRLF

                       CALL SUMA_NUMERE
                       CALL AFISARE_SUMA
                       CALL CRLF
                       CALL AFISARE_CONTOR


                       MOV  AH, 4CH
                       INT  21H

        CITESTE:       
                       MOV  CX, 5
                       MOV  DI,(OFFSET VECTOR)+3
        AGAIN:         PUSH CX
                       MOV  DX,OFFSET NUMERE
                       MOV  AH,9
                       INT  21H                            ; afiseaza sir de interogare

    
                       MOV  [KBD+1],0
                       MOV  AH,0Ah
                       MOV  DX,OFFSET KBD
                       INT  21H                            ; citeste numar cu 1 pana la 3 cifre
    
                       MOV  CL,[KBD+1]
                       MOV  CH,0
                       MOV  SI,(OFFSET KBD)+2
                       PUSH DI
                       SUB  DI,CX

        NEXT:          
                       MOV  AL,[SI]
                       MOV  [DI],AL
                       INC  SI                             ; memoreaza numar
                       INC  DI
                       LOOP NEXT
                       POP  DI
                       ADD  DI,3
                       POP  CX
                       LOOP AGAIN
                       RET
    
        AFISARE:       
                       MOV  CX, 5
                       MOV  SI,OFFSET VECTOR
        DISP:          
                       CALL CRLF
                       PUSH CX
                       MOV  CX,3

        NUM:           
                       MOV  AH,2
                       MOV  DL,[SI]
                       INT  21h                            ; afiseaza sirul de numere

                       INC  SI
                       LOOP NUM

                       POP  CX
                       LOOP DISP
                       RET
    
        CRLF:          
                       MOV  AH,2
                       MOV  DL,0Ah
                       INT  21h
                       MOV  AH,2
                       MOV  DL,0Dh
                       INT  21h
                       RET


       
        SUMA_NUMERE:   
                       MOV  CX, 5                          ;ITERARE CELE 20 ELEM VECTOR
                       MOV  SUMA, 0                        ; INITIALIZARE CU 0
                       MOV  [NR_ELEMENTE_DIV3], 0
                       MOV  BP, 0
        
        ASC_BIN:       
                       PUSH CX
                       MOV  CX, 3                          ;AM 3 CIFRE
                       MOV  BX, 10
                       MOV  SI, OFFSET VECTOR
                       
        AGAIN2:        MOV  AX,[NUMAR]
                       MUL  BX                             ; inmulteste suma partiala cu 10
                       MOV  DL,[SI]
                       MOV  DH,0
                       AND  DL,0FH                         ; conversie ASCII binar pentru cifra curenta
                       ADD  AX,DX                          ; aduna cifra curenta
                       MOV  [NUMAR],AX                     ;NUMAR E NR MEU IN BINAR

                       LOOP AGAIN2
                       POP  CX

                       CMP  BP, 35H
                       JE   END
                       INC  BP
        CONDITIE_DIV3: 
                       XOR  AX,AX

                       MOV  AX,[NUMAR]                     ;PUN IN AX NR IN BINAR
                       MOV  BL, 3
                       DIV  BL                             ;IMPART ELEMENTUL LA 3

                       CMP  AH, 0                          ;COMPAR RESTUL CU 0
                       JNE  NU_E_DIV3

                       ADD  [SUMA], AX                     ;ADAUGA IN SUMA NR DIV 3
                       ADD  [NR_ELEMENTE_DIV3], 1
                       INC  SI
                       

                      
        NU_E_DIV3:     
                       INC  SI
                       JMP  AGAIN2

        END:           RET


              
        AFISARE_SUMA:  
        BIN_ASC:       MOV  CX,4                           ; din numere binare pe 16 biti
        ; pot rezulta siruri ASCII cu 5 cifre
                       MOV  SI,OFFSET TEN_POWER            ; pointer spre tabela puterilor lui 10
                       MOV  DI,(OFFSET NUMASC)+7
        NEXT3:         
                       MOV  AX,[SUMA]
                       MOV  DX,0                           ; pregateste deimpartitul pe 32 de biti
                       DIV  WORD PTR [SI]                  ; obtine catul curent
                       MOV  [SUMA],DX                      ; salveaza restul curent
                       OR   AL,30H                         ; salveaza codul ASCII al cifrei curente
                       MOV  [DI],AL
                       INC  DI
                       ADD  SI,2                           ; avanseaza pointerul spre urmatoarea putere a lui 10
                       LOOP NEXT3
                       OR   DL,30H                         ; salveaza codul ASCII al ultimei cifre (cifra unitatilor)
                       MOV  [DI],DL

                       MOV  AH, 09h
                       MOV  DX, OFFSET NUMASC
                       INT  21H

                       RET

        AFISARE_CONTOR:
                       AND  [NR_ELEMENTE_DIV3], 0FH        ; masca ultimii 4 biti - obtinem cifra coresp caracterului
                       MOV  AH, 2                          ;pregatire pt afisarea caracterului
                       MOV  DL, 0DH                        ; carriage return
                       INT  21H                            ;apelarea intreruperii
                       MOV  AH, 2
                       MOV  DL, 0AH                        ;line feed
                       INT  21H
        

        REZULTAT:      
                       MOV  AH, 9                          ;pregatirea pentru afisarea unui string
                       MOV  DX, OFFSET MSJ_CONTOR          ;sirul FINAL 'NR_DIV3='
                       INT  21H

                       MOV  AL, [NR_ELEMENTE_DIV3]         ;NUMARUL
                       MOV  AH, 0                          ; deimpartitul este ax
                       MOV  BL, 10                         ;impartitorul
                       DIV  BL                             ;imparitm ax la bl -> al = catul si ah = restul
                       PUSH AX                             ;salvez pe stiva rez impartirii
                       CMP  AL, 0                          ;daca suma are o singrua cifra
                       JE   O_CIFRA                        ; sare si nu o mai afiseaza pe prima

                       MOV  DL, AL                         ; pt afisarea catului, adica a primei cifre din suma
                       OR   DL, 30H                        ;codul ascii al caracterului coresp cifrei din tabela ascii
                       MOV  AH, 2
                       INT  21H

        O_CIFRA:       
                       POP  AX                             ;scoate din stiva continutul reg ax
                       MOV  DL, AH                         ;pt afisarea restului, adica celei de a doua cifre
                       OR   DL, 30H                        ;obtinerea caract corespunzator
                       MOV  AH, 2                          ;pregatirea pt afisare
                       INT  21H                            ;apelarea intreruperii
                       RET
        

    END START
  • I stored the numbers that I read from the stdin in ASCII and in the function where I want to make the sum.
  • I iterate the array and convert each element in binary
  • Then I tried to check the divisibility by dividing the number with 3.

But it doesn't work. It shows me the sum 0 and the contor of the numbers that are divisible with 3 to be 1.

I would appreciate any helpful input.


Solution

  • NUMAR is not correct

    Each time that you want to calculate it, you need to reset its value to zero beforehand. And in the AGAIN2 loop you forgot to increment SI so as to use all the different digits. Once this inc si is in place, you no longer need the other INC SI instructions that you have around the label NU_E_DIV3:.

        mov  NUMAR, 0    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        MOV  CX, 3        ; AM 3 CIFRE
        MOV  SI, OFFSET VECTOR
    AGAIN2:
        MOV  AX, 10
        MUL  NUMAR        ; inmulteste suma partiala cu 10
        MOV  DL, [SI]
        AND  dx, 000Fh    ; conversie ASCII binar pentru cifra curenta
        ADD  AX, DX       ; aduna cifra curenta
        MOV  NUMAR, AX    ; NUMAR E NR MEU IN BINAR
        inc  si          <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        LOOP AGAIN2
    

    SUMA is 3x smaller

    Because you add AX to SUMA directly after you divided AX by 3, what you add will not reflect the original value of NUMAR.

        MOV  AX, NUMAR   ; PUN IN AX NR IN BINAR
        MOV  BL, 3
        DIV  BL          ; IMPART ELEMENTUL LA 3
        CMP  AH, 0       ; COMPAR RESTUL CU 0
        JNE  AGAIN2      ; NU_E_DIV3
        mov  ax, NUMAR  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        ADD  [SUMA], AX
        inc  [NR_ELEMENTE_DIV3]
        JMP  AGAIN2
    

    SUMA_NUMERE does not loop good

    You have MOV CX,5 that you don't use later on, and you have CMP BP, 35H JE END that is much more than you have data items for!
    You need to choose which you want to use...

    AFISARE_SUMA does too much

    The TEN_POWER list has but 3 elements. You can't iterate 4 (+ 1) times (; pot rezulta siruri ASCII cu 5 cifre).