Autor Wątek: Skopiowanie większej ilości danych do RAM  (Przeczytany 13611 razy)

siudym

  • **
  • Wiadomości: 61
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #60 dnia: 2022.04.21, 11:24:52 »
Po przerwie znowu wracam do Z80, znowu do prób zastępowania indexowania typowego dla 6502 takim powiedzmy "pseudo-indexowaniem" w Z80.
Mam przykładowy kod, ktory zwiększa dynamicznie prędkość animacji przeciwników używając dwie zmienne na jednego przeciwnika.
Jedna to sam licznik animacji, a drugi to ustawienie prędkości tego licznika (SetTimer).
Chodzi o to, aby nie robić wielu takich osobnych funkcji, ale użyć jednej, która będzie zmieniała kolejność bajtu wg. indexu
(uzywam do tego celu osobnej zmiennej "indexregister1").


Napisalem jedna, indexowana funkcje dla wszystkich przeciwnikow (nie testowane, bo robie to na "brudno"),
kod jest oczywiscie mniejszy rozmiarowo niz wiele osobnych, ale tez zjada wiecej cykli cpu bo i tak musi byc wywolany wiele razy,
ale tu chodzi o sam fakt i przyklad takiego rozwiazania, wiec bede prosil o analize i jakies uwagi :) Bo zapewne da sie to samo zrobic niebo lepiej... ;)



Cytuj
IndexRegister1         DB      ; zmienne w ram

ENEMY00_Animation_Timer      DB
ENEMY01_Animation_Timer      DB
ENEMY02_Animation_Timer      DB
ENEMY03_Animation_Timer      DB
(...)
ENEMY31_Animation_Timer      DB
(...)

ENEMY00_Animation_SetTimer   DB
ENEMY01_Animation_SetTimer   DB
ENEMY02_Animation_SetTimer   DB
ENEMY03_Animation_SetTimer   DB
(...)
ENEMY31_Animation_SetTimer   DB
(...)

Przykladowy, prosty kod sterujacy licznikiem animacji, osobny dla kazdego przeciwnika:

Cytuj

   LD A,(ENEMY00_Animation_Timer)
   LD B,A
   LD A,(ENEMY00_Animation_SetTimer)
   ADD A,B
   LD (ENEMY00_Animation_Timer),A

...

   LD A,(ENEMY01_Animation_Timer)
   LD B,A
   LD A,(ENEMY01_Animation_SetTimer)
   ADD A,B
   LD (ENEMY01_Animation_Timer),A

(...)


Teraz proba indexowania tych zmiennych o index zawarty w zmiennej IndexRegister1:

Cytuj

TimerAnimacji:

   LD HL,ENEMY00_Animation_Timer
   LD A,(IndexRegister1)
   LD E,A
   ADD HL,DE
   LD A,(HL)

   LD B,A               ; Teraz w B mam adres ENEMY00_Animation_Timer zwiekszony o IndexRegister1

   LD HL,ENEMY00_Animation_SetTimer   ; Podobnie jak wyzej ale indexuje zmienna SetTimer
   LD A,(IndexRegister1)
   LD E,A
   ADD HL,DE
   LD A,(HL)

   LD C,A               ; Teraz w C mam adres ENEMY00_Animation_SetTimer zwiekszony o IndexRegister1

   ADD C,B               ; Dodaje SetTimer do Timer

   LD HL,ENEMY00_Animation_Timer      ;EDIT: tu moge na poczatku zachowac wynik HL do np. IX/IY i teraz nie wyliczac znowu tylko przeniesc do HL...
   LD A,(IndexRegister1)
   LD E,A
   ADD HL,DE            ; Teraz w B mam 'znowu" bajt ENEMY00_Animation_Timer zwiekszony o IndexRegister1
   LD A,C               ; Wynik dodawania mialem zachowany w C wiec musze go przeniesc do A aby zapisac pod adres wskazany w HL
   LD (HL),A            ; Zapisz wynik pod adres bajtu ENEMY00_Animation_Timer zwiekszonego o adres indexu czyli odpowiedniego Enemy..

   RET


Teraz wystarczy ustawic index o numer danego przeciwnika i wywolac:

Cytuj
ld d,0   ; oczywiscie d musze miec wyzerowane

   LD A,31               ; wywolaj kod licznika dla ENEMY31
   LD (IndexRegister1),A
   CALL TimerAnimacji
« Ostatnia zmiana: 2022.04.21, 11:37:42 wysłana przez siudym »

matofesi

  • *****
  • Wiadomości: 1938
  • Miejsce pobytu:
    Toruń/Poland
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #61 dnia: 2022.04.21, 11:45:33 »
Tak na szybko... nie ma opcode'u "add c,b" ;) Dodawać można tylko do akumulatora.

Twój przykład zrobiłbym w taki sposób (bez nadmiernej optymalizacji):
TimerAnimacji
        ld hl,ENEMY0_Animation_Timer ; adres pierwszego bloku
        add hl,de ; "indeksowanie"
        push hl ; zapamiętujemy na później
        ld b,(hl) ; pobieramy dane
        ld hl,ENEMY00_AnimationSetTimer ; drugi blok
        add hl,de ; "indeksowanie"
        ld a,(hl) ; pobieramy dane
        add a,b ; dodajemy
        pop hl ; odtwarzamy pierwszy adres po "indeksowaniu"
        ld (hl),a ; zapisujemy dane
        ret

I wywołanie:
        ld de,31 ; indeks ładujemy do de (albo raz 0 do d a potem indeks do e)
        call TimerAnimacji

