查找偶数点后十进制数字最大总和的单词

Finding the word with the maximum sum of even decimal digits

提问人:P.I.S 提问时间:9/29/2023 最后编辑:Sep RolandP.I.S 更新时间:10/2/2023 访问量:55

问:

此 x86 汇编代码定义了两个过程:“addev”用于计算单词中偶数的总和,“maxArray”用于查找数组中偶数最大总和的单词。它接受一个单词数组及其长度作为输入,遍历数组,计算每个单词的偶数之和,并返回 AX 中具有最大偶数和的单词。我无法理解如何进行第二个过程。到目前为止,我走到了这一步。我尝试了一切,但做不到。请帮帮我。

.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

我尝试了ChatGPT,调试,并询问了朋友,但到目前为止我没有成功。

数组 程序集 x86 十进制 数字

评论

1赞 Peter Cordes 9/29/2023
最小可重现示例缺少有关运行它时发生的情况的任何调试详细信息,或者您知道存在什么问题但不知道如何解决。此外,标题并没有告诉未来的读者任何关于这个问题的信息,比如如果其他人正在寻找一个关于查找偶数总和的问题,那么谷歌中出现的这个标题看起来就没有用了。
0赞 Erik Eidt 9/29/2023
如果您对汇编语言中的编码、处理器的工作原理、某些特定的指令、某些特定的汇编结构有疑问,请具体搜索/询问。
0赞 Erik Eidt 9/29/2023
另一方面,如果你正在寻找一种算法,你不必在汇编中思考,因为任何语言都可以操纵数组和操纵数字,当你知道你希望函数做什么时,编写汇编要容易得多,所以用 C 语言编写它,测试它以确保它有效, 然后尽可能从字面上转录到程序集。当你有一个算法时,你的汇编问题将是关于汇编语言的。

答:

0赞 Sep Roland 10/2/2023 #1

一些错误

  • maxArray 过程使用 CH 寄存器来存储中间结果,但 addev 过程也使用 CH 来实现自己的目的。要么在 addev 中保留寄存器,要么使用另一个寄存器。您可以期望的最大总和是 36(来自像 48888 这样的数组元素),因此字节大小的寄存器就可以了。
    我下面的代码将改用 BP 寄存器,因为无论如何它都是一个保留的寄存器!

  • push [di]
    call addev
    pop [di]
    

    由于在退出时使用了 addev 过程,因此会自动删除推送到堆栈的参数。该指令是有害的,必须删除。ret 2pop [di]

一些提示

  • mov bx,[bp+4]
    

    addev 过程无需在 BX 寄存器中返回数组元素的值。父过程可以很容易地使用 DI 中的地址重新读取数组元素。

  • mov dh, dl
    and dl, 1
    jnz cont
    

    要确定是否设置了最低位,最好使用非破坏性指令。这样你就不需要先制作副本了。test dl, 1

一些代码(未经测试)

.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