ZXNet эхоконференция «code.zx»
тема: Математические процедуры.
от: Aleksey Malov
кому: All
дата: 04 Apr 2000
Приветствую тебя, All!
Итак, процедура номер 1: быстрое деление 16/16. Тому, кто сможет ее
ускорить, можно будет памятник при жизни поставить (за его счет). Ускорение
путем замены jr на jp не рассматривается, т.к. выигрыш/ проигрыш в
скорости зависит от величины аргументов.
На входе:
de-делимое
bc-делитель
На выходе:
de-частное
hl-остаток
divide ld a,b ;меняем
cpl ;
ld b,a ;знак
ld a,c ;
cpl ;у
ld c,a ;
inc bc ;делителя t=30
ld hl,0 ;обнулили новое делимое
ld a,d ;сначала двигаем
rla ;старший байт делимого
;t=18
rl l ;┐
add hl,bc ;│
jr c,$+4 ;│8 раз
sbc hl,bc ;│
rla ;┘ t=8*45=360
ld d,a ;ст. байт результата
ld a,e ;теперь двигаем
rla ;младший байт t=12
adc hl,hl ;┐
add hl,bc ;│
jr c,$+4 ;│8 раз
sbc hl,bc ;│
rla ;┘ t=8*52=416
ld e,a ;мл. байт результата
;hl-остаток от деления
;t=4
Итого:
30+18+360+12+416+4=840 тактов.
Если остаток не нужен, то конец проце-
дуры должен выглядеть так:
adc hl,hl ;┐
add hl,bc ;│
jr c,$+4 ;│7 раз
sbc hl,bc ;│
rla ;┘ t=7*52=364
adc hl,hl ;
add hl,bc ;
rla ;
ld e,a ; t=34
Итого:
30+18+360+12+364+34=818 тактов.
P.S. Если будете делить на ноль, то, как и следовало ожидать, частное
будет равно нулю, а остаток - делимому, т.е. в этом плане у процедуры
глюков нет.
;***********************
Процедура номер 2: извлечение квадратного корня из регистровой пары. Вот
тут уж действительно надо памятник поставить тому, кто ускорит процедуру
хотя бы на 1 такт. Ускорение путем замены jr на jp не рассматривается,
т.к. выигрыш/проигрыш в скорости зависит от величины аргумента.
На входе:
hl-число из которого необходимо извлечь
квадратный корень
на выходе:
a-квадратный корень из hl
sqrhl xor a ;обнулили a ;-)
ld de,64 ;этого требует алгоритм
; t=14
sla h ;берем два самых левых
adc a,a ;бита аргумента
sla h ;
adc a,a ;
jr z,$+4 ;если они не равны
dec a ;нулю, то увеличиваем
inc d ;результат
; t=39
sla h ;┐далее следуем
adc a,a ;│алгоритму извлечения
sla h ;│квадратного корня
adc a,a ;│"столбиком", только
sla d ;│
ld c,d ;│3 раза
sli c ;│
cp c ;│
jr c,$+4 ;│
sub c ;│
inc d ;┘ t=63*3=189
sla l ;┐проделываем похожую
adc a,a ;│операцию с
sla l ;│младшим байтом
adc a,a ;│аргумента
sla d ;│
ld c,d ;│2 раза
sli c ;│
cp c ;│
jr c,$+4 ;│
sub c ;│
inc d ;┘ t=63*2=126
ld h,a ;
or a ;обнулили флаг переноса
; t=8
sbc hl,de ;теперь нам не хватает
jr nc,$+3 ;одного регистра d для
add hl,de ;выполнения последних
ccf ;двух циклов, придется
rl d ;использовать более
add hl,hl ;медленные операции
add hl,hl ;с регистровыми парами
; t=67
sbc hl,de ;и последний раз
ccf ;выполняем расчеты, не
ld a,d ;восстанавливая hl
adc a,a ;в a-результат
; t=27
Итого:
14+39+189+126+8+67+27=470 тактов.
Процедура номер 3: извлечение квадратного корня из трехбайтового числа.
Ускорение путм замены jr на jp не рассматривается, т.к. выигрыш/проигрыш в
скорости зависит от величины аргумента.
На входе:
dhl=d*65536+hl - само число
На выходе:
hl - тот самый квадратный корень
sqrdhl xor a ;начало процедуры
ld bc,64 ;практически аналогично
;предыдущей
; t=14
sla d ;
adc a,a ;
sla d ;
adc a,a ; t=39
jr z,$+4 ;
dec a ;
inc b ;
sla d ;┐
adc a,a ;│
sla d ;│
adc a,a ;│
sla b ;│
ld e,b ;│3 раза
sli e ;│
cp e ;│
jr c,$+4 ;│
sub e ;│
inc b ;┘ t=3*63=189
sla h ;┐
adc a,a ;│
sla h ;│
adc a,a ;│
sla b ;│
ld e,b ;│2 раза
sli e ;│
cp e ;│
jr c,$+4 ;│
sub e ;│
inc b ;┘ t=63*2=126
ld d,l ;
ld l,h ;
ld h,a ;меняем регистры
or a ; t=16
sbc hl,bc;┐
jr nc,$+3;│
add hl,bc;│
ccf ;│2 раза
rl b ;│
add hl,hl;│
add hl,hl;┘ t=67*2=134
ld l,h ;есть подозрение, что
ld h,0 ;этот блок и предыдущий
ld c,b ;можно немного ускорить
ld b,h ;
rl h ;
ld a,d ; t=31
rla ;┐да и этот блок мне
adc hl,hl;│не нравится.
rla ;│очень вероятно, что
adc hl,hl;│его можно неплохо
sla c ;│ускорить. Но как?
rl b ;│
ld d,b ;│
ld e c ;│3 раза
sli e ;│
rl d ;│
sbc hl,de;│
jr nc,$+4;│
add hl,de;│
dec c ;│
inc c ;┘ t=3*119=357 (!)
;ужас! Думайте, как
;ускорить!
rla ;этот блок аналогичен
adc hl,hl;предыдущему с
rla ;небольшой разницей
adc hl,hl;в конце. Это сделано
ld d,b ;ради повышения
ld e,c ;скорости вычислений
sla e ;
rl d ;
sli e ;
rl d ;
sbc hl,de;
ccf ; t=97
ld h,b ;
ld l,c ;
adc hl,hl;в hl - результат
; t=23
Итого:
14+39+189+126+16+134+31+357+97+23=1026.
;******************
Hу и процедура расчета адреса в аттрибутах по координатам в знакоместах.
быстрее не сделать, если не использовать таблиц.
На входе:
d-y
e-x
На выходе:
hl-адрес в аттрибутах
ld a,d
rrca
rrca
rrca
ld h,a
and #e0
or e
ld l,a
xor e
xor h
or #58
ld h,a
t=54 такта.
Желаю вам здоровья, счастья и творческих узбеков.
Aleksey Malov aka VIVID/Brainwave.
от: Vitaly Vidmirov
кому: Aleksey Malov
дата: 05 Apr 2000
i`m happy to meet you again, Aleksey!
last time (04 Apr 00 01:03:19) you talk about something
AM> Итак, процедура номер 1: быстрое деление 16/16. Тому, кто сможет
AM> ее ускорить, можно будет памятник при жизни поставить (за его счет).
AM> divide ld a,b ;меняем
AM> cpl ;
AM> ld b,a ;знак
AM> ld a,c ;
AM> cpl ;у
AM> ld c,a ;
AM> inc bc ;делителя t=30
сразу же бросилось в глаза
xor a
sub c
ld c,a
sbc a,b
sub c
ld b,a
30 -> 24.
Остальное посмотрю когда будет время. Hе забудь, что существуют
и другие алгоритмы деления...
catch my respects, Aleksey
|