-
Тем временем реализовал деление на 10 сдвигами:
Код:
unsigned divu10(unsigned n) {
unsigned q, r;
q = (n >> 1) + (n >> 2);
q = q + (q >> 4);
q = q + (q >> 8);
q = q + (q >> 16);
q = q >> 3;
r = n - q*10;
return q + ((r + 6) >> 4);
// return q + (r > 9);
}
-- отсюда
Скрытый текст
Код:
;=======================================================================
; HL [A] = HL/10
;-----------------------------------------------------------------------
proc udiv10
;-----------------------------------------------------------------------
ora a
mov a,h
rar
mov b,a
mov a,l
rar
mov c,a ; bc = n >> 1
ora a
mov a,b
rar
mov d,a
mov a,c
rar
add c
mov e,a
mov c,a
mov a,d
adc b
mov b,a
mov d,a ; bc = de = (hl>>1)+(hl>>2) = q
xchg ; de = n ; bc = hl = q
xra a
call shr_hl.s4 ; hl = q >> 4
dad b ; hl = q = q + (q>>4)
mov c,h
mvi b,0
dad b ; hl = q = q + (q>>8)
xra a
call shr_hl.s3 ; hl = q = q >> 3
mov b,h
mov c,l ; bc = q
dad h
dad h
dad b
dad h ; hl = q*10
mov a,e
sub l
adi 6
rar
rar
rar
rar
ani 15 ; a = (r+6)>>4
add c
mov l,a
mov a,b
aci 0
mov h,a ; hl = q + ((r+6)>>4) = n/10
mov a,l
add a
add a
add l
add a ; a = l*10
sub e
cma
inr a ; a = e - l*10 (remainder)
ret
;-----------------------------------------------------------------------
.dummy = shr_hl
;-----------------------------------------------------------------------
endp
;=======================================================================
;
;=======================================================================
; FOR .s1-.s7 A MUST BE 0 !
;-----------------------------------------------------------------------
proc shr_hl
;-----------------------------------------------------------------------
xra a
.s1:
dad h
ral
.s2:
dad h
ral
.s3:
dad h
ral
.s4:
dad h
ral
.s5:
dad h
ral
.s6:
dad h
ral
.s7:
dad h
ral
mov l,h
mov h,a
ret
;-----------------------------------------------------------------------
endp
;=======================================================================
[свернуть]
-- надо будет ускорить вывод чисел
++++++++++++++++++++++++++
оказалось, что исходный вариант делит хорошо, но остаток у него левый ;) причем не всегда, а когда аргумент равен 10*х и 10*х+1
поэтому доточил в конце вычисление правильного остатка ;) уж даже не знаю, но надеюсь, что быстрее, чем просто деление на 10
(уже влом такты считать)
-
32-битный кубический корень :)
как обычно взял исходник на си из тех же мест, не смог обойтись стеком - использовал память,
доперепилил ;)
Код:
int icbrt2(unsigned x) {
int s;
unsigned y, b, bs, y2;
y2 = 0;
y = 0;
for (s = 30; s >= 0; s = s - 3) {
y2 = 4*y2;
y = 2*y;
b = 3*(y2 + y) + 1;
bs = b << s;
if (x >= bs && b == (bs >> s)) {
x = x - bs;
y2 = y2 + 2*y + 1;
y = y + 1;
}
}
return y;
}
это процедурка
Скрытый текст
Код:
;=======================================================================
; BC = CBRT(DEHL)
;-----------------------------------------------------------------------
cbrt32:
;-----------------------------------------------------------------------
shld .x
xchg
shld .x+2
lxi b,0
mov h,b
mov l,c
shld .y2
shld .y2+2
mvi a,30
;-----------------------------------------------------------------------
.loop:
sta .s
;-----------------------------------------------------------------------
lhld .y2+2
xchg
lhld .y2
mvi a,2
call shl_dehl_a
shld .y2
xchg
shld .y2+2 ; y2=4*y2
xchg
mov a,c
add a
mov c,a
mov a,b
adc a
mov b,a ; y=2*y
dad b
jnc .m1
inx d
.m1: ; dehl = y2 + y
xra a
push b
mov b,h
mov c,l
dad b
aci 0
dad b
aci 0
xchg
mov b,h
mov c,l
dad b
dad b
add l
mov l,a
mov a,h
aci 0
mov h,a
xchg
inx h
mov a,l
ora h
jnz .m2
inx d
.m2:
pop b ; dehl = b = 3*(y2 + y)+1
lda .s
call shl_dehl_a ; dehl = bs = b << s
lda .x
sub l
mov l,a
lda .x+1
sbb h
mov h,a
lda .x+2
sbb e
mov e,a
lda .x+3
sbb d
mov d,a ; dehl = x - bs
jc .skip
shld .x ; x = x - bs
xchg
shld .x+2
lhld .y2+2
xchg
lhld .y2
dad b
jnc .m3
inx d
.m3:
dad b
jnc .m4
inx d
.m4:
inx h
mov a,l
ora h
jnz .m5
inx d
.m5:
shld .y2
xchg
shld .y2+2 ; y2 = y2 + 2*y + 1
inx b ; y = y + 1
.skip:
lda .s
sui 3
jnc .loop
;-----------------------------------------------------------------------
ret
;-----------------------------------------------------------------------
.x dd ?
.y2 dd ?
.s db ?
;=======================================================================
[свернуть]
а это - служебная сдвигайка влево
Скрытый текст
Код:
;=======================================================================
; DEHL = DEHL << A
;-----------------------------------------------------------------------
proc shl_dehl_a
;-----------------------------------------------------------------------
ora a
rz
;-----------------------------------------------------------------------
cpi 32
jnc .zero_dehl
push psw
ani 7
inr a
.loop:
dcr a
jz .move
xchg
dad h
xchg
dad h
jnc .loop
inx d
jmp .loop
.move:
pop psw
ani 18h
rar
rar
rar
rar
jnc .next
mov d,e
mov e,h
mov h,l
mvi l,0
.next:
rar
rnc
xchg
lxi h,0
ret
.zero_dehl:
lxi d,0
lxi h,0
ret
;-----------------------------------------------------------------------
endp
;=======================================================================
[свернуть]
Приблизительный 64-битный квадратный корень.
Использует указанные выше процедуры.
При необходимости сначала побайтно сдвигает аргумент, а потом соответственно и результат, поэтому для аргументов >32 бит является приблизительным.
Скрытый текст
Код:
;=======================================================================
; DEHL = SQRT([HL]) APPROX FOR > 32 BIT (VIA 32-BIT SQRT)
;-----------------------------------------------------------------------
proc sqrt64a
;-----------------------------------------------------------------------
lxi b,7
dad b
mvi b,4
xra a
.loop:
cmp m
jnz .ok
dcx h
dcr b
jnz .loop
.ok:
push b
mov d,m
dcx h
mov e,m
dcx h
mov a,m
dcx h
mov l,m
mov h,a
call sqrt32
lxi d,0
mov h,b
mov l,c
pop psw
add a
rz
add a
jmp shl_dehl_a
;-----------------------------------------------------------------------
endp
;=======================================================================
[свернуть]