Kirill Frolov (2:5020/400)
Гость
32-битное деление чисел, ассемблер Z80. HАЙДЕHА ЖУТКАЯ ОШИБКА!
FromNet: NET_Moscow_Russia_(245_02/09/2005) (commserv.rpb.ru)
From: Kirill Frolov <[email protected]>
Hемедленно нажми на RESET, All!
В неоднократно публиковавшемся здесь алгоритме 32-битного деления
обнаружена серьёзная ошибка!
=== cut here ===
ifused ldiv
ifndef ldiv
; Беззнаковое 32-разрядное деление
; функция состоит из двух частей:
; 1. 32-разрядное делимое и 16-разрядный
; делитель.
; 2. 32-раздядное делимое и 32-разрядный
; делитель.
; hl'hl = hl'hl / de'de
; de'de = hl'hl % de'de
ldiv
push hl
xor a
ld l, a
ld h, a
sub e
ld e, a
sbc a, d
sub e
ld d, a
exx
=== cut here ===
Это начальные строки ОШИБОЧHОЙ ПРОГРАММЫ.
Для устранения ошибки их следует ЗАМЕHИТЬ на следующие:
ldiv
push hl
xor a
ld l, a
ld h, a
sub e
ld e, a
+ ld a, h ; a=0. -- эта строка добавлена
sbc a, d
ld d, a
exx
Ошибка была обнаружена lvd. Задаётся вопрос об авторстве:
автороство, по видимости, коллективное, по результатам переписки
в телеконференциях, иначе я обычно указываю откуда взято.
Полный текст функции выглядит следующим образом:
ifused ldiv
ifndef ldiv
; версия от 2006-12-18T15:11:28+0300
; Беззнаковое 32-разрядное деление
; функция состоит из двух частей:
; 1. 32-разрядное делимое и 16-разрядный
; делитель.
; 2. 32-раздядное делимое и 32-разрядный
; делитель.
; hl'hl = hl'hl / de'de
; de'de = hl'hl % de'de
ldiv
push hl
xor a
ld l, a
ld h, a
sub e
ld e, a
ld a, h
sbc a, d
ld d, a
exx
pop bc
ld a, 0
sbc a, e
ld e, a
sbc a, d ; de'de=0-divisor
sub e
ld d, a
and e
inc a ; Z=short divisor
push hl
ld hl, 0 ; hl'hl=reminder
exx
pop bc
ld a, b ; a,c,bc'=divident
jr nz, ldiv_long
; divisor = -00de
ld b, 8
rla
ldivs0
rl l
add hl, de
jr c, ldivs1
sbc hl, de
ldivs1 rla
djnz ldivs0
ld b, c
ld c, a
ld a, b
ld b, 8
rla
ldivs2
adc hl, hl
add hl, de
jr c, ldivs3
sbc hl, de
ldivs3 rla
djnz ldivs2
jr ldiv_long1
; divisor=-de'de
ldiv_long
call ldiv_8
ld b, c
ld c, a
ld a, b
call ldiv_8
ldiv_long1
exx
exa
ld a, b
exa
ld b, a
exa
exx
call ldiv_8
exx
exa
ld a, c
exa
ld c, a
exa
exx
call ldiv_8
; result=c,bc',a -> hl'hl
; reminder=hl'hl -> de'de
ex de, hl
ld l, a
ld a, c
exx
ex de, hl
ld h, a
ld l, b
ld a, c
exx
ld h, a
ret
; hl'hl=reminder
; de'de=divisor
; a=divident
ldiv_8
ld b, 8
rla
ldiv_8_0
adc hl, hl
exx
adc hl, hl
exx
add hl, de
exx
adc hl, de
exx
jr c, ldiv_8_1
sbc hl, de
exx
sbc hl, de
exx
ldiv_8_1
rla
djnz ldiv_8_0
ret
endif
endif