8086 assembly on DOSBox: Bug with idiv instruction?

那年仲夏 提交于 2019-11-26 02:21:29
Michael Petch

This question is a variation on other division related failures. The x86 tag wiki has some additional links:


The apparently random code your debugger seems to jump to is the Arithmetic Exception handler (also the same one as Divide by Zero). What is happening is that your code is experiencing a Division Overflow. You are doing a 16-bit/8-bit IDIV. From the documentation:

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

You will notice that for division with an 8-bit divisor (in your case BL) the range for the quotient is -128 to +127. 044c0h IDIV 85 is 207 (decimal). 207 doesn't fit in a signed 8-bit register so you get division overflow and the cause of your unexpected problem.

To resolve this you can move up to a 16-bit divisor. So you can place your divisor in BX (16-bit register). That would be mov bx, 85. Unfortunately it isn't so simple. When using a 16-bit divisor the processor assumes the dividend is 32-bits with high 16-bits in DX and lower 16-bits in AX.

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

To resolve this you have to sign extend the 16-bit value in AX. This is simple as you only need to use the CWD instruction after placing the value in AX. From the instruction set reference

DX:AX ← sign-extend of AX.

Effectively if the Most Significant Bit (MSB) of AX is 0 DX will become 0. If the MSB is 1 then DX would become 0ffffh (all bits set to one). The sign bit of a number is the MSB.

With all this in mind your division code could be adjusted to take a 16-bit divisor:

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!