Wielobajtowe NOP-y
From Atariki
Wersja z dnia 09:31, 6 maj 2008 KMK (Dyskusja | wkład) (Programowanie: Techniki skracania kodu moved to Użycie rozkazu BIT jako wielobajtowego NOP-a) ← Previous diff |
Wersja z dnia 15:15, 6 maj 2008 KMK (Dyskusja | wkład) (edit) Next diff → |
||
Linia 1: | Linia 1: | ||
- | Na stronie znajdują się metody pozwalające skrócić kod, często kosztem szybkości działania programu. | + | 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. |
- | == Użycie rozkazu BIT do zamaskowania innego rozkazu == | + | 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: |
- | + | ||
- | 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: | + | |
<pre> | <pre> | ||
Linia 27: | Linia 25: | ||
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. | 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)'''. | + | '''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. |
Wersja z dnia 15:15, 6 maj 2008
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 ; BEQ _1 LDA #dana2 _2 ...
można zapisać tak:
LDA zmienna CMP dana BNE _1+1 LDA #dana1 .BYTE $2C _1 LDA #$xx ; $xx - dana2