Pero Peric
Pero Peric

Reputation: 27

assembly 8086, count even numbers in array

So I came across one example in my box for assembly 8086 and i could use some help with completing the code

So example goes like this: there is an array of integers, calculate number of even elements in the array

.model small
.stack
.data
arr dw 10 dup (1,2,3,4,5,6,7,8,9,10)
msg db 'number of even elements is:', '$'   ;;
.code
;printing
print proc a:word

        push bp
        mov bp, sp

        mov ax, a
        mov cx, 10
        mov bx, 0
        cmp ax, 0  

        jne begin
        mov dl, 0
        add dl, '0'
        mov ah, 2
        int 21h
        jmp toend

    begin: 
        cmp ax, 0
        je print

        mov dx, 0
        div cx

        push dx
        inc bx
        jmp begin

    print:   

        cmp bx, 0
        je kraj

        pop dx
        add dl, '0'
        mov ah, 2
        int 21h

        dec bx
        jmp print

toend:
        mov dl, 10 
        mov ah, 2
        int 21h

        pop bp
        ret 2

print endp

main:

    mov ax, @data
    mov ds, ax

    mov ax, ;number
    call print
    jmp fin

I looked at some previous code and somehow tried to make this work..

So my question is am I at right path at all, should I use idiv instruction or?

EDIT: I can't seem to get anything else beside "21243" as a result, and by the way i tried to calculate some other things and got lost in the process,here's the complete code:

; there is an array of integers.  calculate the number of
; even elements in the array.

.model small
.stack
.data
arr dw 10 dup (1,2,3,4,5,6,7,8,9,10)
msg db 'Average (in procents): ', '$'
msg1 db 'Average of even elements: ', '$'
msg2 db 'Sum  is:', '$'  ;;
msg3 db 'Number of even elements is :', '$'   ;;
limit dw ? ; length * 2, because we save dw (length of 2 bytes)
number dw 2345     ;;
sum dw 0   ;;
.code
print proc a:word

        push bp
        mov bp, sp

        mov ax, a
        mov cx, 10
        mov bx, 0
        cmp ax, 0  

        jne begining
        mov dl, 0
        add dl, '0'
        mov ah, 2
        int 21h
        jmp toend

    begining:
        cmp ax, 0
        je print

        mov dx, 0
        div cx

        push dx
        inc bx
        jmp begining

    print:  

        cmp bx, 0
        je toend

        pop dx
        add dl, '0'
        mov ah, 2
        int 21h

        dec bx
        jmp print

toend:
        mov dl, 10
        mov ah, 2
        int 21h

        pop bp
        ret 2

print endp

main:

    mov ax, @data
    mov ds, ax

    mov ax, number
    call print
    jmp fin




    shl ax, 1           ;mul 2
    mov limit, ax

    mov bx, 0
    mov cx, 2

poc:

    cmp bx, limit
    je k

    mov ax, arr[bx]
    ;mov dx, 0 ;
    ;div cx    ;
    cwd

    idiv cx  ;signed division
    cmp dx, 0
    jne  jumpp

    mov ax, number
    inc ax
    mov number, ax

    mov ax, sum
    add ax, arr[bx]
    mov sum, ax

jumpp:

    add bx, 2 ;because 'length' of elements is 2 bytes
    jmp poc

k:

    mov ax, 100
    mov bx, number
    mul bx

    mov dx, 0     ; xor dx, dx
    mov bx, length arr  ; length of array = 10 so this is mov bx, 10
    div bx    

    mov es, ax
    mov dl, offset msg
    mov ah, 9
    int 21h

    mov ax, es
    push ax
    call print

    ; mov dl, offset msg2
    ; mov ah, 9
    ; int 21h

    mov ax, sum
    push ax
    call print

    ; mov dl, offset msg3
    ; mov ah, 9
    ; int 21h

    mov ax, number
    push ax
    call print

    ; mov dl, offset msg1
    ; mov ah, 9
    ; int 21h

    mov ax, sum
    mov dx, 0
    cwd
    mov bx, number
    cmp bx, 0
    je here
    idiv number

    push ax
    call print
    jmp fin

here:
    mov dl, 0
    add dl, '0'
    mov ah, 2
    int 21h

fin:
    mov ah, 4ch
    int 21h

end main

Upvotes: 0

Views: 7008

Answers (1)

Sep Roland
Sep Roland

Reputation: 39236

mov ax, number
call print
jmp fin

Don't think about counting even numbers for now. First you need to get displaying the number right.
Also because of the jmp fin instruction none of the additional instructions is executed anyway.

Your print procedure has several problems:

  • You end it with ret 2 which means that it should be called with a word-sized argument pushed on the stack, but there isn't!

  • You've passed the argument via the AX register, but almost immediately you destroy it with mov ax, a.

  • Your print procedure contains a label with the same name print. Knowing that emu8086 is kind of broken software, I coudn't tell that the call print instruction reaches the procedure or the label.

Next code should work. Verify that it does and build upon it. Add small things to it (just a few lines of code) and don't continue adding more until it works as it should!

.model small
.stack
.data
    number dw 2345

.code

; IN (ax) OUT () MOD (ax,bx,cx,dx)
print:
    mov  cx, 10     ; Constant divider
    mov  bx, 0      ; Count pushes
  divide:
    mov  dx, 0      ; Dividing DX:AX
    div  cx
    push dx
    inc  bx
    cmp  ax, 0
    jne  divide
  show:
    pop  dx         ; Always at least 1 pop here
    add  dl, '0'
    mov  ah, 02h    ; DOS.DisplayCharacter
    int  21h
    dec  bx
    jnz  show
    mov  dl, 10     ; Linefeed, Don't you need carry return (13) too?
    mov  ah, 02h
    int  21h
    ret

main:
    mov ax, @data
    mov ds, ax

    mov ax, number
    call print
    jmp fin

    ...

fin:
    mov  ax, 4C00h  ; DOS.Terminate
    int  21h

end main

For further reading and to better understand why the above code works see Displaying numbers with DOS

Upvotes: 1

Related Questions