0

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
Pero Peric
  • 27
  • 1
  • 3
  • 1
    `div cx` with `cx=10` would divide by 10 not 2 obviously. Also you never even use the result. While using division is fine in the general case, for powers of two you normally use bitwise operatins. – Jester Jun 07 '18 at 15:04
  • will this work for division by 2? `mov cx, 2 ;; idiv cx ;; push ax` – Pero Peric Jun 07 '18 at 15:15
  • Yes that will work, although it's unclear why you are pushing the result to the stack, especially since your question title says "count". – Jester Jun 07 '18 at 15:16
  • For that i'm trying also in the same code to calculate length,sum,average – Pero Peric Jun 07 '18 at 15:28
  • 1
    None of which require the saving of the quotient on the stack. – Jester Jun 07 '18 at 15:29
  • `idiv` or `div` will work only with valid input values, your piece of code doesn't seem to set them up correctly, consult the x86 instruction manual for details about `div` or `idiv`. ... (oh, actually there's `mov dx,0`... I'm blind already. But that will work only for non-negative values, while `idiv` is rather used for signed math) – Ped7g Jun 07 '18 at 15:30
  • i'll try to finish this, probably gonna need some more help – Pero Peric Jun 07 '18 at 15:35
  • edited and got stuck again.. – Pero Peric Jun 07 '18 at 19:22
  • 2
    The best way to count even numbers is probably to count odd numbers and do `even = length - odd`. Odd numbers have their low bit set, so you can do `odd += (*p++) & 1`. e.g. `lodsw` / `and ax, 1` / `add dx, ax`. – Peter Cordes Jun 08 '18 at 02:13

1 Answers1

1
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

Sep Roland
  • 33,889
  • 7
  • 43
  • 76