gpt4 book ai didi

assembly - DOSBox : Bug with idiv instruction? 上的 8086 程序集

转载 作者:行者123 更新时间:2023-12-04 17:43:57 27 4
gpt4 key购买 nike

我正在帮助我的一个 friend 调试他的程序,我们将其缩小到一个甚至在这里也会发生的问题:

.MODEL small
.STACK 16
.CODE
start:
mov ax, 044c0h
mov bl, 85
idiv bl
exit:
mov ax, 4c00h
int 21h

end start

用 tasm 4.1 组装后,在 DOSBox 0.74 上运行,进入无限循环。使用 Turbo 调试器检查它时,可以看到它发生在 idiv 之后。指令,出于某种原因修改了 csip寄存器,并在两条看似随机的指令后将它们恢复为指向 idiv行,无限次地再次执行它。

有没有人对此有任何解释?

最佳答案

这个问题是其他部门相关失败的变体。 x86 tag wiki有一些额外的链接:



您的调试器似乎跳转到的明显随机代码是算术异常处理程序(也与除以零相同)。发生的情况是您的代码遇到了 Division Overflow .你正在做一个 16 位/8 位 IDIV .从文档:

Signed divide AX by r/m8, with result stored in: AL ← Quotient, AH ← Remainder.



enter image description here

您会注意到,对于使用 8 位除数(在您的情况下为 BL)的除法,商的范围是 -128 到 +127。 044c0h IDIV 85 是 207(十进制)。 207 不适合有符号的 8 位寄存器,因此您会遇到除法溢出和意外问题的原因。

要解决此问题,您可以向上移动到 16 位除数。因此,您可以将除数放在 BX(16 位寄存器)中。那将是 mov bx, 85 .不幸的是,事情并没有那么简单。当使用 16 位除数时,处理器假定被除数为 32 位,其中 DX 为高 16 位,AX 为低 16 位。

Signed divide DX:AX by r/m16, with result stored in AX ← Quotient, DX ← Remainder.



要解决此问题,您必须对 AX 中的 16 位值进行符号扩展。这很简单,因为您只需要使用 CWD将值放入 AX 后的指令。来自指令集引用

DX:AX ← sign-extend of AX.



如果 AX 的最高有效位 (MSB) 为 0,则 DX 将变为 0。如果 MSB 为 1,则 DX 将变为 0ffffh(所有位设置为 1)。数字的符号位是 MSB。

考虑到所有这些,您的除法代码可以调整为采用 16 位除数:
mov ax, 044c0h
cwd ; Sign extend AX into DX (DX:AX = 32-bit dividend)
mov bx, 85 ; Divisor is 85
idiv bx ; Signed divide of DX:AX by BX

关于assembly - DOSBox : Bug with idiv instruction? 上的 8086 程序集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43574914/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com