2
.model small
.data
nizA db 1,2,3,4,5,6,7,8   
nizB db 8 dup(?)
len equ 8
.code   
main proc
mov si,0
mov di,0
mov cx,len

program: 
    mov al,nizA[si]      ;problem is here it always stores CDh in AL
    cbw                  ;convert AL to AX so i can divide
    mov bl,2             ;The number I want to divide so I test if its even or not
    div bl               ;Overflow message
    cmp ah,0
    je next:
        input:
            mov dl,nizA[si]
            mov nizB[di],dl
            inc di
next:
    add si,2
    loop program
endp
end

我这里有这段代码,用于我需要制作的决赛,非常简单。从给定数组的偶数索引中查找奇数。所以很自然,这意味着我增加SI了 2 并将该数组元素放入AL. 但是无论数组中的数字是什么,存储的AL始终是十六进制数字 CD,然后,如果它按应有的方式存储,我想做CBW转换为AX并能够除以BL 我现在只是有错误来自 EMU 8086 的消息说

除法错误 - 溢出。要手动处理此错误,请更改中断向量表中 INT 0 的地址。

这肯定与CD编号有关,我这里只有两个问题

  1. 正在存储 CD 而不是 1
  2. 溢出(很可能是因为 CD 太高了,但我仍然将数字除以它们只会减少,所以它有点没有意义)
4

2 回答 2

1

您使用 加载cx8因此您的循环将迭代 8 次。但是si每次迭代都会增加 2,因此在前 4 次迭代之后,您已经超过了nizA数组的末尾。

尝试替换mov cx, lenmov cx, len/2.

顺便说一句,检查是否al为奇数的一种更简单、更有效的方法是 do test al, 1,它根据与 1 的按位与来设置标志al

于 2021-09-12T16:35:25.383 回答
1

“正在存储 CD 而不是 1”

当 DOS .EXE 启动时,DS段寄存器不指向程序的 .data 部分!DS段寄存器指向 ProgramSegmentPrefix aka PSP 。这个 256 字节的区域是 DOS 保存有关正在运行的程序的一些重要数据的地方,在这里您可以在偏移地址 128 处检索程序的命令行。

您在代码运行时找到了值 CDh,因为它恰好是 PSP 中的第一个字节。它是int 20h始终开始 PSP 的指令的操作码。

你需要写的是以下内容:

.code   
main proc
mov ax, @data
mov ds, ax

“溢出(很可能是因为 CD 太高了,但我仍然将数字除以它们只会减少,所以它有点没有意义)”

其实也有道理。因为您正在使用CBW将被除数扩展到AX,并且因为AL错误的值是 CDh,所以 in 的新值AX变为 FFCDh。当您的代码然后将其除以 2(使用mov bl, 2 div bl)时,商远大于可以存储在除法专用商寄存器中的商AL。这就是你得到“除法错误”的原因。

解决方案

  • 这次验证除法是否有效的解决方案:
    mov  ax, @data
    mov  ds, ax
    mov  si, 0
    mov  di, 0
    mov  cx, len/2
program: 
    mov  al, nizA[si]
    mov  ah, 0           ; For UNSIGNED division don't use CBW
    mov  bl, 2
    div  bl
    cmp  ah, 0           ; Remainder
    je   next
    mov  dl, nizA[si]    ; Reload
    mov  nizB[di], dl
    inc  di
next:
    add  si, 2
    loop program
  • 避免分裂的解决方案有利于TEST并添加一些额外的改进:
    mov  ax, @data
    mov  ds, ax
    xor  si, si        ; Better than 'mov si, 0` for zeroing a register
    xor  di, di        ; idem
program: 
    mov  al, nizA[si]
    test al, 1
    jz   IsEven
    mov  nizB[di], al  ; Only storing 'odd' values
    inc  di
IsEven:
    add  si, 2         ; Next 'even' index
    cmp  si, len
    jb   program

看看寄存器TEST AL, 1上的非破坏性如何AL,因此您不需要在写入nizB数组之前重新加载值?
另请注意,您并不总是需要单独的循环计数器。在这里,我使用了源数组索引。

于 2021-09-13T23:19:01.153 回答