You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无32位寄存器的32位/16位有符号整数除法问题(286平台)

Fixing 32-bit Signed Division by 16-bit on 286 (IDIV32 Issues)

Let's break down why your current IDIV32 implementation is failing, and walk through a corrected version that leverages your working DIV32 code.

What's Wrong with the Original IDIV32?

Your approach of swapping XOR DX,DX with CWD and DIV with IDIV works only for positive values where the quotient fits in 16 bits, but it breaks for signed cases because:

  1. Incorrect stepwise division logic: The two-step division that works for unsigned numbers doesn't translate to signed division. Signed division relies on the entire 32-bit dividend's sign, not just the high 16 bits. Splitting it into two 16-bit signed divisions produces invalid intermediate results (like your -131076/2 returning -2 instead of -65538).
  2. IDIV range limitations: The 286 IDIV instruction requires the quotient to fit within a 16-bit signed integer (-32768 to 32767). When dividing by ±1, the high 16 bits of a large 32-bit dividend (e.g., 0x80000000) will produce a quotient that exceeds this range, triggering a division error.

Corrected IDIV32 Implementation

Instead of trying to adapt the stepwise signed division, we'll use a more reliable approach: convert the problem to unsigned division (using your working DIV32), then adjust the signs of the quotient and remainder afterward.

IDIV32 PROC
;DIVIDES A SIGNED 32-BIT VALUE BY A SIGNED 16-BIT VALUE.
;ALTERS AX, BX, DX, SI, DI
;EXPECTS THE SIGNED 32-BIT DIVIDEND IN DX:AX
;EXPECTS THE SIGNED 16-BIT DIVISOR IN BX
;RETURNS THE SIGNED 32-BIT QUOTIENT IN DX:AX
;RETURNS THE SIGNED 16-BIT REMAINDER IN BX
    push cx
    push di
    push si

    ; Save sign flags:
    ; SI = quotient sign (0=positive, 1=negative)
    ; DI = remainder sign (matches original dividend's sign)
    xor si, si
    xor di, di

    ; Check and normalize dividend (convert to unsigned absolute value)
    test dx, 8000h       ; Check if dividend is negative (bit 31 set)
    jz @f
    mov di, 1            ; Remainder will be negative
    or si, 1             ; Quotient sign starts as negative
    ; Compute absolute value of 32-bit dividend
    neg dx
    neg ax
    sbb dx, 0            ; Handle carry from negating AX
@@:

    ; Check and normalize divisor (convert to unsigned absolute value)
    test bx, 8000h       ; Check if divisor is negative (bit 15 set)
    jz @f
    xor si, 1            ; Flip quotient sign (negative ÷ negative = positive)
    ; Compute absolute value of 16-bit divisor
    neg bx
@@:

    ; Use working unsigned division to get quotient and remainder
    call DIV32

    ; Adjust quotient sign if needed
    test si, 1
    jz @f
    ; Negate 32-bit quotient (convert back to signed negative)
    neg dx
    neg ax
    sbb dx, 0
@@:

    ; Adjust remainder sign to match original dividend
    test di, 1
    jz @f
    ; Negate 16-bit remainder
    neg bx
@@:

    pop si
    pop di
    pop cx
    ret
IDIV32 ENDP

How This Works

  1. Sign Tracking: We first record whether the original dividend and divisor are negative. The quotient's sign is the XOR of the two signs, and the remainder's sign always matches the original dividend (per signed division rules).
  2. Normalization: Convert both the dividend and divisor to their unsigned absolute values. For the 32-bit dividend, we use neg ax + neg dx + sbb dx,0 to correctly handle the edge case of 0x80000000 (the smallest 32-bit signed integer, which has no positive equivalent).
  3. Unsigned Division: Call your trusted DIV32 to compute the unsigned quotient and remainder.
  4. Sign Adjustment: Convert the unsigned results back to signed values by negating them if their recorded sign requires it.

Testing Your Problem Cases

  • -131076 / 2: The dividend converts to 0x00020004 (unsigned), divides by 2 to get quotient 0x00010002 and remainder 0. We negate the quotient to get -65538 (correct) and leave the remainder as 0.
  • Divisor ±1: By using unsigned division, we avoid the IDIV range limit. For example, 0x80000000 / -1 converts to 0x80000000 / 1 (unsigned), quotient 0x80000000, then we negate it to get 0x80000000 (the correct signed result, no division error).
  • -65538 / 2: Converts to 0x00010002 / 2, quotient 0x00008001, negated to -32769 (correct).

内容的提问来源于stack exchange,提问作者bad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:00:41