这个问题是其他除法相关失败的变体。这x86标签维基 https://stackoverflow.com/tags/x86/info有一些额外的链接:
-
idiv
/ div
问题: Zero edx首先,或符号扩展eax进去。 https://stackoverflow.com/questions/38416593/why-should-edx-be-0-before-i-use-div-opcode/38416896#38416896。 32位div
如果 64b/32b => 32b 商实际上不适合 32b,则会出错。
您的调试器似乎跳转到的明显随机代码是算术异常处理程序(也与除以零相同)。发生的情况是您的代码正在经历Division Overflow
。你正在做一个16位/8位IDIV http://www.felixcloutier.com/x86/IDIV.html。从文档中:
有符号 AX 除以 r/m8,结果存储在:AL ← 商,AH ← 余数。
您会注意到,对于具有 8 位除数的除法(在您的情况下BL) 商的范围是 -128 到 +127。 044c0hIDIV85 是 207(十进制)。 207 不适合有符号的 8 位寄存器,因此您会遇到除法溢出以及意外问题的原因。
要解决此问题,您可以将除数提高到 16 位。所以你可以把你的除数放在BX(16 位寄存器)。那将是mov bx, 85
。不幸的是事情没那么简单。当使用 16 位除数时,处理器假定被除数为 32 位,其中高 16 位为DX和低 16 位AX.
有符号 DX:AX 除以 r/m16,结果存储在 AX ← 商,DX ← 余数中。
要解决此问题,您必须对 16 位值进行签名扩展AX。这很简单,因为您只需要使用CWD http://www.felixcloutier.com/x86/CWD:CDQ:CQO.html将值放入后的指令AX。来自指令集参考
DX:AX ← AX 的符号扩展。
有效地,如果最高有效位 (MSB)AX is 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