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和