siudym

  • **
  • Wiadomości: 61
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #62 dnia: 2022.04.21, 15:56:28 »
Racja, mozna wykonywac jedynie ADD A,r...
Teraz widze bez sensu dodawalem IndexRegister 3x do DE skoro jest zawsze taki sam.
Co do uzycia zmiennej zamiast od razu przed CALL ustawic wartosc indexu do DE, to chodzi o to, ze mam do przepisania kod z 6502, w ktorym uzywalem np. 3 rozne indexy (np. zwiekszany o jeden, kolejny co cztery bajty a inny co 16) dlatego nie uzylem od razu DE przed CALL do wspolnej funkcji.

Wracajac do pomyslu, aby zachowac zawartosc HL w rejestracy IX/IY to widze, ze nie da sie wykonac LD IX,HL, ale mozna by zrobic backup uzywajac stosu aby w pozniejszym kodzie uzyc, np.:

   PUSH HL        ; przenies HL do IX za pomoca stosu
   POP IX

(...)

   PUSH IX           ; odczytaj zachowany HL "w IX" znowu do HL za pomoca stosu..
   POP HL

Tez powinno byc ok?
« Ostatnia zmiana: 2022.04.21, 17:48:25 wysłana przez siudym »

matofesi

  • *****
  • Wiadomości: 1938
  • Miejsce pobytu:
    Toruń/Poland
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #63 dnia: 2022.04.22, 09:01:07 »
Tak - PUSH/POP będzie OK poza faktem, że przerzuca dane przez stos.
Poza tym wszystkie rozkazy i IX/IY są dłuższe o bajt prefiksu (oraz ewentualny indeks) oraz wolniejsze o 4-12 taktów zależnie od rozkazu więc jeśli koniecznie nie jest ci potrzebne to lepiej jest jednak nie używać rejestrów indeksowych.

trojacek

  • *****
  • Wiadomości: 6417
  • Miejsce pobytu:
    Warszawa
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #64 dnia: 2022.04.22, 09:09:19 »
Dokładnie.
Czasami bardziej się opłaca korzystać z drugiego zestawu rejestrów (EXX).

matofesi

  • *****
  • Wiadomości: 1938
  • Miejsce pobytu:
    Toruń/Poland
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #65 dnia: 2022.04.22, 09:45:40 »
@trojacek owszem pod warunkiem, że nie chcesz przechować czegoś czego musisz użyć - EXX się do tego nie nadaje.

W ogóle obserwując stawiane tu problemy mam wrażenie, że 6502 i Z80 to są dwie prawie całkowicie różne filozofie i portowanie mechanizmów z jednego do drugiego na siłę nie jest najlepszym pomysłem. 6502 jest bardzo wydajny przy mnóstwie trybów adresowania i stosunkowo krótkiej liście rozkazów, Z80 ma więcej rejestrów różnych dziwnych rozkazów za to znacznie mniej trybów adresowania. Trzeba się chyba dobrze nauczyć obu żeby portowany z jednego do drugiego kod nie był kulawy i średnio wydajny ;)

Ale z drugiej strony może ja po prostu jestem za bardzo skrzywiony przez lata pisania na Z80 ;)

trojacek

  • *****
  • Wiadomości: 6417
  • Miejsce pobytu:
    Warszawa
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #66 dnia: 2022.04.22, 13:25:58 »
@trojacek owszem pod warunkiem, że nie chcesz przechować czegoś czego musisz użyć - EXX się do tego nie nadaje.

Dlatego napisałem, że czasami. Akurat nie mam na tyle czasu, by rozkminiać ten ostatni zadany problem, więc nie wiem, czy akurat tu się to przyda, czy raczej jednak nie.

Cytuj
Ale z drugiej strony może ja po prostu jestem za bardzo skrzywiony przez lata pisania na Z80 ;)

Tak, jesteś - podobnie jak wielu z nas na tym forum, nawet nie mając tego świadomości :)
Bo domyślam się, że nie wszyscy fani Spectrum mieli okazję i chęć zgłębiać architekturę i język maszynowy innych procesorów, zwłaszcza motopochodnych.

I tak, masz racje:
Cytuj
[...]Trzeba się chyba dobrze nauczyć obu żeby portowany z jednego do drugiego kod nie był kulawy i średnio wydajny ;)

Bo moim zdaniem tłumaczenie rozkaz po rozkazie nie ma sensu, podobnie jak tłumaczenia z jednego języka (takiego ludzkiego) na inny (ludzki) - bo przekład wyłoży się np. na idiomach czy zwrotach potocznych.
Kluczem do sukcesu jest cofnięcie się od zastanej implementacji do definicji problemu i potem analiza, jak go zaimplementować z użyciem specyficznej architektury danego procesora.

siudym

  • **
  • Wiadomości: 61
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #67 dnia: 2022.04.25, 10:49:07 »
W ogóle obserwując stawiane tu problemy mam wrażenie, że 6502 i Z80 to są dwie prawie całkowicie różne filozofie i portowanie mechanizmów z jednego do drugiego na siłę nie jest najlepszym pomysłem

No właśnie ostatnio zauważyłem, że lepiej nie próbować czegoś zastąpić 1:1 z 6502 na Z80, tylko napisać "od nowa" wszystko aby tylko osiągnąć ten sam cel.
Co ciekawe, ostatnio miałem epizod z nauką MC68K i tam poznikały wszystkie problemy jakie miałem w przypadku 6502->Z80 :) Świetny procesor, kiedyś czytałem, że jest chyba najprzystępniejszy do nauki ASM i chyba faktycznie tak jest.