装配程序,带有未签名/签名的部门

Qua*_*fan 1 assembly masm

我正在尝试编写一个简单的汇编程序,将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
Run Code Online (Sandbox Code Playgroud)

如果我使用无符号除法div而不是有符号除法,问题就会消失idiv.

有谁能解释为什么?

我知道分裂的唯一条件是股息必须是除数的两倍.还有其他我想念的东西吗?

Mic*_*ael 5

const是一个字节.当你这样做时IDIV byte_divisor,商将被放入AL,并且范围为-128到127. 1000/5是200,这不在允许的范围内.如果使用DIV,则商的范围是0到255,这就是为什么您的示例在这种情况下有效.

如果你想要IDIV1000乘5,你应该使用16位除数.但是你需要记住,在使用时IDIV r/m16,你实际划分的是32位双字组成DXAX(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;
Run Code Online (Sandbox Code Playgroud)

所以在IDIV你应该DX:AX从值中创建一个有符号的双字之前AX.有一个命名指令CWD正是这样做的:

CWD指令将AX寄存器中值的符号(第15位)复制到寄存器中的每个位DX.

即:

.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
Run Code Online (Sandbox Code Playgroud)