2015-10-20 61 views
1

我想写一个简单的装配程序除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

任何人都可以解释为什么吗?

我知道除法的唯一条件是股息必须是除数的两倍。还有什么我失踪?

回答

5

const是一个字节。当你做IDIV byte_divisor时,商将被放置在AL中,并且具有-128到127的范围。1000/5是200,这不在允许的范围内。如果使用DIV,商的范围是0到255,这就是您的示例在这种情况下工作的原因。

如果你想IDIV 1000乘5你应该使用一个16位除数。但是需要注意的是,当使用IDIV r/m16时,实际上划分的是由DXAXDX保存最高有效位,而AX最低有效位)组成的32位双字。

从Intel的手册:

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所做的正是这一个指令:

CWD指令 复制标志在AX寄存器中的值转换成DX寄存器的每个位的(第15位)。

即:

.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 
+0

完美。谢谢! –