Programowanie mikrokontrolerów
Asembler AVR, część 2
Marcin Engel
Marcin Peczarski
22 października 2008
Mnożenie
I
Mamy następujące rozkazy mnożenia:
MUL
Rd, Rr
MULS
Rd, Rr
MULSU
Rd, Rr
FMUL
Rd, Rr
FMULS
Rd, Rr
FMULSU Rd, Rr
I
Każdy z rozkazów mnoży dwie 8-bitowe wartości, umieszczone
w rejestrach, które są jego argumentami.
I
Wynik jest wartością 16-bitową i jest umieszczany w parze
rejestrów R1:R0
Mnożenie całkowitoliczbowe
I
Rozkaz mul
I
mnoży liczby bez znaku,
I
wynik jest liczbą bez znaku,
I
argumenty mogą być w dowolnych rejestrach.
I
Rozkaz muls
I
mnoży liczby ze znakiem (U2),
I
wynik jest liczbą ze znakiem (U2),
I
argumenty mogą być w rejestrach R16, . . . , R31.
I
Rozkaz mulsu
I
mnoży liczbę ze znakiem (pierwszy argument) i liczbę bez
znaku (drugi argument),
I
wynik jest liczbą ze znakiem (U2),
I
argumenty mogą być w rejestrach R16, . . . , R23.
Liczby ułamkowe
I
W ograniczonym zakresie dostępne są operacje arytmetyczne
na liczbach ułamkowych.
I
Jeśli wartość 8-bitowa reprezentuje liczbę całkowitą x (bez
znaku lub ze znakiem), to przy jej interpretacji jako liczba
ułamkowa jest to liczba x 2
−7
.
I
Podobnie dla wartości 16-bitowej, reprezentującej liczbę
całkowitą x , jest to liczba x 2
−15
.
I
Liczba ułamkowa bez znaku jest z przedziału [0; 2).
I
Liczba ułamkowa ze znakiem jest z przedziału [−1; 1).
I
Do dodawania i odejmowania liczb ułamkowych używa się
tych samych rozkazów, co dla liczb całkowitych.
I
Do mnożenia służą rozkazy FMUL, FMULS i FMULSU.
Rozkazy mnożenia liczb ułamkowych
I
Argumenty mogą być w rejestrach R16, . . . , R23.
I
Rozkaz wykonuje tę samą operację, co odpowiedni rozkaz
mnożenia całkowitoliczbowego.
I
Wynik jest przesuwany o jeden bit w lewo.
I
Ewentualne przpepełnienie, czyli najstarszy bit jest
umieszczany w znaczniku przeniesienia C.
I
Mnożenie −1 przez −1 rozkazem FMULS daje wynik −1.
I
Przykład:
LDI
R16, Q7(-0.135)
LDI
R17, Q7(0.753)
FMULS R16, R17
Gdy nie ma rozkazu mnożenia
I
Mikrokontrolery z serii tiny nie mają rozkazu mnożenia.
I
Poniższy kod prawie dobrze emuluje rozkaz mul.
.macro emul
push
r2
push
r4
push
@0
mov
r4, @1
pop
r2
rcall
mul_emulator
pop
r4
pop
r2
.endmacro
Procedura mnożąca
mul_emulator:
push
r3
clr
r0
clr
r1
clr
r3
rjmp
mul_emulator_loop_condition
mul_emulator_loop:
lsr
r4
brcc
mul_emulator_no_addition
add
r0, r2
adc
r1, r3
mul_emulator_no_addition:
lsl
r2
rol
r3
mul_emulator_loop_condition:
tst
r4
brne
mul_emulator_loop
Procedura mnożąca, dokończenie
pop
r3
ret
Skoki bezwarunkowe
I
Skok bezpośredni
JMP
k
I
Skok względny
RJMP
k
I
Skok pośredni do adresu z rejestru Z
IJMP
I
Skok bezpośredni umożliwia skoczenie pod dowolny adres
w pamięci programu.
I
Skok względny umożliwia skoczenie pod adres odległy od
bieżącego w zakresie od −2047 do 2048 słów, ale wykonuje
się szybciej i zajmuje mniej pamięci programu.
Wołanie procedur
I
Bezpośrednie wołanie procedury
CALL
k
I
Względne wołanie procedury
RCALL k
I
Pośrednie wołanie procedury spod adresu z rejestru Z
ICALL
I
Do terminów bezpośredni i pośredni odnoszą się te same
uwagi co przy rozkazach skoków.
I
Wołanie procedury odkłada na stos adres powrotu.
I
Powrót z procedury
RET
I
Powrót z procedury (obsługi przerwania), włączenie przerwań
RETI
I
Powrót z procedury zdejmuje adres powrotu ze stosu.
Rozkazy porównujące wartości
I
Porównaj wartość rejestrów, wykonaj odejmowanie Rd - Rr,
ustaw znaczniki, ale nie zapisuj wyniku.
CP
Rd, Rr
I
Porównaj wartość rejestrów i znacznik przeniesienia C,
wykonaj odejmowanie Rd - Rr - C, ustaw znaczniki, ale nie
zapisuj wyniku.
CPC
Rd, Rr
I
Porównaj wartość rejestru ze stałą, wykonaj odejmowanie
Rd - K, ustaw znaczniki, ale nie zapisuj wyniku, tylko na
rejestrach R16, . . . , R31.
CPI
Rd, K
Rozkazy warunkowe
I
Pomiń następny rozkaz, gdy dwa rejestry mają tę samą
wartość.
CPSE Rd, Rr
I
Pomiń następny rozkaz, gdy bit w rejestrze wyzerowany.
SBRC Rr, b
I
Pomiń następny rozkaz, gdy bit w rejestrze ustawiony.
SBRS Rr, b
I
Przykład:
obliczenie wartości bezwzględnej
SBRC R16, 7
NEG
R16
Skoki warunkowe
I
Skocz, gdy bit w rejestrze stanu ustawiony.
BRBS s, k
I
Skocz, gdy bit w rejestrze stanu wyzerowany.
BRBC s, k
I
Przykład:
skocz do miejsca ETYKIETA, gdy bit Z (zero)
wyzerowany.
BRBC 1, ETYKIETA
I
Żeby nie musieć pamiętać numerów bitów w rejestrze stanu,
używamy następujących skrótów . . .
Skróty dla skoków warunkowych
rozkaz
warunek
komentarz
skoku
BREQ
Z = 1
porównywane wartości równe
wynik operacji zero
BRNE
Z = 0
porównywane wartości różne
niezerowy wynik operacji
BRCS
C = 1
wystąpiło przeniesienie
BRLO
pierwszy argument mniejszy
BRCC
C = 0
nie wystąpiło przeniesienie
BRSH
pierwszy argument większy lub równy
BRVS
V = 1
wystąpiło przepełnienie (U2)
BRVC
V = 0
nie było przepełnienia (U2)
BRMI
N = 1
wynik operacji ujemny (U2)
BRPL
N = 0
wynik operacji nieujemny (U2)
BRLT
S = 1
pierwszy argument mniejszy (U2)
BRGE
S = 0
pierwszy argument większy lub równy (U2)
Skróty dla skoków warunkowych, cd.
rozkaz
warunek
komentarz
skoku
BRHS
H = 1
wystąpiło przeniesienie z 3. bitu
BRHC
H = 0
nie było przeniesienia z 3. bitu
BRTS
T = 1
znacznik użytkownika ustawiony
BRTC
T = 0
znacznik użytkownika wyzerowany
BRIE
I = 1
przerwania włączone
BRID
I = 0
przerwania wyłączone
Skoki warunkowe, cd.
I
Przykład:
skok, gdy wartość w rejstrze R18 jest równa 0 lub
większa od 127
CPI
R18, 1
BRLT ETYKIETA
Operacje na znacznikach
I
Skopiuj bit z rejestru do znacznika użytkownika T.
BST
Rr, b
I
Skopiuj bit ze znacznika użytkownika T do rejestru.
BLD
Rd, b
I
Ustaw znacznik.
BSET s
I
Wyzeruj znacznik.
BCLR s
I
Żeby nie musieć pamiętać numerów bitów w rejestrze stanu,
używamy następujących skrótów . . .
Skróty operacji na znacznikach
rozkaz
operacja
rozkaz
operacja
SEC
C := 1
CLC
C := 0
SEZ
Z := 1
CLZ
Z := 0
SEN
N := 1
CLN
N := 0
SEV
V := 1
CLV
V := 0
SES
S := 1
CLS
S := 0
SEH
H := 1
CLH
H := 0
SET
T := 1
CLT
T := 0
SEI
I := 1
CLI
I := 0
Przesłania między rejestrami
I
Między dowolnymi dwoma rejestrami
MOV
Rd, Rr
I
Między parami rejestrów
MOVW Rd, Rr
I
Przykład:
przesłanie wyniku mnożenia do pary rejestrów
R17:R16
MOVW R17:R16, R1:R0
Adresowanie natychmiastowe
I
Inicjacja rejestru dowolną stałą, tylko rejestry R16, . . . , R31,
nie modyfikuje znaczników.
LDI
Rd, K
I
Wyzerowanie dowolnego rejestru, modyfikuje znaczniki.
CLR
Rd
; inny zapis dla EOR Rd, Rd
I
Ustawienie wszystkich bitów na 1, tylko rejestry R16, . . . ,
R31, nie modyfikuje znaczników.
SER
Rd
; inny zapis dla LDI Rd, $FF
Adresowanie bezpośrednie i pośrednie
I
Ładowanie rejestru wartością z pamięci danych
LDS
Rd, k
I
Zapisanie wartości z rejestru do pamięci danych
STS
k, Rr
I
Ładowanie rejestru wartością z pamięci danych, adres
w rejestrze X, Y lub Z
LD
Rd, Rxyz
I
Zapisanie wartości z rejestru do pamięci danych, adres
w rejestrze X, Y lub Z
ST
Rxyz, Rr
Adresowanie pośrednie z postinkrementacją
i predekrementacją
I
Ładowanie rejestru wartością z pamięci danych, adres
w rejestrze X, Y lub Z, który jest następnie zwiększany o 1.
LD
Rd, Rxyz+
I
Zapisanie wartości z rejestru do pamięci danych, adres
w rejestrze X, Y lub Z, który jest następnie zwiększany o 1.
ST
Rxyz+, Rr
I
Ładowanie rejestru wartością z pamięci danych, adres
w rejestrze X, Y lub Z, który jest uprzednio zmniejszany o 1.
LD
Rd, -Rxyz
I
Zapisanie wartości z rejestru do pamięci danych, adres
w rejestrze X, Y lub Z, który jest uprzednio zmniejszany o 1.
ST
-Rxyz, Rr
Adresowanie pośrednie z przemieszczeniem
I
Ładowanie rejestru wartością z pamięci danych, adres
w rejestrze Y lub Z plus przemieszczenie o wartości od 0 do 63.
LDD
Rd, Ryz+q
I
Zapisanie wartości z rejestru do pamięci danych, adres
w rejestrze Y lub Z plus przemieszczenie o wartości od 0 do 63.
STD
Ryz+q, Rr
Adresowanie pamięci programu
I
Załadowanie do rejestru bajtu z pamięci programu o adresie
w rejestrze Z
LPM
Rd, Z
I
Załadowanie do rejestru bajtu z pamięci programu o adresie
w rejestrze Z, następnie zwiększenie Z
LPM
Rd, Z+
I
Zapisanie zawartości pary rejestrów R1:R0 w pamięci
programu o adresie w rejestrze Z
SPM
I
Rozkaz LPM adresuje bajty.
I
Rozkaz SPM adresuje słowa.
I
Rozkaz SPM umożliwia samomodyfikowanie się programu. Aby
poznać dokładnie jego działanie zajrzyj do dokumentacji.
Adresowanie pamięci programu
I
Przykład:
załadowanie do rejestru Z 16-bitowej wartości
z pamięci programu
LDI
ZL, LOW(VALUE << 1)
LDI
ZH, HIGH(VALUE << 1)
LPM
R16, Z+
LPM
R17, Z
MOVW ZH:ZL, R17:R16
.CSEG
VALUE:
.DW
3456
Operacje na rejestrach we-wy
I
Odczyt
IN
Rd, A
I
Zapis
OUT
A, Rr
I
Przykład:
odczyt rejestru stanu do rejestru R16
IN
R16, SREG
I
Wyzerowanie bitu, tylko rejestry o adresach od $00 do $1F
CBI
A, b
I
Ustawienie bitu, tylko rejestry o adresach od $00 do $1F
SBI
A, b
I
Przykład:
ustawienie stanu wysokiego na nodze PA3 (musi
być skonfigurowana jako wyjście)
SBI
PORTA, PA3
Operacje na rejestrach we-wy
I
Pominięcie następnej instrukcji, gdy bit wyzerowany
SBIC A, b
I
Pominięcie następnej instrukcji, gdy bit ustawiony
SBIS A, b
I
Przykład:
aktywne oczekiwanie na zmianę stanu nogi PA2
z wysokiego na niski (noga PA2 musi być skonfigurowana jako
wejście)
CZEKAJ:
SBIC PINA, PA2
RJMP CZEKAJ
Operacje stosowe
I
Odłożenie na stos zawartości rejestru
PUSH Rr
I
Zdjęcie wartości ze stosu
POP
Rd
I
Przykład:
odłożenie na stos rejestru stanu na początku
procedury obsługi przerwania
PUSH R16
IN
R16, SREG
PUSH R16
I
Przykład:
odtworzenie rejestru stanu na końcu procedury
obsługi przerwania
POP
R16
OUT
SREG, R16
POP
R16
Pozostałe rozkazy
I
Nic nie rób.
NOP
I
Zresetuj układ nadzorujący (watchdog).
WDR
I
Zaśnij.
SLEEP
I
Pułapka używana przy debugowaniu w układzie (patrz JTAG
lub dW).
BREAK