Assembly 组件(8086)中的分区溢出

Assembly 组件(8086)中的分区溢出,assembly,x86-16,Assembly,X86 16,我不知道这个部门溢出的确切定义是什么。你能先解释一下,然后用下面的例子来说明吗 例如,我的书中写到,这段代码导致溢出。我不知道为什么 mov dx,0087h mov ax,6002h mov bx,10h div bx 但这段代码是正确的,不会导致溢出: mov dx,0087h mov ax,6000h mov bx,100h div bx 那么为什么第一个结果是溢出,而第二个结果不是溢出呢?寄存器DX和AX中的被除数实际上是一个32位的数字,在您的示例中是00876002h 它将被除数

我不知道这个部门溢出的确切定义是什么。你能先解释一下,然后用下面的例子来说明吗

例如,我的书中写到,这段代码导致溢出。我不知道为什么

mov dx,0087h
mov ax,6002h
mov bx,10h
div bx
但这段代码是正确的,不会导致溢出:

mov dx,0087h
mov ax,6000h
mov bx,100h
div bx

那么为什么第一个结果是溢出,而第二个结果不是溢出呢?

寄存器
DX
AX
中的被除数实际上是一个32位的数字,在您的示例中是
00876002h

它将被除数
BX
除以,结果(商)应适合寄存器
AX
。无符号除法后的余数将放入寄存器
DX

当您尝试将
00876002h
除以
BX
10h
)的内容时,结果为
87600h
,余数为2。现在您应该了解它触发错误的原因:商
87600h
太大,无法放入16位寄存器
AX


除数溢出(别名除零)发生在除数太小时。当
BX
低于
DX
时,您的示例将溢出寄存器
DX
AX
中的红利实际上是32位数字,在您的示例中是
00876002h

它将被除数
BX
除以,结果(商)应适合寄存器
AX
。无符号除法后的余数将放入寄存器
DX

当您尝试将
00876002h
除以
BX
10h
)的内容时,结果为
87600h
,余数为2。现在您应该了解它触发错误的原因:商
87600h
太大,无法放入16位寄存器
AX


除数溢出(别名除零)发生在除数太小时。当
BX
低于
DX
0x00876002/0x10=0x87600
时,您的示例将溢出,因此
DX:AX/BX
的商不适合AX,因此您会得到一个#DE异常。英特尔的《指令参考手册》(x86 SDM第2卷)对每一条指令都有详细的描述,而
div
的条目解释了这一点。有一个HTML的摘录。有关英特尔文档和其他内容的链接,请参阅

除以10h是右移1个十六进制数字,但输入的高半部DX有2个有效十六进制数字

大多数情况下都是重复的,@rcgldr的答案有扩展精度除法的代码(例如,32位/16位产生32位商和16位余数),使用适用于任意16位除法器的
div


在你的特殊情况下,你要除以2的幂。对于
div
,这是非常低效的

对于这些二次幂划分,您应该使用

; input in DX:AX

shrd ax, dx, 4      ; right shift AX, shifting in bits from DX
shr  dx, 4          ; separately right shift DX

; DX:AX = 0008:7600 = 0x87600 = 32-bit quotient
如果您想要剩余的,它是原始AX的低4位,您应该使用
mov cl,al
/
和cl,0Fh
获得

SHRD只修改其目的地,而不修改源,因此您需要DX上的第二个
shr
。这对于更大的扩展精度移位是有意义的:您希望使用SHRD指令链依次将位移位到每个元素的顶部,而不希望移位为零

或者,如果您不能使用386指令,比如,您可以使用左、右移位和Or来模拟SHRD。原来的8086也没有立即的计数移位,所以您需要在CL中进行计数

; 8086-compatible version of 32-bit division by 10h, i.e. right shift by 4.
; input in DX:AX

mov  bx, dx
mov  cl, 16-4
shl  bx, cl       ; bx = the bits shifted across the 16-bit boundary into low half

mov  cl, 4
shr  ax, cl
shr  dx, cl       ; discards the bits shifted out

or   ax, bx       ; replace the 4 zeros at the top of AX with the bits from DX

; quotient in DX:AX

或者,如果您知道结果不会溢出,比如在除以
100h
(右移8)的情况下,您可以只使用一个SHRD。

0x00876002/0x10=0x87600
,因此
DX:AX/BX
的商不适合AX,因此您会得到一个#DE异常。英特尔的《指令参考手册》(x86 SDM第2卷)对每一条指令都有详细的描述,而
div
的条目解释了这一点。有一个HTML的摘录。有关英特尔文档和其他内容的链接,请参阅

除以10h是右移1个十六进制数字,但输入的高半部DX有2个有效十六进制数字

大多数情况下都是重复的,@rcgldr的答案有扩展精度除法的代码(例如,32位/16位产生32位商和16位余数),使用适用于任意16位除法器的
div


在你的特殊情况下,你要除以2的幂。对于
div
,这是非常低效的

对于这些二次幂划分,您应该使用

; input in DX:AX

shrd ax, dx, 4      ; right shift AX, shifting in bits from DX
shr  dx, 4          ; separately right shift DX

; DX:AX = 0008:7600 = 0x87600 = 32-bit quotient
如果您想要剩余的,它是原始AX的低4位,您应该使用
mov cl,al
/
和cl,0Fh
获得

SHRD只修改其目的地,而不修改源,因此您需要DX上的第二个
shr
。这对于更大的扩展精度移位是有意义的:您希望使用SHRD指令链依次将位移位到每个元素的顶部,而不希望移位为零

或者,如果您不能使用386指令,比如,您可以使用左、右移位和Or来模拟SHRD。原来的8086也没有立即的计数移位,所以您需要在CL中进行计数

; 8086-compatible version of 32-bit division by 10h, i.e. right shift by 4.
; input in DX:AX

mov  bx, dx
mov  cl, 16-4
shl  bx, cl       ; bx = the bits shifted across the 16-bit boundary into low half

mov  cl, 4
shr  ax, cl
shr  dx, cl       ; discards the bits shifted out

or   ax, bx       ; replace the 4 zeros at the top of AX with the bits from DX

; quotient in DX:AX

或者,如果您知道结果不会溢出,比如在除以
100h
(右移8)的情况下,您可以只使用一个SHRD。

琐事-8086和80186的可能重复项的可能重复项将最多移动255次,如果cl>=16,则可用于调零寄存器。对于80286及更高版本,移位计数用01fh屏蔽,仍然足以将16位寄存器归零。对于80386和更高版本的32位模式,移位计数用01fh屏蔽,对于64位模式,移位计数用03fh屏蔽(不足以清除寄存器)。琐事-8086和80186将最多移位255次,如果cl>=16,则可用于调零寄存器。80286和