assembly - EMU 8086 在寄存器中存储错误的数组元素值

标签 assembly masm emu8086

.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 code> 转换为 AX 并能够与 BL 相除 我现在只收到来自 EMU 8086 的错误消息:

divide error - overflow. to manually process this error, change address of INT 0 in interrupt vector table.

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

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

最佳答案

“正在存储 CD,而不是 1”

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

当代码运行时,您发现了值 CDh,因为它恰好是 PSP 中的第一个字节。它是始终启动 PSP 的 int 20h 指令的操作码。

您需要编写以下内容:

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

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

其实也有道理。因为您使用 CBW 将被除数扩展到 AX,并且 AL 中的值错误地为 CDh,所以 中的新值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 数组?
另请注意,您并不总是需要单独的循环计数器。这里我使用了源数组索引。

关于assembly - EMU 8086 在寄存器中存储错误的数组元素值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69153092/

相关文章:

assembly - 删除屏幕上的一个字符

loops - x86 程序集中嵌套在另一个循环中的两个循环

assembly - 将字数组复制到双字数组 NASM 程序集

assembly - MASM 在保护模式下生成错误的调用目标

operating-system - MASM 中的微型操作系统

assembly - DosBox如何修复字符属性?

assembly - 添加 4 位数字并显示总和 - 汇编语言

assembly - 汇编中的常量

C++ 变量地址和对齐 | x86

assembly - 在程序集问题中将大写字母转换为小写字母