PDA

Просмотр полной версии : Оптимизация в HL



drbars
16.08.2013, 22:42
Нужна скоростная операция:

В HL содержится число (0..447) кратное 3.

Требуется быстро разделить HL на 3 и результат умножить на 4.

HL=(HL/3)*4

jerri
16.08.2013, 23:21
hl=hl*155h
так?

drbars
16.08.2013, 23:25
hl=hl*155h
так?

ну вот пример:

HL = #12F

HL/3 = #065

HL*4=#194

jerri
16.08.2013, 23:32
ага
12f*155=193 9b
447/3*4=254h

447*155h=253 6b

drbars
16.08.2013, 23:32
Ситуация какая... буфер для восстановление байта на экране занимает 3 байта буфера на байт экрана (word:adr, byte:data)

А процедура восстановления жрёт 4 байта на восстановление байта экрана... Нужно расчитать точку входа в процедуру по размеру буфера...

В HL у нас размер буфера.

jerri
16.08.2013, 23:33
округлять наверное :)
считает то правильно

drbars
16.08.2013, 23:35
Подумаю ещё, может чего оптимизирую.

Пример на асме есть? мне циклы нельзя городить в процедуре

jerri
16.08.2013, 23:36
а может будет достаточно ld l,h:ld h,a:inc hl

drbars
17.08.2013, 00:24
а может будет достаточно ld l,h:ld h,a:inc hl
Не совсем понял, всё таки...

---------- Post added at 03:24 ---------- Previous post was at 02:45 ----------

Может задачу иначе поставить?

Вот процедура восстановления циклом:
Поскольку буфер заполняется командой PUSH, то конец буфера фикированный, а начало в HL.

C = конец буфера.

Тормозно, но работает. 4 байта не могу в буфере хранить, нет места.


LD SP,HL ; HL = начало текущего буфера
RES_LN POP DE
DEC SP
POP AF
LD (DE),A
LD HL,#0000
ADD HL,SP
LD A,H
CP C
JP NZ,RES_LN


Стеком выгодно делать, если цикл развернуть... Иначе видимо нет.
А чтобы развернуть, нужно расчитать точку входа :)



RES_LN LD E,(HL)
INC HL
LD D,(HL)
INC HL
LD A,(HL)
INC HL
LD (DE),A
LD A,H
CP C
JP NZ,RES_LN

char
17.08.2013, 00:52
может, посмотреть в сторону последовательности pop de:ldi
байты фона отдельно, адреса отдельно
?

drbars
17.08.2013, 00:56
может, посмотреть в сторону последовательности pop de:ldi
байты фона отдельно, адреса отдельно
?
Так весьма проблематично буфер построить, плюс две точки начала буферов будут...

char
17.08.2013, 01:03
Так весьма проблематично буфер построить, плюс две точки начала буферов будут...

строить - попробовать push hl:ldd

начала буфера кратные 2 и 1 будут, а не 3

сколько байтов фона? если меньше 257 - еще удобнее.

drbars
17.08.2013, 01:17
строить - попробовать push hl:ldd

Не, никак. HL нельзя менять, т.к. HL байт где ставится точка прямой. Адрес поэтому стеком и снимается.

jerri
17.08.2013, 01:17
drbars, нее
я предлагаю умножать на #155
а потом hl уже чуть корректировать.

drbars
17.08.2013, 01:35
drbars, нее
я предлагаю умножать на #155
а потом hl уже чуть корректировать.
Оставлю наверное цикл, жрёт вроде терпимо... меньше чем рисование линии точно :)



RES_LN LD E,(HL)
INC HL
LD D,(HL)
INC HL
LDI
CP H
JP NZ,RES_LN

char
17.08.2013, 10:31
Оставлю наверное цикл, жрёт вроде терпимо... меньше чем рисование линии точно :)



RES_LN LD E,(HL)
INC HL
LD D,(HL)
INC HL
LDI
CP H
JP NZ,RES_LN


есть смысл bc рассчитать и избавиться от cp h, первый inc hl заменить на inc l? ;)

drbars
17.08.2013, 12:47
есть смысл bc рассчитать и избавиться от cp h, первый inc hl заменить на inc l? ;)
CP H не так критичен, как расчет B.

Чтобы расчитать B.. нужно (конец буфера — начало буфера)/3.

jerri
17.08.2013, 13:42
CP H не так критичен, как расчет B.

Чтобы расчитать B.. нужно (конец буфера — начало буфера)/3.
нифига - bc=количество элементов

drbars
17.08.2013, 17:53
нифига - bc=количество элементов
И как ты его узнаешь? На выходе из процедуры линии у нас есть указатель стека на начало буфера и всё. Ещё мы знаем конец буфера. (Конец - начало)/3 = кол-во элементов. Зная кол-во элементов *4 можно расчитать точку ухода в мегакод восстановления.


первый inc hl заменить на inc l? ;)
INC L тоже рисковано делать, буфер 448 байт. Если процедура "вылетит" то запоганит память. Это подходит для инкремента кратного 2.

jerri
17.08.2013, 23:45
И как ты его узнаешь? На выходе из процедуры линии у нас есть указатель стека на начало буфера и всё. Ещё мы знаем конец буфера. (Конец - начало)/3 = кол-во элементов. Зная кол-во элементов *4 можно расчитать точку ухода в мегакод восстановления.


я же тебе дал способ пересчета?
hl*#155
потом взять старшие 16 бит и сделать +1

---------- Post added at 23:45 ---------- Previous post was at 23:38 ----------

drbars, а чего такое странное число? 149*3?

