Wielobajtowe NOP-y

From Atariki

(Różnice między wersjami)
Jump to: navigation, search
Wersja z dnia 22:07, 27 gru 2007
KMK (Dyskusja | wkład)
(Użycie rozkazu BIT do zamaskowania innego rozkazu)
← Previous diff
Aktualna wersja
KMK (Dyskusja | wkład)

Linia 1: Linia 1:
-Na stronie znajdują się metody pozwalające skrócić kod, często kosztem szybkości działania programu.+== Rozkaz BIT ==
-== Użycie rozkazu BIT do zamaskowania innego rozkazu ==+Rozkazy ''BIT abs'' (trzybajtowy: $2C ll hh) i ''BIT zp'' (dwubajtowy: $24 hh) nie modyfikują zawartości pamięci ani rejestrów (z wyjątkiem rejestru statusu 6502), więc mogą być użyte jako legalne, wielobajtowe NOP-y do zamaskowania (przeskoczenia) dowolnego rozkazu jedno- lub dwubajtowego.
-Rozkaz ''BIT abs'' (trzybajtowy: $2C ll hh) nie modyfikuje zawartości rejestrów (z wyjątkiem rejestru statusu 6502), więc może być użyty jako legalny, trzybajtowy NOP do zamaskowania (przeskoczenia) dowolnego rozkazu dwubajtowego. Na ogół maskowane są w ten sposób rozkazy ładujące ośmiobitowe stałe do rejestrów. Technikę tę stosuje się na ogół w podprogramach, w których kod główny spełnia różne funkcje w zależności od stałego parametry przekazanego w akumulatorze, a punkty wejścia wywoływane są za pośrednictwem jakiejś tablicy adresów. Zamiast:+Na ogół maskowane są w ten sposób rozkazy ładujące ośmiobitowe stałe do rejestrów. Technikę tę stosuje się najczęściej w podprogramach, w których kod główny spełnia różne funkcje w zależności od stałego parametru przekazanego w akumulatorze, a punkty wejścia wywoływane są za pośrednictwem jakiejś tablicy adresów. Zamiast:
<pre> <pre>
Linia 25: Linia 25:
</pre> </pre>
-Dzięki pozbyciu się skoków w tym przykładzie zaoszczędzono dwa bajty. Z tego prostego triku nagminnie korzysta kod [[SpartaDOS X]].+Dzięki pozbyciu się skoków w tym przykładzie zaoszczędzono dwa bajty. Z tego prostego triku nagminnie korzysta kod [[SpartaDOS X]] celem zaoszczędzenia pamięci RAM.
-''Stosując ten trik trzeba pamiętać, że maskowany rozkaz wraz z argumentem stanowi adres dla rozkazu BIT, a ten generuje odczyt. Może to spowodować kłopoty w przypadku trafienia w rejestr sprzętowy wrażliwy na odczyt. Takie mogą się znajdować na stronie $D5 (obszar przeznaczony dla kartridży)''.+'''Stosując ten trik trzeba pamiętać, że maskowany rozkaz wraz z argumentem stanowi adres dla rozkazu BIT, a ten generuje odczyt. Np. użyta w powyższym przykładzie sekwencja ''.BYTE $2C / LDA #$FF'' ($2C, $A9, $FF) w przypadku wykonania w całości zostanie zinterpretowana przez procesor jako ''BIT $FFA9'' powodując odczytanie bajtu spod wymienionego adresu. W przypadku trafienia w ten sposób w rejestr sprzętowy wrażliwy na odczyt będą kłopoty. Takie rejestry mogą się znajdować na stronie $D5 (obszar przeznaczony dla kartridży)'''. Z tego względu trzeba unikać maskowania rozkazów, których drugi bajt (argument) ma wartość z zakresu $D0-$D7, zwłaszcza $D1 i $D5.
Inne zastosowanie to załadowanie rejestru stałą w zależności od zmiennego parametru (gdy nie opłaca się zastosowanie tabeli). Przykład w pseudokodzie: ''IF zmienna=dana THEN A=dana1 ELSE A=dana2'' - badane mogą być inne relacje zmienna - dana. Inne zastosowanie to załadowanie rejestru stałą w zależności od zmiennego parametru (gdy nie opłaca się zastosowanie tabeli). Przykład w pseudokodzie: ''IF zmienna=dana THEN A=dana1 ELSE A=dana2'' - badane mogą być inne relacje zmienna - dana.
Linia 38: Linia 38:
BNE _1 BNE _1
LDA #dana1 LDA #dana1
- BNE _2 ; BEQ+ BNE _2 ; lub BEQ
_1 LDA #dana2 _1 LDA #dana2
_2 ... _2 ...
Linia 47: Linia 47:
LDA zmienna LDA zmienna
CMP dana CMP dana
- BNE _1+1+ BNE _1
LDA #dana1 LDA #dana1
-_1 BIT $xxA9 ; $xx - dana2, $A9 kod rozkazu LDA+ .BYTE $2C
 +_1 LDA #dana2
 +</pre>
 + 
 +== Rozkazy odgałęzień ==
 + 
 +W rzadkich przypadkach, kiedy w danym miejscu programu konkretne znaczniki CPU są ustalone, można w opisany powyżej sposób użyć rozkazu odgałęzienia Bxx zamiast rozkazu ''BIT zp'' do zamaskowania następującego rozkazu jednobajtowego. Zysk polega na zaoszczędzeniu 1 cyklu pracy CPU (przez uniknięcie zbędnego dostępu do pamięci) oraz uniknięciu modyfikacji stanu jego rejestrów (poza, oczywiście, PC).
 + 
 +Zamiast:
 + 
 +<pre>
 +ON SEC
 + .BYTE $24 ;BIT
 +OFF CLC
 +</pre>
 + 
 +można napisać:
 + 
 +<pre>
 +ON SEC
 + .BYTE $90 ;BCC
 +OFF CLC
