gpt4 book ai didi

assembly - 没有 32 位寄存器的 32 位/16 位有符号整数除法?

转载 作者:行者123 更新时间:2023-12-03 02:12:17 26 4
gpt4 key购买 nike

我正在尝试将 32 位有符号整数除以 16 位有符号整数,以获得有符号 32 位商和 16 位余数。

我的目标是没有 FPU 的 286。

我过去已经编写过代码来进行 32 位无符号除法:

DIV32 PROC

;DIVIDES A 32-BIT VALUE BY A 16-BIT VALUE.

;ALTERS AX
;ALTERS BX
;ALTERS DX

;EXPECTS THE 32-BIT DIVIDEND IN DX:AX
;EXPECTS THE 16-BIT DIVISOR IN BX

;RETURNS THE 32-BIT QUOTIENT IN DX:AX
;RETURNS THE 16-BIT REMAINDER IN BX

push di
push si


mov di, ax ;di -> copy of LSW of given dividend
mov ax, dx ;ax -> MSW of given dividend
xor dx, dx ;dx:ax -> 0:MSW
div bx ;ax:dx -> ax=MSW of final quotient, dx=remainder

mov si, ax ;si -> MSW of final quotient
mov ax, di ;dx:ax -> dx=previous remainder, ax=LSW of given dividend
div bx ;ax:dx -> ax=LSW of final quotient, dx=final remainder
mov bx, dx ;bx -> final remainder
mov dx, si ;dx:ax -> final quotient


pop si
pop di
ret

DIV32 ENDP

到目前为止,我已经尝试做显而易见的事情,只是通过将 XOR DX, DX 替换为 CWDDIV 来修改现有代码IDIV:

IDIV32 PROC

;DIVIDES A SIGNED 32-BIT VALUE BY A SIGNED 16-BIT VALUE.

;ALTERS AX
;ALTERS BX
;ALTERS DX

;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 16-BIT REMAINDER IN BX

push di
push si


mov di, ax ;di -> copy of LSW of given dividend
mov ax, dx ;ax -> MSW of given dividend
cwd ;dx:ax -> 0:MSW, or ffff:MSW
idiv bx ;ax:dx -> ax=MSW of final quotient, dx=remainder

mov si, ax ;si -> MSW of final quotient
mov ax, di ;dx:ax -> dx=previous remainder, ax=LSW of given dividend
idiv bx ;ax:dx -> ax=LSW of final quotient, dx=final remainder
mov bx, dx ;bx -> final remainder
mov dx, si ;dx:ax -> final quotient


pop si
pop di
ret

IDIV32 ENDP

这适用于某些计算,例如 -654,328/2=-327164 (0xfff60408/2=fffb0204)。但它不适用于某些输入,-131,076/2 返回 -2 余数 0 的错误结果。除数 1 或 -1 似乎会导致除法错误,无论被除数如何。

我测试了许多不同的正负股息和除数,试图找到某种正确和错误结果的模式,我注意到它无法正确返回 -65538 的结果。

我有预感,我应该根据输入有条件地使用 CWD,但似乎 XOR DX, DX 更频繁地返回不正确的结果。当除数和被除数均为正且商小于 0x7fffffff 时,两者都有效。

最佳答案

我不知道有什么算法可以将大负数分成几部分并为 IDIV 做好准备。我会计算被除数和除数的绝对值,使用函数 DIV32,最后根据存储的符号处理结果:

IDIV32 PROC      ; DX:AX / BX = DX/AX rem BX
; 99 / 5 = 19 rem 4
; 99 / -5 = -19 rem 4
; -99 / 5 = -19 rem -4
; -99 / -5 = 19 rem -4

mov ch, dh ; Only the sign bit counts!
shr ch, 7 ; CH=1 means negative dividend
mov cl, bh ; Only the sign bit counts!
shr cl, 7 ; CL=1 means negative divisor

cmp ch, 1 ; DX:AX negative?
jne J1 ; No: Skip the next two lines
not dx ; Yes: Negate DX:AX
neg ax ; CY=0 -> AX was NULL
cmc
adc dx, 0 ; Adjust DX, if AX was NULL
J1:

cmp cl, 1 ; BX negative?
jne J2 ; No: Skip the next line
neg bx ; Yes: Negate BX
J2:

push cx ; Preserve CX
call DIV32
pop cx ; Restore CX

cmp ch, cl ; Had dividend and divisor the same sign?
je J3 ; Yes: Skip the next two lines
not dx
neg ax ; CY=0 -> AX was NULL
cmc
adc dx, 0 ; Adjust DX, if AX was NULL
J3:

cmp ch, 1 ; Was divisor negative?
jnz J4 ; No: Skip the next line
neg bx ; Negate remainder
J4:

ret
IDIV32 ENDP

关于assembly - 没有 32 位寄存器的 32 位/16 位有符号整数除法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55429707/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com