ZX Spectrum > PROGRAMOWANIE
mój pierwszy programik
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
[#] Następna strona
Idź do wersji pełnej