unsigned/signed 分部的汇编程序
Assembly program with unsigned/signed division
我正在尝试编写一个将 1000 除以 5 的简单汇编程序,但我的程序冻结了系统。
程序如下,
include pcmac.inc
.model Small
.586
.stack 100h
.data
const db 5
Main PROC
_Begin
mov AX, 1000
idiv const // Problem line
_Exit 0
Main ENDP
End Main
如果我使用无符号除法 div
而不是有符号除法 idiv
,问题就会消失。
谁能解释为什么?
我知道除法的唯一条件是被除数必须是除数的两倍。还有什么我想念的吗?
const
是一个字节。当您执行 IDIV byte_divisor
时,商将放在 AL
中,范围为 -128 到 127。1000 / 5 为 200,这不在允许范围内。如果您使用 DIV
,商的范围是 0 到 255,这就是您的示例在这种情况下有效的原因。
如果您想 IDIV
1000 乘以 5,您应该改用 16 位除数。但是您需要记住,在使用 IDIV r/m16
时,您实际上是在划分由 DX
和 AX
组成的 32 位双字(DX
持有最高有效位,AX
最低有效位)。
来自英特尔的手册:
IDIV r/m16 Signed divide DX:AX by r/m16, with result stored in AX ← Quotient, DX ← Remainder.
IF OperandSize = 16 (* Doubleword/word operation *)
THEN
temp ← DX:AX / SRC; (* Signed division *)
IF (temp > 7FFFH) or (temp < 8000H)
(* If a positive result is greater than 7FFFH
or a negative result is less than 8000H *)
THEN
#DE; (* Divide error *)
ELSE
AX ← temp;
DX ← DX:AX SignedModulus SRC;
因此,在 IDIV
之前,您应该根据 AX
中的值在 DX:AX
中创建一个带符号的双字。有一条名为 CWD
的指令正是这样做的:
The CWD
instruction
copies the sign (bit 15) of the value in the AX
register into every bit position in the DX
register.
即:
.data
const dw 5 ; now a word
.code
mov ax,1000
cwd ; sign-extend ax into dx
idiv const
; quotient is in ax, remainder in dx
我正在尝试编写一个将 1000 除以 5 的简单汇编程序,但我的程序冻结了系统。
程序如下,
include pcmac.inc
.model Small
.586
.stack 100h
.data
const db 5
Main PROC
_Begin
mov AX, 1000
idiv const // Problem line
_Exit 0
Main ENDP
End Main
如果我使用无符号除法 div
而不是有符号除法 idiv
,问题就会消失。
谁能解释为什么?
我知道除法的唯一条件是被除数必须是除数的两倍。还有什么我想念的吗?
const
是一个字节。当您执行 IDIV byte_divisor
时,商将放在 AL
中,范围为 -128 到 127。1000 / 5 为 200,这不在允许范围内。如果您使用 DIV
,商的范围是 0 到 255,这就是您的示例在这种情况下有效的原因。
如果您想 IDIV
1000 乘以 5,您应该改用 16 位除数。但是您需要记住,在使用 IDIV r/m16
时,您实际上是在划分由 DX
和 AX
组成的 32 位双字(DX
持有最高有效位,AX
最低有效位)。
来自英特尔的手册:
IDIV r/m16 Signed divide DX:AX by r/m16, with result stored in AX ← Quotient, DX ← Remainder.
IF OperandSize = 16 (* Doubleword/word operation *)
THEN
temp ← DX:AX / SRC; (* Signed division *)
IF (temp > 7FFFH) or (temp < 8000H)
(* If a positive result is greater than 7FFFH
or a negative result is less than 8000H *)
THEN
#DE; (* Divide error *)
ELSE
AX ← temp;
DX ← DX:AX SignedModulus SRC;
因此,在 IDIV
之前,您应该根据 AX
中的值在 DX:AX
中创建一个带符号的双字。有一条名为 CWD
的指令正是这样做的:
The
CWD
instruction copies the sign (bit 15) of the value in theAX
register into every bit position in theDX
register.
即:
.data
const dw 5 ; now a word
.code
mov ax,1000
cwd ; sign-extend ax into dx
idiv const
; quotient is in ax, remainder in dx