【问题标题】:assembly 8086, count even numbers in array程序集 8086,计算数组中的偶数
【发布时间】:2018-06-07 15:02:03
【问题描述】:

所以我在我的组装 8086 框中遇到了一个示例,我可以使用一些帮助来完成代码

所以例子是这样的:有一个整数数组,计算数组中偶数元素的个数

.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

我查看了一些以前的代码,并试图以某种方式使其工作..

所以我的问题是我是否走在正确的道路上,我应该使用idiv 指令还是?

编辑: 结果,除了“21243”之外,我似乎无法得到其他任何东西,顺便说一下,我试图计算一些其他的东西并在这个过程中迷失了方向,这是完整的代码:

; 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

【问题讨论】:

  • div cxcx=10 显然会除以 10 而不是 2。你甚至从不使用结果。虽然在一般情况下使用除法很好,但对于 2 的幂,您通常使用按位运算。
  • 这对除以 2 有效吗? mov cx, 2 ;; idiv cx ;; push ax
  • 是的,这会起作用,尽管目前还不清楚为什么要将结果推送到堆栈,特别是因为您的问题标题显示为“count”。
  • 没有一个需要在堆栈上保存商。
  • 计算偶数的最佳方法可能是计算奇数并执行even = length - odd。奇数设置了低位,因此您可以使用odd += (*p++) & 1。例如lodsw / and ax, 1 / add dx, ax.

标签: arrays assembly x86-16 emu8086


【解决方案1】:
mov ax, number
call print
jmp fin

暂时不要考虑计算偶数。首先,您需要正确显示数字。
同样由于jmp fin 指令,任何附加指令都不会执行。

您的打印程序有几个问题:

  • 你用ret 2结束它,这意味着它应该被压入堆栈的字大小的参数调用,但没有!

  • 您已经通过AX 寄存器传递了参数,但您几乎立即使用mov ax, a 将其销毁。

  • 您的print 程序包含一个同名print 的标签。知道emu8086是一种破软件,我不能说call print指令到达程序或标签。

下一个代码应该可以工作。验证它确实如此并以此为基础。向它添加一些小东西(只需几行代码),在它正常工作之前不要继续添加更多!

.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

如需进一步阅读并更好地理解上述代码为何有效,请参阅 Displaying numbers with DOS

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2021-03-10
    • 2022-11-25
    • 1970-01-01
    相关资源
    最近更新 更多