drbars
18.08.2013, 10:17
я же тебе дал способ пересчета?
hl*#155
потом взять старшие 16 бит и сделать +1
drbars, а чего такое странное число? 149*3?
Умножение сожрёт всю выгоду на коротких прямых.
Странное число — максимальный размер буфера. Рациональное использование любого свободного кусочка.


первый inc hl заменить на inc l? ;)
Посчитал, первый inc hl можно заменить, он не попадает в границу.

jerri
18.08.2013, 12:29
drbars, я к тому что у тебя максимальный размер линии 149 точек по вертикали

char
18.08.2013, 14:16
Посчитал, первый inc hl можно заменить, он не попадает в границу.

ok, при размере буфера менее 2 секторов, граница переходится 1 раз, ежели наметить переход на команду ldi, тогда и оба inc hl получится заменить на inc l? ;)

... видимо, с заменой cp h на cp l ...

drbars
18.08.2013, 19:43
drbars, я к тому что у тебя максимальный размер линии 149 точек по вертикали
Игровое пространство 144 точки по вертикали.. буфер позволяет 149.

---------- Post added at 22:43 ---------- Previous post was at 22:29 ----------


ok, при размере буфера менее 2 секторов, граница переходится 1 раз, ежели наметить переход на команду ldi, тогда и оба inc hl получится заменить на inc l? ;)
... видимо, с заменой cp h на cp l ...

Не получится наметить, я уже максимально оптимизировал. Старший адрес как раз и проверяет, закончился ли буфер.

85*3=255. Это значит что 2-ой INC HL попадает на границу. Если мы буфер на байт сдвинем, как из него выходить? L у нас может быть одинаковым 2 раза. Тут уже ничего не сделаешь.

Не забывай ещё, что буфер строится от конца к началу, а востанавливается от начала к концу.

char
18.08.2013, 19:54
Игровое пространство 144 точки по вертикали.. буфер позволяет 149.

---------- Post added at 22:43 ---------- Previous post was at 22:29 ----------



Не получится наметить, я уже максимально оптимизировал. Старший адрес как раз и проверяет, закончился ли буфер.

85*3=255. Это значит что 2-ой INC HL попадает на границу. Если мы буфер на байт сдвинем, как из него выходить? L у нас может быть одинаковым 2 раза. Тут уже ничего не сделаешь.

Не забывай ещё, что буфер строится от конца к началу, а востанавливается от начала к концу.

перепроверь, такой L будет только 1 раз (в конце), на проверку идет только 1 байт из трех. ;)

видимо, A=255

drbars
18.08.2013, 20:06
перепроверь, такой L будет только 1 раз (в конце), на проверку идет только 1 байт из трех. ;)
видимо, A=255
Ты от конца считаешь?

Пример:
Начало буфера #7E40
Конец буфера +1 = #8000

заполняем стеком по 3 байта.

LD SP,#8000

повтор N раз
PUSH AF
INC SP
PUSH HL

куда придётся граница 256-го?

char
18.08.2013, 20:12
ld sp,#7fff

выйдет только по этому адресу

#7eff на проверку не попадает, только #00 будет сравниваться с A (предыдущий же был #FD)

drbars
18.08.2013, 20:17
ld sp,#7fff

выйдет только по этому адресу

#7eff на проверку не попадает, только #00 будет сравниваться с A (предыдущий же был #FD)

Ок, теперь восстанавливаем в обратном порядке:

А = #80
HL = начало буфера.



RES_LN LD E,(HL)
INC L
LD D,(HL)
INC HL
LDI
CP H
JP NZ,RES_LN
RET


Что будет если А = #7F ?

char
18.08.2013, 20:21
ok, при размере буфера менее 2 секторов, граница переходится 1 раз, ежели наметить переход на команду ldi, тогда и оба inc hl получится заменить на inc l?

... видимо, с заменой cp h на cp l ...


sp=#7fff
...
заполнили буфер
...

a=#ff

...
ldi
cp l
jp nz,RES_LN


L при сравнении с A будет #ff только в конце.

drbars
18.08.2013, 20:59
sp=#7fff
...
заполнили буфер
...

a=#ff

...
ldi
cp l
jp nz,RES_LN


L при сравнении с A будет #ff только в конце.
Ладно, уговорил. Внесу fix. :)

char
18.08.2013, 21:04
Да, не говори, красиво вообще :)

p.s. Плюс буфер можно таскать, не обязательно именно у границы сектора заканчивать

Robus
22.08.2013, 16:46
Что-то такое придумалось, наверное можно сильнее оптимизировать:

; IN:HL=VALUE
;OUT:HL=HL/3*4
DIVHL3MUL4
EX DE,HL
XOR A
LD L,D
LD H,A
ADD HL,DE
ADD HL,HL
ADD HL,HL
ADD HL,DE
ADD HL,HL
ADD HL,HL
ADD HL,DE
ADD HL,HL
ADD HL,HL
ADD HL,DE
ADD HL,HL
RLA
ADD HL,HL
RLA
ADD HL,DE
RLC L
LD L,H
LD H,A
RET NC
INC HL
RET

jerri
22.08.2013, 17:34
Robus, Ну ты просто мой алгоритм материализовал :)
а все вхождения проверил?
у тебя ошибка

LD L,D
должно быть
LD L,A

drbars
22.08.2013, 17:56
Всем спасибо) Я уже понял, что расчитывать точку вхождения в мегакод в моём случае — особое извращение. Поэтому оставил цикл. Быстрая память экстремально заканчивается, начинаю извращаться уже)