DOSBox上的8086程序集:idiv指令的错误?
我在帮我的一个朋友调试他的程序,我们把范围缩小到这里竟然出现了问题:DOSBox上的8086程序集:idiv指令的错误?
.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
指令之后,该指令出于某种原因修改了cs
和ip
寄存器,并且在两条看似随机的指令将它们恢复为指向idiv
行之后,再次无限次地执行它。
有没有人有任何解释?
这个问题是其他分裂相关失败的变体。该x86
tag wiki有一些额外的链接:
idiv
/div
问题:Zeroedx
first, or sign-extendeax
into it.。 32bitdiv
故障如果64b/32b => 32b商实际上不符合32b。
明显随机代码的调试器似乎跳到是算术异常处理程序(也同实施除以零)。发生什么事是您的代码正在经历Division Overflow
。你正在做一个16位/ 8位IDIV。从文档:
签署的鸿沟AX由r/m8,结果存储在:AL←商,AH←余数。
你会发现,为师带一个8位的除数(在你的情况BL)为商范围为-128至+127。 044c0h IDIV 85是207(十进制)。 207不适合签名的8位寄存器,因此会导致分区溢出并导致意外问题。
要解决这个问题,您可以移动一个16位的除数。因此,您可以将您的除数放入BX(16位寄存器)。那将是mov bx, 85
。不幸的是,它并不那么简单。当使用16位分频因子时,处理器假定分辨率为32位,高位16位,DX,低位16位,AX。
签名除法DX:AX by r/m16,结果存储在AX←商,DX←余数中。
要解决此问题,您必须在AX上签名扩展16位值。这很简单,因为在将值放入AX之后,您只需要使用指令。从指令设定的基准
DX:AX←AX的符号扩展。
有效如果AX的最高有效位(MSB)为0 DX将成为0。如果MSB为1则DX将成为0FFFFH(设置为一个所有位)。数字的符号位是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
因为你的部门的签字商不能在8位寄存器(_AL_)严丝合缝你会得到算术溢出。 r16/r8 [IDIV](http://www.felixcloutier.com/x86/IDIV.html)上商的范围是-128到+127。你的部门产量为207. –
@MichaelPetch:是的。我正要提交这个答案,但你打败了我! – wallyk
这将是INT 00h中断处理程序。有点令我惊讶的是,它只是跳回到破损的代码,导致无限循环。我本来会期望它终止应用程序,打印一条错误消息,或者更明显一些。你是多少天里第二个被这个困惑的人。 –