Finding the word with the maximum sum of even decimal digits

60 views Asked by At

This x86 assembly code defines two procedures: "addev" to compute the sum of even digits in a word and "maxArray" to find the word with the maximum sum of even digits in an array. It takes an array of words and its length as input, iterates through the array, calculates the sum of even digits for each word, and returns the word with the maximum even digit sum in AX. I'm unable to understand how to do the second procedure. So far I got to this point. I tried everything but couldn't do it. Please help me.

.model small
.stack 100h
.data
A dw 1489, 32661, 31248, 24788, 13499, 28
N dw 6
.code
mov ax, @data
mov ds, ax
push offset A
push N
call maxArray


.exit
addev proc near
    push bp
    mov bp, sp
    mov ax, [bp + 4]
    mov bx, 10
    mov ch, 0
next:
    mov dx, 0
    div bx
    mov dh, dl
    and dl, 1
    jnz cont
    mov dl, dh
    mov dh, 0
    add ch, dl
cont:
    cmp ax, 0
    jne next
    mov al, ch
    mov bx,[bp+4]
    pop bp
    ret 2
addev endp

maxArray proc near
    push bp
    mov bp, sp
    mov bx, 0
    mov cx, 0
    mov di, [bp + 6]
    mov si, di 
next1:
    cmp cl, [bp + 4]
    je ext
    push [di]
    call addev
    pop [di]
    inc di
    inc di
    cmp ch, al
    ja cont2
    cmp ch, al
    jne check
    cmp bx, [si]
    jae cont2
    mov si, di
cont2:
    inc cl
    jmp next1
check:
    mov ch, al
    mov si, di
    jmp cont2
ext:
    mov ax, [si] 
    pop bp
    ret 4
maxArray endp
end

I tried ChatGPT, debugging, and asking friends, but so far I did not succeed.

1

There are 1 answers

0
Sep Roland On

Some errors

  • The maxArray procedure uses the CH register to store the intermediate result, but the addev procedure also uses CH for its own purposes. Either preserve the register in addev, or alternatively use another register. The largest sum that you can expect is 36 (from an array element like 48888), therefore a byte-sized register will do.
    My code below will use the BP register instead because that's a preserved register anyway!

  • push [di]
    call addev
    pop [di]
    

    Because the addev procedure used ret 2 on exit, the argument that was pushed to the stack was removed automatically. The pop [di] instruction is harmful and must be removed.

Some tips

  • mov bx,[bp+4]
    

    There's no need for the addev procedure to return the array element's value in the BX register. The parent procedure can just as easy re-read the array element using the address in DI.

  • mov dh, dl
    and dl, 1
    jnz cont
    

    To find out if the lowest bit is set, it is better to use the non-destructive test dl, 1 instruction. That way you don't need to make a copy first.

Some code (untested)

.model small
.stack 100h
.data
A dw 1489, 32661, 31248, 24788, 13499, 28
N dw 6
.code
mov  ax, @data
mov  ds, ax
push offset A
push N
call maxArray
.exit

addev proc near
    push bp
    mov  bp, sp
    mov  ax, [bp + 4] ; An array element
    mov  di, 10       ; CONST
    xor  bp, bp       ; Sum of the even digits
next:
    xor  dx, dx
    div  di
    test dx, 1
    jnz  IsOdd
    add  bp, dx       ; DX={0,2,4,6,8}
IsOdd:
    test ax, ax
    jnz  next
    mov  ax, bp
    pop  bp
    ret  2
addev endp

maxArray proc near
    push bp
    mov  bp, sp
    xor  ax, ax       ; Always return something meaningful
    mov  cx, [bp + 4] ; Length of the array
    jcxz done 
    mov  si, [bp + 6] ; Address of the array
    xor  bp, bp       ; Largest sum of even digits
next1:
    lodsw
    push ax
    call addev        ; -> AX
    cmp  ax, bp
    jbe  NotBetter
    mov  bp, ax
    mov  bx, si       ; Because of LODSW that adds 2 to SI, this points behind the concerned array element
NotBetter:
    dec  cx
    jnz  next1
    mov  ax, [bx - 2] ; The element with the largest sum of even digits
done:
    pop  bp
    ret  4
maxArray endp
end