ZX Spectrum > PROGRAMOWANIE

mój pierwszy programik

<< < (2/14) > >>

matofesi:

--- Cytat: Dalthon w 2018.08.06, 12:36:17 ---Ogólna uwaga - aby procedury szybciej działały zamiast jr... używaj jp... 1 bajt więcej ale szybciej działa.

--- Koniec cytatu ---

A żeby uściślić - warunkowe JR ma różne czasy wykonania zależnie od tego, czy warunek jest spełniony (12 t-states) czy nie (7 t-states), warunkowe JP ma zawsze 10 t-states.

JP warto używać w kodzie, który ma się wykonywać "równo" (efekty na borderze, dokładna synchronizacja do rastra) albo w sytuacji, gdy np. przewidujemy "krótką" pętlę (czyli warunek może być spełniony bądź nie mniej więcej w równych proporcjach). Jeśli kod będzie się "kręcił" dość długo w jednym miejscu i wyskakiwał warunkowo raz na jakiś czas (czyli przez większość czasu "przelatywał" przez skok) to bardziej się opłaca JR. Oczywiście w takiej sytuacji dobrze jest przeliczyć takty zużywane na obsługę i np. główną pętlę robić na JR (o ile sięgnie) a warunki na JP itp.

Za każdym razem jeśli kod ma być szybki należy mu się przyjrzeć z tabelką rozkazów i policzyć co się bardziej opłaca. A już najlepiej - jeśli mamy miejsce w pamięci - rozwinąć wszystko co się da rozwinąć ;)

gorgh:
dzięki matofesi,
posiedziałem trochę nad kodem i tak jak radziliście zmieniłem operacje na pamięci na operacje na rejestrach, kod obliczający wartość poszczególnych pixeli wcześniej wyglądał tak:

--- Kod: ---
 ld a,(s1)
 add a,2
 ld (s1),a
 
 add a,e
 ld e,a

 ld a,(de)
 ld e,0
 ld (byte1),a

 ld a,(s2)
 add a,3
 ld (s2),a
 
 add a,e
 ld e,a

 ld a,(de)
 ld e,0
 ld (byte2),a

 ld a,(s3)
 add a,6
 ld (s3),a

 add a,e
 ld e,a

 ld a,(de)
 ld e,0
 ld (byte3),a

 ld a,(s4)
 add a,8
 ld (s4),a
 
 add a,e
 ld e,a

 ld a,(de)
 ld e,0
 
 push hl

 ld hl,byte1

 add a,(hl)
 jr nc,forw1
 inc e
forw1
 inc l
 add a,(hl)
 jr nc,forw2
 inc e
forw2
 inc l
 add a,(hl)
 jr nc,forw3
 inc e
forw3

 pop hl

--- Koniec kodu ---

teraz wygląda tak:

--- Kod: ---
 exx

 ld a,b
 add a,2
 ld b,a
 
 ld (for_sinus1+1),a

for_sinus1
 ld a,($7000)
 ld (for_add1+1),a

 ld a,c
 add a,3
 ld c,a
 
 ld (for_sinus2+1),a

for_sinus2
 ld a,($7000)
 ld (for_add2+1),a


 ld a,d
 add a,6
 ld d,a

 ld (for_sinus3+1),a

for_sinus3
 ld a,($7000)
 ld (for_add3+1),a


 ld a,e
 add a,8
 ld e,a

 ld (for_sinus4+1),a

for_sinus4
 ld a,($7000)
 
 exx

 ld e,0

for_add1
 add a,0
 jp nc,for_add2
 inc e
for_add2
 add a,0
 jp nc,for_add3
 inc e
for_add3
 add a,0
 jp nc,finished
 inc e
finished


--- Koniec kodu ---

I działa to znacznie szybciej :)

matofesi:
Nie analizując dogłębnie algorytmu zasugeruję jeszcze jedną rzecz - używasz "sla a" do mnożenia przez dwa. To jest wysoce nieekonomiczne - sla to 8 t-stateów a "add a,a" robiące w tym wypadku to samo tylko 4. Niby grosze, ale jednak ;)

Poz tym jeśli masz stosunkowo krótką pętlę DJNZ do przy każdym jej "obrocie" tracisz 13 t-stateów - jeśli nie ma ograniczeń co do rozmiaru kodu rozwiń pętlę np tak:

--- Kod: ---; ld b,$40
 
rept $40
;loop_sin2
 ld a,(hl)
 cpl
 ld (de),a 
 inc e
 inc l
endm
; djnz loop_sin2

--- Koniec kodu ---

Na każdej trzech pętli oszczędzisz ponad 800 t-stateów.

Pewnie jakby się temu przyjrzeć z głębszą analizą samego algorytmu dałoby się urwać jeszcze coś ;)

gorgh:
wow dziękuweczka, cenne rady panie!

gorgh:

--- Cytat: matofesi w 2018.08.06, 14:28:03 ---
Na każdej trzech pętli oszczędzisz ponad 800 t-stateów.


--- Koniec cytatu ---

Akurat ta procka jest wywoływana tylko 1 raz, ale rozpętlanie kiedyś się na pewno przyda

Nawigacja

[0] Indeks wiadomości

[#] Następna strona

[*] Poprzednia strona

Idź do wersji pełnej