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

ASM 8086无DIV指令实现除法:如何编写b=a/6程序?

Dividing by 6 in 8086 ASM Without Using DIV

Great question! Since 6 factors into 2×3, we can split the problem into two manageable parts: dividing by 2 (which you already have down with SAR), then handling division by 3 without using the DIV instruction. Let’s cover a few practical, efficient approaches tailored for 8086 assembly.

Approach 1: Multiplicative Inverse (Fast for Unsigned Numbers)

For unsigned integers, we can leverage the multiplicative inverse trick. Dividing by 3 is equivalent to multiplying by 1/3, and in modular arithmetic (for 2^16 values), we can use an approximate inverse that works for integer division. For 16-bit unsigned numbers, the inverse of 3 is 0x5555 (since 0x5555 * 3 = 0xFFFF, which is just 1 less than 2^16).

Here’s how to combine this with dividing by 2:

; Assume 'a' is a 16-bit unsigned variable, result stored in 'b'
mov ax, a       ; Load a into AX
shr ax, 1       ; Divide by 2 (SHR works for unsigned; SAR also works here)
mov bx, 0x5555  ; Load 16-bit inverse of 3
mul bx          ; Multiply AX by BX: result is in DX:AX
mov ax, dx      ; Take the high 16 bits (equivalent to shifting right by 16)
mov b, ax       ; Store the final result (a/6)
  • Why this works: Multiplying by 0x5555 and taking the high 16 bits effectively computes (a/2) * (2^16 / 3) / 2^16, which approximates (a/2)/3 = a/6 perfectly for all unsigned 16-bit values.

Approach 2: Shift-and-Add with Adjustment (Works for Signed Numbers)

If you need to handle signed integers (negative numbers), SAR correctly divides by 2, but we need a division-by-3 method that respects sign. We can use a series of shifts and adds based on the infinite series approximation of 1/3 (1/3 = 1/4 + 1/16 + 1/64 + ...), then adjust for remainder errors.

Here’s a robust implementation:

; Assume 'a' is a 16-bit signed variable, result stored in 'b'
mov ax, a       ; Load a into AX
sar ax, 1       ; Divide by 2 (SAR preserves sign for negative numbers)
mov cx, ax      ; Save a copy of (a/2) for calculations

; Approximate (a/2)/3 using shift-and-add
sar ax, 2       ; ax = (a/2)/4
add ax, cx      ; ax = (a/2) + (a/2)/4 = 5*(a/2)/4
sar ax, 2       ; ax = 5*(a/2)/16
add ax, cx      ; ax = (a/2) + 5*(a/2)/16 = 21*(a/2)/16
sar ax, 2       ; ax = 21*(a/2)/64
add ax, cx      ; ax = (a/2) + 21*(a/2)/64 = 85*(a/2)/64

; Adjust for remainder to get exact division
mov dx, ax
shl dx, 1       ; dx = 2*ax
add dx, ax      ; dx = 3*ax (check what 3*our quotient is)
sub cx, dx      ; cx = (a/2) - 3*ax (remainder)

; Adjust quotient based on remainder sign and value
cmp cx, 0
jge no_neg_adjust
sub ax, 1       ; If remainder is negative, subtract 1 from quotient
no_neg_adjust:
cmp cx, 3
jl no_pos_adjust
add ax, 1       ; If remainder is >=3, add 1 to quotient
no_pos_adjust:

mov b, ax       ; Store the final signed result (a/6)
  • Why this works: The shift-and-add steps get us close to the true quotient, and the remainder adjustment fixes any off-by-one errors, ensuring correct signed division.

Approach 3: Subtraction Loop (Simple but Slow)

If you’re working with small values and prioritize simplicity over speed, a subtraction loop gets the job done. We just repeatedly subtract 3 from a/2 and count how many times we can do it before going negative.

; Assume 'a' is a 16-bit variable (signed or unsigned), result stored in 'b'
mov ax, a       ; Load a into AX
sar ax, 1       ; Divide by 2
mov cx, 0       ; Initialize quotient counter

divide_by_3_loop:
sub ax, 3
js end_divide   ; Stop if subtraction makes AX negative
inc cx
jmp divide_by_3_loop

end_divide:
; cx now holds the quotient (a/6)
mov b, cx
  • Note: For unsigned numbers, use JB instead of JS to check for underflow. This method is straightforward but inefficient for large values (e.g., dividing 65535 would take 10922 iterations).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 19:22:50