</pre> </pre>
[[Kategoria:Niezbędnik kodera]] [[Kategoria:Niezbędnik kodera]]

Aktualna wersja

Rozkaz BIT

Rozkazy BIT abs (trzybajtowy: $2C ll hh) i BIT zp (dwubajtowy: $24 hh) nie modyfikują zawartości pamięci ani rejestrów (z wyjątkiem rejestru statusu 6502), więc mogą być użyte jako legalne, wielobajtowe NOP-y do zamaskowania (przeskoczenia) dowolnego rozkazu jedno- lub dwubajtowego.

Na ogół maskowane są w ten sposób rozkazy ładujące ośmiobitowe stałe do rejestrów. Technikę tę stosuje się najczęściej w podprogramach, w których kod główny spełnia różne funkcje w zależności od stałego parametru przekazanego w akumulatorze, a punkty wejścia wywoływane są za pośrednictwem jakiejś tablicy adresów. Zamiast:

E0   LDA #$00
     BEQ EXEC
E1   LDA #$01
     BNE EXEC
EFF  LDA #$FF
EXEC ...

piszemy:

E0   LDA #$00
     .BYTE $2C
E1   LDA #$01
     .BYTE $2C
EFF  LDA #$FF
EXEC ...

Dzięki pozbyciu się skoków w tym przykładzie zaoszczędzono dwa bajty. Z tego prostego triku nagminnie korzysta kod SpartaDOS X celem zaoszczędzenia pamięci RAM.

Stosując ten trik trzeba pamiętać, że maskowany rozkaz wraz z argumentem stanowi adres dla rozkazu BIT, a ten generuje odczyt. Np. użyta w powyższym przykładzie sekwencja .BYTE $2C / LDA #$FF ($2C, $A9, $FF) w przypadku wykonania w całości zostanie zinterpretowana przez procesor jako BIT $FFA9 powodując odczytanie bajtu spod wymienionego adresu. W przypadku trafienia w ten sposób w rejestr sprzętowy wrażliwy na odczyt będą kłopoty. Takie rejestry mogą się znajdować na stronie $D5 (obszar przeznaczony dla kartridży). Z tego względu trzeba unikać maskowania rozkazów, których drugi bajt (argument) ma wartość z zakresu $D0-$D7, zwłaszcza $D1 i $D5.

Inne zastosowanie to załadowanie rejestru stałą w zależności od zmiennego parametru (gdy nie opłaca się zastosowanie tabeli). Przykład w pseudokodzie: IF zmienna=dana THEN A=dana1 ELSE A=dana2 - badane mogą być inne relacje zmienna - dana.

Zamiast:

     LDA zmienna
     CMP dana
     BNE _1
     LDA #dana1
     BNE _2      ; lub BEQ
_1   LDA #dana2
_2   ...

można zapisać tak:

     LDA zmienna
     CMP dana
     BNE _1
     LDA #dana1
     .BYTE $2C
_1   LDA #dana2

Rozkazy odgałęzień

W rzadkich przypadkach, kiedy w danym miejscu programu konkretne znaczniki CPU są ustalone, można w opisany powyżej sposób użyć rozkazu odgałęzienia Bxx zamiast rozkazu BIT zp do zamaskowania następującego rozkazu jednobajtowego. Zysk polega na zaoszczędzeniu 1 cyklu pracy CPU (przez uniknięcie zbędnego dostępu do pamięci) oraz uniknięciu modyfikacji stanu jego rejestrów (poza, oczywiście, PC).

Zamiast:

ON   SEC
     .BYTE $24   ;BIT
OFF  CLC

można napisać:

ON   SEC
     .BYTE $90   ;BCC
OFF  CLC
Personal tools