Inkrementacja i dekrementacja liczb wielobajtowych
From Atariki
Wersja z dnia 04:34, 5 wrz 2011 KMK (Dyskusja | wkład) ← Previous diff |
Wersja z dnia 05:09, 5 wrz 2011 KMK (Dyskusja | wkład) (+ propozycja mono) Next diff → |
||
Linia 4: | Linia 4: | ||
<pre> | <pre> | ||
- | inc zmienna | + | inc zmienna |
- | bne omin | + | bne koniec |
- | inc zmienna+1 | + | inc zmienna+1 |
- | omin | + | koniec |
</pre> | </pre> | ||
Linia 13: | Linia 13: | ||
<pre> | <pre> | ||
- | inc zmienna | + | inc zmienna |
- | bne omin | + | bne koniec |
- | inc zmienna+1 | + | inc zmienna+1 |
- | bne omin | + | bne koniec |
- | inc zmienna+2 | + | inc zmienna+2 |
- | omin | + | koniec |
</pre> | </pre> | ||
Niektóre asemblery (np. [[MADS]]) oferują tu ułatwiające życie pseudorozkazy, odpowiednio INW oraz INL. | Niektóre asemblery (np. [[MADS]]) oferują tu ułatwiające życie pseudorozkazy, odpowiednio INW oraz INL. | ||
- | Technika ta przestaje się opłacać przy liczbach czterobajtowych; w takim przypadku lepiej jest użyć pętli oszczędzając w ten sposób 4 bajty: | + | Technika ta przestaje się opłacać już przy liczbach trzybajtowych; w takim przypadku lepiej jest użyć pętli oszczędzając w ten sposób 3 bajty (n - wielkość ''zmiennej'' w bajtach): |
<pre> | <pre> | ||
- | ldx #$fc | + | ldx #-n-1 |
- | sec | + | petla inx |
- | petla | + | beq koniec |
- | lda zmienna-$fc,x | + | inc zmienna-$0100+n,x |
- | adc #$00 | + | beq petla |
- | sta zmienna-$fc,x | + | koniec |
- | inx | + | </pre> |
- | bne petla | + | |
+ | Jeśli zaś chodzi o przeniesienie inkrementowanej wartości do innej zmiennej, pętla może wyglądać tak: | ||
+ | |||
+ | <pre> | ||
+ | ldx #-n | ||
+ | sec | ||
+ | petla lda zmienna_a-$0100+n,x | ||
+ | adc #$00 | ||
+ | sta zmienna_b-$0100+n,x | ||
+ | inx | ||
+ | bne petla | ||
</pre> | </pre> | ||
Wykorzystano tu fakt, że rozkaz ADC dodaje do akumulatora wartość podanego argumentu plus wartość znacznika C. | Wykorzystano tu fakt, że rozkaz ADC dodaje do akumulatora wartość podanego argumentu plus wartość znacznika C. | ||
- | Taka pętla nie zadziała prawidłowo, jeśli "zmienna" znajduje się na stronie zerowej. Patrz [[Ujemne indeksowanie]]. | + | Pętle nie zadziałają prawidłowo, jeśli "zmienna" znajduje się na stronie zerowej, do tego trzeba je odpowiednio zmodyfikować. Patrz [[Ujemne indeksowanie]]. |
== Dekrementacja == | == Dekrementacja == | ||
Linia 45: | Linia 55: | ||
<pre> | <pre> | ||
- | lda zmienna | + | lda zmienna |
- | bne d1 | + | bne d1 |
- | dec zmienna+1 | + | dec zmienna+1 |
- | d1 dec zmienna | + | d1 dec zmienna |
</pre> | </pre> | ||
- | To z kolei przestaje się opłacać już przy liczbach trzybajtowych; lepiej jest wtedy użyć pętli podobnej do tej powyżej wykorzystując fakt, że działanie znacznika C dla rozkazu SBC jest odwrotne niż dla ADC (SBC odejmuje od akumulatora podaną wartość zwiększoną o odwrotność znacznika C): | + | To również przestaje się opłacać już przy liczbach trzybajtowych; lepiej jest wtedy użyć pętli podobnej do tej powyżej wykorzystując fakt, że działanie znacznika C dla rozkazu SBC jest odwrotne niż dla ADC (SBC odejmuje od akumulatora podaną wartość zwiększoną o odwrotność znacznika C): |
<pre> | <pre> | ||
- | ldx #$fd | + | ldx #-n |
- | clc | + | clc |
- | petla | + | petla lda zmienna-$0100+n,x |
- | lda zmienna-$fd,x | + | sbc #$00 |
- | sbc #$00 | + | sta zmienna-$0100+n,x |
- | sta zmienna-$fd,x | + | inx |
- | inx | + | bne petla |
- | bne petla | + | |
</pre> | </pre> | ||
Wersja z dnia 05:09, 5 wrz 2011
Inkrementacja
Sekwencja rozkazów zwiększająca wartość dwubajtowej liczby całkowitej o 1 jest powszechnie znana i często używana:
inc zmienna bne koniec inc zmienna+1 koniec
Sekwencja inkrementująca liczbę trzybajtową wygląda analogicznie:
inc zmienna bne koniec inc zmienna+1 bne koniec inc zmienna+2 koniec
Niektóre asemblery (np. MADS) oferują tu ułatwiające życie pseudorozkazy, odpowiednio INW oraz INL.
Technika ta przestaje się opłacać już przy liczbach trzybajtowych; w takim przypadku lepiej jest użyć pętli oszczędzając w ten sposób 3 bajty (n - wielkość zmiennej w bajtach):
ldx #-n-1 petla inx beq koniec inc zmienna-$0100+n,x beq petla koniec
Jeśli zaś chodzi o przeniesienie inkrementowanej wartości do innej zmiennej, pętla może wyglądać tak:
ldx #-n sec petla lda zmienna_a-$0100+n,x adc #$00 sta zmienna_b-$0100+n,x inx bne petla
Wykorzystano tu fakt, że rozkaz ADC dodaje do akumulatora wartość podanego argumentu plus wartość znacznika C.
Pętle nie zadziałają prawidłowo, jeśli "zmienna" znajduje się na stronie zerowej, do tego trzeba je odpowiednio zmodyfikować. Patrz Ujemne indeksowanie.
Dekrementacja
Dekrementacja dwubajtowej liczby całkowitej jest nieco bardziej kłopotliwa, niż inkrementacja takowej:
lda zmienna bne d1 dec zmienna+1 d1 dec zmienna
To również przestaje się opłacać już przy liczbach trzybajtowych; lepiej jest wtedy użyć pętli podobnej do tej powyżej wykorzystując fakt, że działanie znacznika C dla rozkazu SBC jest odwrotne niż dla ADC (SBC odejmuje od akumulatora podaną wartość zwiększoną o odwrotność znacznika C):
ldx #-n clc petla lda zmienna-$0100+n,x sbc #$00 sta zmienna-$0100+n,x inx bne petla
Dla liczby trzybajtowej (jakiej dotyczy przykład) zysk wynosi 5 bajtów, a dla czterobajtowej - aż 13. Jak powyżej, jeśli "zmienna" jest na stronie zerowej, pętlę trzeba odpowiednio zmodyfikować.